diff --git a/.github/containers/Dockerfile b/.github/containers/Dockerfile index 207332f3c0..3f370a4a45 100644 --- a/.github/containers/Dockerfile +++ b/.github/containers/Dockerfile @@ -115,7 +115,7 @@ RUN mv "${HOME}/.local/bin/python3.11" "${HOME}/.local/bin/pypy3.11" && \ mv "${HOME}/.local/bin/python3.10" "${HOME}/.local/bin/pypy3.10" # Install CPython versions -RUN uv python install -f cp3.14 cp3.13 cp3.12 cp3.11 cp3.10 cp3.9 cp3.8 +RUN uv python install -f cp3.14 cp3.14t cp3.13 cp3.12 cp3.11 cp3.10 cp3.9 cp3.8 # Set default Python version to CPython 3.13 RUN uv python install -f --default cp3.13 diff --git a/.github/workflows/build-ci-image.yml b/.github/workflows/build-ci-image.yml index 8d56ad35c9..ab183f48a2 100644 --- a/.github/workflows/build-ci-image.yml +++ b/.github/workflows/build-ci-image.yml @@ -97,7 +97,7 @@ jobs: touch "${{ runner.temp }}/digests/${digest#sha256:}" - name: Upload Digest - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 with: name: digests-${{ matrix.cache_tag }} path: ${{ runner.temp }}/digests/* @@ -114,7 +114,7 @@ jobs: steps: - name: Download Digests - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # 5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # 6.0.0 with: path: ${{ runner.temp }}/digests pattern: digests-* diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2337ee8d40..ddbcd8cb2f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,8 +41,12 @@ jobs: os: ubuntu-24.04 - wheel: cp313-manylinux os: ubuntu-24.04 + - wheel: cp313t-manylinux + os: ubuntu-24.04 - wheel: cp314-manylinux os: ubuntu-24.04 + - wheel: cp314t-manylinux + os: ubuntu-24.04 # Linux musllibc - wheel: cp38-musllinux os: ubuntu-24.04 @@ -56,8 +60,12 @@ jobs: os: ubuntu-24.04 - wheel: cp313-musllinux os: ubuntu-24.04 + - wheel: cp313t-musllinux + os: ubuntu-24.04 - wheel: cp314-musllinux os: ubuntu-24.04 + - wheel: cp314t-musllinux + os: ubuntu-24.04 # Windows # Windows wheels won't but published until the full release announcement. # - wheel: cp313-win @@ -89,6 +97,7 @@ jobs: CIBW_ARCHS_MACOS: native CIBW_ARCHS_WINDOWS: AMD64 ARM64 CIBW_ENVIRONMENT_LINUX: "LD_LIBRARY_PATH=/opt/rh/devtoolset-8/root/usr/lib64:/opt/rh/devtoolset-8/root/usr/lib:/opt/rh/devtoolset-8/root/usr/lib64/dyninst:/opt/rh/devtoolset-8/root/usr/lib/dyninst:/usr/local/lib64:/usr/local/lib" + CIBW_ENABLE: cpython-freethreading CIBW_TEST_REQUIRES: pytest CIBW_TEST_COMMAND_LINUX: "export PYTHONPATH={project}/tests; pytest {project}/tests/agent_unittests -vx" CIBW_TEST_COMMAND_MACOS: "export PYTHONPATH={project}/tests; pytest {project}/tests/agent_unittests -vx" @@ -97,7 +106,7 @@ jobs: CIBW_TEST_SKIP: "*-win_arm64" - name: Upload Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 with: name: ${{ github.job }}-${{ matrix.wheel }} path: ./wheelhouse/*.whl @@ -134,7 +143,7 @@ jobs: openssl md5 -binary "dist/${tarball}" | xxd -p | tr -d '\n' > "dist/${md5_file}" - name: Upload Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 with: name: ${{ github.job }}-sdist path: | @@ -166,7 +175,7 @@ jobs: environment: ${{ matrix.pypi-instance }} steps: - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # 5.0.0 + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # 6.0.0 with: path: ./dist/ merge-multiple: true diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 17e65ed47a..8f74866d43 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -68,7 +68,7 @@ jobs: # Upload MegaLinter artifacts - name: Archive production artifacts if: success() || failure() - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 with: name: MegaLinter reports include-hidden-files: "true" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fc51fcb08c..0d3f853f1d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -100,7 +100,7 @@ jobs: architecture: x64 - name: Download Coverage Artifacts - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # 5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # 6.0.0 with: pattern: coverage-* path: ./ @@ -134,7 +134,7 @@ jobs: architecture: x64 - name: Download Results Artifacts - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # 5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # 6.0.0 with: pattern: results-* path: ./ @@ -196,7 +196,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -206,7 +206,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -261,7 +261,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -271,7 +271,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -283,9 +283,8 @@ jobs: windows: env: TOTAL_GROUPS: 1 - UV_PYTHON: "3.13" - UV_PYTHON_DOWNLOADS: "never" - UV_PYTHON_PREFERENCE: "only-system" + UV_PYTHON_DOWNLOADS: "manual" + UV_PYTHON_PREFERENCE: "only-managed" strategy: fail-fast: false @@ -301,15 +300,13 @@ jobs: run: | git fetch --tags origin - - name: Install Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # 6.0.0 - with: - python-version: | - 3.13 - 3.14 - - name: Install uv - uses: astral-sh/setup-uv@2ddd2b9cb38ad8efd50337e8ab201519a34c9f24 # 7.1.1 + uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # 7.1.2 + + - name: Install Python + run: | + uv python install -f 3.13 3.14 3.14t + uv python install -f --default 3.13 - name: Install Dependencies run: | @@ -333,7 +330,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -343,7 +340,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -355,9 +352,8 @@ jobs: windows_arm64: env: TOTAL_GROUPS: 1 - UV_PYTHON: "3.13" - UV_PYTHON_DOWNLOADS: "never" - UV_PYTHON_PREFERENCE: "only-system" + UV_PYTHON_DOWNLOADS: "manual" + UV_PYTHON_PREFERENCE: "only-managed" strategy: fail-fast: false @@ -373,15 +369,13 @@ jobs: run: | git fetch --tags origin - - name: Install Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # 6.0.0 - with: - python-version: | - 3.13 - 3.14 - - name: Install uv - uses: astral-sh/setup-uv@2ddd2b9cb38ad8efd50337e8ab201519a34c9f24 # 7.1.1 + uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # 7.1.2 + + - name: Install Python + run: | + uv python install -f 3.13 3.14 3.14t + uv python install -f --default 3.13 - name: Install Dependencies run: | @@ -405,7 +399,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -415,7 +409,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -475,7 +469,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -485,7 +479,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -558,7 +552,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -568,7 +562,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -638,7 +632,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -648,7 +642,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -719,7 +713,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -729,7 +723,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -804,7 +798,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -814,7 +808,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -869,7 +863,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -879,7 +873,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -959,7 +953,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -969,7 +963,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1037,7 +1031,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1047,7 +1041,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1115,7 +1109,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1125,7 +1119,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1193,7 +1187,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1203,7 +1197,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1276,7 +1270,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1286,7 +1280,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1359,7 +1353,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1369,7 +1363,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1438,7 +1432,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1448,7 +1442,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1519,7 +1513,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1529,7 +1523,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1599,7 +1593,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1609,7 +1603,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1679,7 +1673,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1689,7 +1683,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1758,7 +1752,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1768,7 +1762,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1836,7 +1830,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1846,7 +1840,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -1955,7 +1949,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -1965,7 +1959,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -2035,7 +2029,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -2045,7 +2039,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} @@ -2113,7 +2107,7 @@ jobs: FORCE_COLOR: "true" - name: Upload Coverage Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: coverage-${{ github.job }}-${{ strategy.job-index }} @@ -2123,7 +2117,7 @@ jobs: retention-days: 1 - name: Upload Results Artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 if: always() with: name: results-${{ github.job }}-${{ strategy.job-index }} diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 2016fe2121..9bf87921d7 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -61,6 +61,6 @@ jobs: - name: Upload Trivy scan results to GitHub Security tab if: ${{ github.event_name == 'schedule' }} - uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # 4.30.9 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 4.31.0 with: sarif_file: "trivy-results.sarif" diff --git a/newrelic/common/object_wrapper.py b/newrelic/common/object_wrapper.py index be8c351f4e..e535559109 100644 --- a/newrelic/common/object_wrapper.py +++ b/newrelic/common/object_wrapper.py @@ -21,11 +21,16 @@ import inspect +from newrelic.packages.wrapt import ( # noqa: F401 + BaseObjectProxy, + apply_patch, + resolve_path, + wrap_object, + wrap_object_attribute, +) from newrelic.packages.wrapt import BoundFunctionWrapper as _BoundFunctionWrapper from newrelic.packages.wrapt import CallableObjectProxy as _CallableObjectProxy from newrelic.packages.wrapt import FunctionWrapper as _FunctionWrapper -from newrelic.packages.wrapt import ObjectProxy as _ObjectProxy -from newrelic.packages.wrapt import apply_patch, resolve_path, wrap_object, wrap_object_attribute # noqa: F401 # We previously had our own pure Python implementation of the generic # object wrapper but we now defer to using the wrapt module as its C @@ -44,7 +49,7 @@ # ObjectProxy or FunctionWrapper should be used going forward. -class ObjectProxy(_ObjectProxy): +class ObjectProxy(BaseObjectProxy): """ This class provides method overrides for all object wrappers used by the agent. These methods allow attributes to be defined with the special prefix diff --git a/newrelic/core/_thread_utilization.c b/newrelic/core/_thread_utilization.c index d1d7bfacc6..18f081a5be 100644 --- a/newrelic/core/_thread_utilization.c +++ b/newrelic/core/_thread_utilization.c @@ -202,13 +202,10 @@ static PyObject *NRUtilization_new(PyTypeObject *type, return NULL; /* - * XXX Using a mutex for now just in case the calls to get - * the current thread are causing release of GIL in a - * multithreaded context. May explain why having issues with - * object referred to by weakrefs being corrupted. The GIL - * should technically be enough to protect us here. + * Using a mutex to ensure this is compatible with free threaded Python interpreters. + * In the past, this relied on the GIL for thread safety with weakrefs but that was + * not reliable enough anyway. */ - self->thread_mutex = PyThread_allocate_lock(); self->set_of_all_threads = PyDict_New(); @@ -455,6 +452,10 @@ moduleinit(void) PyModule_AddObject(module, "ThreadUtilization", (PyObject *)&NRUtilization_Type); +#ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED); +#endif + return module; } diff --git a/newrelic/hooks/database_aiomysql.py b/newrelic/hooks/database_aiomysql.py index 9a2f3d1d18..2cedcb40f9 100644 --- a/newrelic/hooks/database_aiomysql.py +++ b/newrelic/hooks/database_aiomysql.py @@ -78,6 +78,10 @@ async def _wrap_pool__acquire(wrapped, instance, args, kwargs): with FunctionTrace(name=callable_name(wrapped), terminal=True, rollup=rollup, source=wrapped): connection = await wrapped(*args, **kwargs) connection_kwargs = getattr(instance, "_conn_kwargs", {}) + + if hasattr(connection, "__wrapped__"): + return connection + return AsyncConnectionWrapper(connection, dbapi2_module, (((), connection_kwargs))) return _wrap_pool__acquire diff --git a/newrelic/hooks/database_dbapi2.py b/newrelic/hooks/database_dbapi2.py index b100fa58de..1e38880113 100644 --- a/newrelic/hooks/database_dbapi2.py +++ b/newrelic/hooks/database_dbapi2.py @@ -89,6 +89,9 @@ def callproc(self, procname, parameters=DEFAULT): else: return self.__wrapped__.callproc(procname) + def __iter__(self): + return iter(self.__wrapped__) + class ConnectionWrapper(ObjectProxy): __cursor_wrapper__ = CursorWrapper diff --git a/newrelic/hooks/external_botocore.py b/newrelic/hooks/external_botocore.py index d8c18b49db..28bd8ffb13 100644 --- a/newrelic/hooks/external_botocore.py +++ b/newrelic/hooks/external_botocore.py @@ -1451,6 +1451,9 @@ def wrap_serialize_to_request(wrapped, instance, args, kwargs): ("kinesis", "untag_resource"): aws_function_trace( "untag_resource", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis" ), + ("kinesis", "update_max_record_size"): aws_function_trace( + "update_max_record_size", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis" + ), ("kinesis", "update_shard_count"): aws_function_trace( "update_shard_count", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis" ), diff --git a/newrelic/packages/requirements.txt b/newrelic/packages/requirements.txt index 5d8c59db2e..b3820134f3 100644 --- a/newrelic/packages/requirements.txt +++ b/newrelic/packages/requirements.txt @@ -4,5 +4,5 @@ # to the New Relic Python Agent's dependencies in newrelic/packages/. opentelemetry_proto==1.32.1 urllib3==1.26.19 -wrapt==1.16.0 +wrapt==2.0.0 asgiref==3.6.0 # We only vendor asgiref.compatibility.py diff --git a/newrelic/packages/wrapt/__init__.py b/newrelic/packages/wrapt/__init__.py index ed31a94313..3735818c61 100644 --- a/newrelic/packages/wrapt/__init__.py +++ b/newrelic/packages/wrapt/__init__.py @@ -1,30 +1,63 @@ -__version_info__ = ('1', '16', '0') -__version__ = '.'.join(__version_info__) - -from .__wrapt__ import (ObjectProxy, CallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, PartialCallableObjectProxy) - -from .patches import (resolve_path, apply_patch, wrap_object, wrap_object_attribute, - function_wrapper, wrap_function_wrapper, patch_function_wrapper, - transient_function_wrapper) - +""" +Wrapt is a library for decorators, wrappers and monkey patching. +""" + +__version_info__ = ("2", "0", "0") +__version__ = ".".join(__version_info__) + +from .__wrapt__ import ( + BaseObjectProxy, + BoundFunctionWrapper, + CallableObjectProxy, + FunctionWrapper, + PartialCallableObjectProxy, + partial, +) +from .decorators import AdapterFactory, adapter_factory, decorator, synchronized +from .importer import ( + discover_post_import_hooks, + notify_module_loaded, + register_post_import_hook, + when_imported, +) +from .patches import ( + apply_patch, + function_wrapper, + patch_function_wrapper, + resolve_path, + transient_function_wrapper, + wrap_function_wrapper, + wrap_object, + wrap_object_attribute, +) +from .proxies import AutoObjectProxy, LazyObjectProxy, ObjectProxy, lazy_import from .weakrefs import WeakFunctionProxy -from .decorators import (adapter_factory, AdapterFactory, decorator, - synchronized) - -from .importer import (register_post_import_hook, when_imported, - notify_module_loaded, discover_post_import_hooks) - -# Import of inspect.getcallargs() included for backward compatibility. An -# implementation of this was previously bundled and made available here for -# Python <2.7. Avoid using this in future. - -from inspect import getcallargs - -# Variant of inspect.formatargspec() included here for forward compatibility. -# This is being done because Python 3.11 dropped inspect.formatargspec() but -# code for handling signature changing decorators relied on it. Exposing the -# bundled implementation here in case any user of wrapt was also needing it. - -from .arguments import formatargspec +__all__ = ( + "AutoObjectProxy", + "BaseObjectProxy", + "BoundFunctionWrapper", + "CallableObjectProxy", + "FunctionWrapper", + "LazyObjectProxy", + "ObjectProxy", + "PartialCallableObjectProxy", + "partial", + "AdapterFactory", + "adapter_factory", + "decorator", + "synchronized", + "discover_post_import_hooks", + "notify_module_loaded", + "register_post_import_hook", + "when_imported", + "apply_patch", + "function_wrapper", + "patch_function_wrapper", + "resolve_path", + "transient_function_wrapper", + "wrap_function_wrapper", + "wrap_object", + "wrap_object_attribute", + "WeakFunctionProxy", +) diff --git a/newrelic/packages/wrapt/__init__.pyi b/newrelic/packages/wrapt/__init__.pyi new file mode 100644 index 0000000000..31ba64ca10 --- /dev/null +++ b/newrelic/packages/wrapt/__init__.pyi @@ -0,0 +1,315 @@ +import sys + +if sys.version_info >= (3, 10): + from inspect import FullArgSpec + from types import ModuleType, TracebackType + from typing import ( + Any, + Callable, + Concatenate, + Generic, + ParamSpec, + Protocol, + TypeVar, + overload, + ) + + P = ParamSpec("P") + R = TypeVar("R", covariant=True) + + T = TypeVar("T", bound=Any) + + class Boolean(Protocol): + def __bool__(self) -> bool: ... + + # ObjectProxy + + class BaseObjectProxy(Generic[T]): + __wrapped__: T + def __init__(self, wrapped: T) -> None: ... + + class ObjectProxy(BaseObjectProxy[T]): + def __init__(self, wrapped: T) -> None: ... + + class AutoObjectProxy(BaseObjectProxy[T]): + def __init__(self, wrapped: T) -> None: ... + + # LazyObjectProxy + + class LazyObjectProxy(AutoObjectProxy[T]): + def __init__(self, callback: Callable[[], T] | None) -> None: ... + + @overload + def lazy_import(name: str) -> LazyObjectProxy[ModuleType]: ... + @overload + def lazy_import(name: str, attribute: str) -> LazyObjectProxy[Any]: ... + + # CallableObjectProxy + + class CallableObjectProxy(BaseObjectProxy[T]): + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + + # PartialCallableObjectProxy + + class PartialCallableObjectProxy: + def __init__( + self, func: Callable[..., Any], *args: Any, **kwargs: Any + ) -> None: ... + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + + def partial( + func: Callable[..., Any], /, *args: Any, **kwargs: Any + ) -> Callable[..., Any]: ... + + # WeakFunctionProxy + + class WeakFunctionProxy: + def __init__( + self, + wrapped: Callable[..., Any], + callback: Callable[..., Any] | None = None, + ) -> None: ... + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + + # FunctionWrapper + + WrappedFunction = Callable[P, R] + + GenericCallableWrapperFunction = Callable[ + [WrappedFunction[P, R], Any, tuple[Any, ...], dict[str, Any]], R + ] + + ClassMethodWrapperFunction = Callable[ + [type[Any], WrappedFunction[P, R], Any, tuple[Any, ...], dict[str, Any]], R + ] + + InstanceMethodWrapperFunction = Callable[ + [Any, WrappedFunction[P, R], Any, tuple[Any, ...], dict[str, Any]], R + ] + + WrapperFunction = ( + GenericCallableWrapperFunction[P, R] + | ClassMethodWrapperFunction[P, R] + | InstanceMethodWrapperFunction[P, R] + ) + + class _FunctionWrapperBase(ObjectProxy[WrappedFunction[P, R]]): + _self_instance: Any + _self_wrapper: WrapperFunction[P, R] + _self_enabled: bool | Boolean | Callable[[], bool] | None + _self_binding: str + _self_parent: Any + _self_owner: Any + + class BoundFunctionWrapper(_FunctionWrapperBase[P, R]): + def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: ... + def __get__( + self, instance: Any, owner: type[Any] | None = None + ) -> "BoundFunctionWrapper[P, R]": ... + + class FunctionWrapper(_FunctionWrapperBase[P, R]): + def __init__( + self, + wrapped: WrappedFunction[P, R], + wrapper: WrapperFunction[P, R], + enabled: bool | Boolean | Callable[[], bool] | None = None, + ) -> None: ... + def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: ... + def __get__( + self, instance: Any, owner: type[Any] | None = None + ) -> BoundFunctionWrapper[P, R]: ... + + # AdapterFactory/adapter_factory() + + class AdapterFactory(Protocol): + def __call__( + self, wrapped: Callable[..., Any] + ) -> str | FullArgSpec | Callable[..., Any]: ... + + def adapter_factory(wrapped: Callable[..., Any]) -> AdapterFactory: ... + + # decorator() + + class Descriptor(Protocol): + def __get__(self, instance: Any, owner: type[Any] | None = None) -> Any: ... + + class FunctionDecorator(Generic[P, R]): + def __call__( + self, + callable: ( + Callable[P, R] + | Callable[Concatenate[type[T], P], R] + | Callable[Concatenate[Any, P], R] + | Callable[[type[T]], R] + | Descriptor + ), + ) -> FunctionWrapper[P, R]: ... + + class PartialFunctionDecorator: + @overload + def __call__( + self, wrapper: GenericCallableWrapperFunction[P, R], / + ) -> FunctionDecorator[P, R]: ... + @overload + def __call__( + self, wrapper: ClassMethodWrapperFunction[P, R], / + ) -> FunctionDecorator[P, R]: ... + @overload + def __call__( + self, wrapper: InstanceMethodWrapperFunction[P, R], / + ) -> FunctionDecorator[P, R]: ... + + # ... Decorator applied to class type. + + @overload + def decorator(wrapper: type[T], /) -> FunctionDecorator[Any, Any]: ... + + # ... Decorator applied to function or method. + + @overload + def decorator( + wrapper: GenericCallableWrapperFunction[P, R], / + ) -> FunctionDecorator[P, R]: ... + @overload + def decorator( + wrapper: ClassMethodWrapperFunction[P, R], / + ) -> FunctionDecorator[P, R]: ... + @overload + def decorator( + wrapper: InstanceMethodWrapperFunction[P, R], / + ) -> FunctionDecorator[P, R]: ... + + # ... Positional arguments. + + @overload + def decorator( + *, + enabled: bool | Boolean | Callable[[], bool] | None = None, + adapter: str | FullArgSpec | AdapterFactory | Callable[..., Any] | None = None, + proxy: type[FunctionWrapper[Any, Any]] | None = None, + ) -> PartialFunctionDecorator: ... + + # function_wrapper() + + @overload + def function_wrapper(wrapper: type[Any]) -> FunctionDecorator[Any, Any]: ... + @overload + def function_wrapper( + wrapper: GenericCallableWrapperFunction[P, R], + ) -> FunctionDecorator[P, R]: ... + @overload + def function_wrapper( + wrapper: ClassMethodWrapperFunction[P, R], + ) -> FunctionDecorator[P, R]: ... + @overload + def function_wrapper( + wrapper: InstanceMethodWrapperFunction[P, R], + ) -> FunctionDecorator[P, R]: ... + # @overload + # def function_wrapper(wrapper: Any) -> FunctionDecorator[Any, Any]: ... # Don't use, breaks stuff. + + # wrap_function_wrapper() + + def wrap_function_wrapper( + target: ModuleType | type[Any] | Any | str, + name: str, + wrapper: WrapperFunction[P, R], + ) -> FunctionWrapper[P, R]: ... + + # patch_function_wrapper() + + class WrapperDecorator: + def __call__(self, wrapper: WrapperFunction[P, R]) -> FunctionWrapper[P, R]: ... + + def patch_function_wrapper( + target: ModuleType | type[Any] | Any | str, + name: str, + enabled: bool | Boolean | Callable[[], bool] | None = None, + ) -> WrapperDecorator: ... + + # transient_function_wrapper() + + class TransientDecorator: + def __call__( + self, wrapper: WrapperFunction[P, R] + ) -> FunctionDecorator[P, R]: ... + + def transient_function_wrapper( + target: ModuleType | type[Any] | Any | str, name: str + ) -> TransientDecorator: ... + + # resolve_path() + + def resolve_path( + target: ModuleType | type[Any] | Any | str, name: str + ) -> tuple[ModuleType | type[Any] | Any, str, Callable[..., Any]]: ... + + # apply_patch() + + def apply_patch( + parent: ModuleType | type[Any] | Any, + attribute: str, + replacement: Any, + ) -> None: ... + + # wrap_object() + + WrapperFactory = Callable[ + [Callable[..., Any], tuple[Any, ...], dict[str, Any]], type[ObjectProxy[Any]] + ] + + def wrap_object( + target: ModuleType | type[Any] | Any | str, + name: str, + factory: WrapperFactory | type[ObjectProxy[Any]], + args: tuple[Any, ...], + kwargs: dict[str, Any], + ) -> Any: ... + + # wrap_object_attribute() + + def wrap_object_attribute( + target: ModuleType | type[Any] | Any | str, + name: str, + factory: WrapperFactory | type[ObjectProxy[Any]], + args: tuple[Any, ...] = (), + kwargs: dict[str, Any] = {}, + ) -> Any: ... + + # register_post_import_hook() + + def register_post_import_hook( + hook: Callable[[ModuleType], Any] | str, name: str + ) -> None: ... + + # discover_post_import_hooks() + + def discover_post_import_hooks(group: str) -> None: ... + + # notify_module_loaded() + + def notify_module_loaded(module: ModuleType) -> None: ... + + # when_imported() + + class ImportHookDecorator: + def __call__(self, hook: Callable[[ModuleType], Any]) -> Callable[..., Any]: ... + + def when_imported(name: str) -> ImportHookDecorator: ... + + # synchronized() + + class SynchronizedObject: + def __call__(self, wrapped: Callable[P, R]) -> Callable[P, R]: ... + def __enter__(self) -> Any: ... + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> bool | None: ... + + @overload + def synchronized(wrapped: Callable[P, R]) -> Callable[P, R]: ... + @overload + def synchronized(wrapped: Any) -> SynchronizedObject: ... diff --git a/newrelic/packages/wrapt/__wrapt__.py b/newrelic/packages/wrapt/__wrapt__.py index 9933b2c972..ac8f32bb92 100644 --- a/newrelic/packages/wrapt/__wrapt__.py +++ b/newrelic/packages/wrapt/__wrapt__.py @@ -1,14 +1,44 @@ +"""This module is used to switch between C and Python implementations of the +wrappers. +""" + import os -from .wrappers import (ObjectProxy, CallableObjectProxy, - PartialCallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, _FunctionWrapperBase) +from .wrappers import BoundFunctionWrapper, CallableObjectProxy, FunctionWrapper +from .wrappers import ObjectProxy as BaseObjectProxy +from .wrappers import PartialCallableObjectProxy, _FunctionWrapperBase + +# Try to use C extensions if not disabled. + +_using_c_extension = False + +_use_extensions = not os.environ.get("WRAPT_DISABLE_EXTENSIONS") + +if _use_extensions: + try: + from ._wrappers import ( # type: ignore[no-redef,import-not-found] + BoundFunctionWrapper, + CallableObjectProxy, + FunctionWrapper, + ) + from ._wrappers import ( + ObjectProxy as BaseObjectProxy, # type: ignore[no-redef,import-not-found] + ) + from ._wrappers import ( # type: ignore[no-redef,import-not-found] + PartialCallableObjectProxy, + _FunctionWrapperBase, + ) + + _using_c_extension = True + except ImportError: + # C extensions not available, using Python implementations + pass -try: - if not os.environ.get('WRAPT_DISABLE_EXTENSIONS'): - from ._wrappers import (ObjectProxy, CallableObjectProxy, - PartialCallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, _FunctionWrapperBase) -except ImportError: - pass +def partial(*args, **kwargs): + """Create a callable object proxy with partial application of the given + arguments and keywords. This behaves the same as `functools.partial`, but + implemented using the `ObjectProxy` class to provide better support for + introspection. + """ + return PartialCallableObjectProxy(*args, **kwargs) diff --git a/newrelic/packages/wrapt/_wrappers.c b/newrelic/packages/wrapt/_wrappers.c index e0e1b5bc65..8cd2f6c28f 100644 --- a/newrelic/packages/wrapt/_wrappers.c +++ b/newrelic/packages/wrapt/_wrappers.c @@ -10,34 +10,38 @@ /* ------------------------------------------------------------------------- */ -typedef struct { - PyObject_HEAD +typedef struct +{ + PyObject_HEAD - PyObject *dict; - PyObject *wrapped; - PyObject *weakreflist; + PyObject *dict; + PyObject *wrapped; + PyObject *weakreflist; } WraptObjectProxyObject; PyTypeObject WraptObjectProxy_Type; PyTypeObject WraptCallableObjectProxy_Type; -typedef struct { - WraptObjectProxyObject object_proxy; +typedef struct +{ + WraptObjectProxyObject object_proxy; - PyObject *args; - PyObject *kwargs; + PyObject *args; + PyObject *kwargs; } WraptPartialCallableObjectProxyObject; PyTypeObject WraptPartialCallableObjectProxy_Type; -typedef struct { - WraptObjectProxyObject object_proxy; - - PyObject *instance; - PyObject *wrapper; - PyObject *enabled; - PyObject *binding; - PyObject *parent; +typedef struct +{ + WraptObjectProxyObject object_proxy; + + PyObject *instance; + PyObject *wrapper; + PyObject *enabled; + PyObject *binding; + PyObject *parent; + PyObject *owner; } WraptFunctionWrapperObject; PyTypeObject WraptFunctionWrapperBase_Type; @@ -46,3195 +50,4048 @@ PyTypeObject WraptFunctionWrapper_Type; /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_new(PyTypeObject *type, - PyObject *args, PyObject *kwds) +static int raise_uninitialized_wrapper_error(WraptObjectProxyObject *object) { - WraptObjectProxyObject *self; + // Before raising an exception we need to first check whether this is a lazy + // proxy object and attempt to intialize the wrapped object using the supplied + // callback if so. If the callback is not present then we can proceed to raise + // the exception, but if the callback is present and returns a value, we set + // that as the wrapped object and continue and return without raising an error. + + static PyObject *wrapped_str = NULL; + static PyObject *wrapped_factory_str = NULL; + static PyObject *wrapped_get_str = NULL; + + PyObject *callback = NULL; + PyObject *value = NULL; + + if (!wrapped_str) + { + wrapped_str = PyUnicode_InternFromString("__wrapped__"); + wrapped_factory_str = PyUnicode_InternFromString("__wrapped_factory__"); + wrapped_get_str = PyUnicode_InternFromString("__wrapped_get__"); + } + + // Note that we use existance of __wrapped_factory__ to gate whether we can + // attempt to initialize the wrapped object lazily, but it is __wrapped_get__ + // that we actually call to do the initialization. This is so that we can + // handle multithreading correctly by having __wrapped_get__ use a lock to + // protect against multiple threads trying to initialize the wrapped object + // at the same time. + + callback = PyObject_GenericGetAttr((PyObject *)object, wrapped_factory_str); + + if (callback) + { + if (callback != Py_None) + { + Py_DECREF(callback); + + callback = PyObject_GenericGetAttr((PyObject *)object, wrapped_get_str); + + if (!callback) + return -1; - self = (WraptObjectProxyObject *)type->tp_alloc(type, 0); + value = PyObject_CallObject(callback, NULL); - if (!self) - return NULL; + Py_DECREF(callback); - self->dict = PyDict_New(); - self->wrapped = NULL; - self->weakreflist = NULL; + if (value) + { + // We use setattr so that special dunder methods will be properly set. - return (PyObject *)self; + if (PyObject_SetAttr((PyObject *)object, wrapped_str, value) == -1) + { + Py_DECREF(value); + return -1; + } + + Py_DECREF(value); + + return 0; + } + else + { + return -1; + } + } + else + { + Py_DECREF(callback); + } + } + else + PyErr_Clear(); + + // We need to reach into the wrapt.wrappers module to get the exception + // class because the exception we need to raise needs to inherit from both + // ValueError and AttributeError and we can't do that in C code using the + // built in exception classes, or at least not easily or safely. + + PyObject *wrapt_wrappers_module = NULL; + PyObject *wrapper_not_initialized_error = NULL; + + // Import the wrapt.wrappers module and get the exception class. + // We do this fresh each time to be safe with multiple sub-interpreters. + + wrapt_wrappers_module = PyImport_ImportModule("wrapt.wrappers"); + + if (!wrapt_wrappers_module) + { + // Fallback to ValueError if import fails. + + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + + return -1; + } + + wrapper_not_initialized_error = PyObject_GetAttrString( + wrapt_wrappers_module, "WrapperNotInitializedError"); + + if (!wrapper_not_initialized_error) + { + // Fallback to ValueError if attribute lookup fails. + + Py_DECREF(wrapt_wrappers_module); + + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + + return -1; + } + + // Raise the custom exception. + + PyErr_SetString(wrapper_not_initialized_error, + "wrapper has not been initialized"); + + // Clean up references. + + Py_DECREF(wrapper_not_initialized_error); + Py_DECREF(wrapt_wrappers_module); + + return -1; } /* ------------------------------------------------------------------------- */ -static int WraptObjectProxy_raw_init(WraptObjectProxyObject *self, - PyObject *wrapped) +static PyObject *WraptObjectProxy_new(PyTypeObject *type, PyObject *args, + PyObject *kwds) { - static PyObject *module_str = NULL; - static PyObject *doc_str = NULL; + WraptObjectProxyObject *self; - PyObject *object = NULL; + self = (WraptObjectProxyObject *)type->tp_alloc(type, 0); - Py_INCREF(wrapped); - Py_XDECREF(self->wrapped); - self->wrapped = wrapped; + if (!self) + return NULL; - if (!module_str) { -#if PY_MAJOR_VERSION >= 3 - module_str = PyUnicode_InternFromString("__module__"); -#else - module_str = PyString_InternFromString("__module__"); -#endif - } + self->dict = PyDict_New(); + self->wrapped = NULL; + self->weakreflist = NULL; - if (!doc_str) { -#if PY_MAJOR_VERSION >= 3 - doc_str = PyUnicode_InternFromString("__doc__"); -#else - doc_str = PyString_InternFromString("__doc__"); -#endif - } + return (PyObject *)self; +} - object = PyObject_GetAttr(wrapped, module_str); +/* ------------------------------------------------------------------------- */ - if (object) { - if (PyDict_SetItem(self->dict, module_str, object) == -1) { - Py_DECREF(object); - return -1; - } - Py_DECREF(object); +static int WraptObjectProxy_raw_init(WraptObjectProxyObject *self, + PyObject *wrapped) +{ + static PyObject *module_str = NULL; + static PyObject *doc_str = NULL; + static PyObject *wrapped_factory_str = NULL; + + PyObject *object = NULL; + + // If wrapped is Py_None and we have a __wrapped_factory__ attribute + // then we defer initialization of the wrapped object until it is first needed. + + if (!wrapped_factory_str) + { + wrapped_factory_str = PyUnicode_InternFromString("__wrapped_factory__"); + } + + if (wrapped == Py_None) + { + PyObject *callback = NULL; + + callback = PyObject_GenericGetAttr((PyObject *)self, wrapped_factory_str); + + if (callback) + { + if (callback != Py_None) + { + Py_DECREF(callback); + return 0; + } + else + { + Py_DECREF(callback); + } } else - PyErr_Clear(); + PyErr_Clear(); + } + + Py_INCREF(wrapped); + Py_XDECREF(self->wrapped); + self->wrapped = wrapped; + + if (!module_str) + { + module_str = PyUnicode_InternFromString("__module__"); + } + + if (!doc_str) + { + doc_str = PyUnicode_InternFromString("__doc__"); + } + + object = PyObject_GetAttr(wrapped, module_str); + + if (object) + { + if (PyDict_SetItem(self->dict, module_str, object) == -1) + { + Py_DECREF(object); + return -1; + } + Py_DECREF(object); + } + else + PyErr_Clear(); - object = PyObject_GetAttr(wrapped, doc_str); + object = PyObject_GetAttr(wrapped, doc_str); - if (object) { - if (PyDict_SetItem(self->dict, doc_str, object) == -1) { - Py_DECREF(object); - return -1; - } - Py_DECREF(object); + if (object) + { + if (PyDict_SetItem(self->dict, doc_str, object) == -1) + { + Py_DECREF(object); + return -1; } - else - PyErr_Clear(); + Py_DECREF(object); + } + else + PyErr_Clear(); - return 0; + return 0; } /* ------------------------------------------------------------------------- */ -static int WraptObjectProxy_init(WraptObjectProxyObject *self, - PyObject *args, PyObject *kwds) +static int WraptObjectProxy_init(WraptObjectProxyObject *self, PyObject *args, + PyObject *kwds) { - PyObject *wrapped = NULL; + PyObject *wrapped = NULL; - static char *kwlist[] = { "wrapped", NULL }; + char *const kwlist[] = {"wrapped", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:ObjectProxy", - kwlist, &wrapped)) { - return -1; - } + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:ObjectProxy", kwlist, + &wrapped)) + { + return -1; + } - return WraptObjectProxy_raw_init(self, wrapped); + return WraptObjectProxy_raw_init(self, wrapped); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_traverse(WraptObjectProxyObject *self, - visitproc visit, void *arg) + visitproc visit, void *arg) { - Py_VISIT(self->dict); - Py_VISIT(self->wrapped); + Py_VISIT(self->dict); + Py_VISIT(self->wrapped); - return 0; + return 0; } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_clear(WraptObjectProxyObject *self) { - Py_CLEAR(self->dict); - Py_CLEAR(self->wrapped); + Py_CLEAR(self->dict); + Py_CLEAR(self->wrapped); - return 0; + return 0; } /* ------------------------------------------------------------------------- */ static void WraptObjectProxy_dealloc(WraptObjectProxyObject *self) { - PyObject_GC_UnTrack(self); + PyObject_GC_UnTrack(self); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *)self); - WraptObjectProxy_clear(self); + WraptObjectProxy_clear(self); - Py_TYPE(self)->tp_free(self); + Py_TYPE(self)->tp_free(self); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_repr(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromFormat("<%s at %p for %s at %p>", - Py_TYPE(self)->tp_name, self, - Py_TYPE(self->wrapped)->tp_name, self->wrapped); -#else - return PyString_FromFormat("<%s at %p for %s at %p>", - Py_TYPE(self)->tp_name, self, - Py_TYPE(self->wrapped)->tp_name, self->wrapped); -#endif + return PyUnicode_FromFormat("<%s at %p for %s at %p>", Py_TYPE(self)->tp_name, + self, Py_TYPE(self->wrapped)->tp_name, + self->wrapped); } /* ------------------------------------------------------------------------- */ -#if PY_MAJOR_VERSION < 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 3) -typedef long Py_hash_t; -#endif - static Py_hash_t WraptObjectProxy_hash(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PyObject_Hash(self->wrapped); + return PyObject_Hash(self->wrapped); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_str(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_Str(self->wrapped); + return PyObject_Str(self->wrapped); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_add(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_Add(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_Add(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_subtract(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } - return PyNumber_Subtract(o1, o2); + return PyNumber_Subtract(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_multiply(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - return PyNumber_Multiply(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_divide(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } - return PyNumber_Divide(o1, o2); + return PyNumber_Multiply(o1, o2); } -#endif /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_remainder(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_Remainder(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_Remainder(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_divmod(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_Divmod(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_Divmod(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_power(PyObject *o1, PyObject *o2, - PyObject *modulo) + PyObject *modulo) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_Power(o1, o2, modulo); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_Power(o1, o2, modulo); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_negative(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyNumber_Negative(self->wrapped); + return PyNumber_Negative(self->wrapped); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_positive(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyNumber_Positive(self->wrapped); + return PyNumber_Positive(self->wrapped); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_absolute(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyNumber_Absolute(self->wrapped); + return PyNumber_Absolute(self->wrapped); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_bool(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PyObject_IsTrue(self->wrapped); + return PyObject_IsTrue(self->wrapped); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_invert(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyNumber_Invert(self->wrapped); + return PyNumber_Invert(self->wrapped); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_lshift(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_Lshift(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_Lshift(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_rshift(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_Rshift(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_Rshift(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_and(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_And(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_And(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_xor(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_Xor(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_Xor(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_or(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_Or(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_int(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } - return PyNumber_Int(self->wrapped); + return PyNumber_Or(o1, o2); } -#endif /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_long(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyNumber_Long(self->wrapped); + return PyNumber_Long(self->wrapped); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_float(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyNumber_Float(self->wrapped); + return PyNumber_Float(self->wrapped); } /* ------------------------------------------------------------------------- */ -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_oct(WraptObjectProxyObject *self) +static PyObject *WraptObjectProxy_inplace_add(WraptObjectProxyObject *self, + PyObject *other) { - PyNumberMethods *nb; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if ((nb = self->wrapped->ob_type->tp_as_number) == NULL || - nb->nb_oct == NULL) { - PyErr_SetString(PyExc_TypeError, - "oct() argument can't be converted to oct"); - return NULL; - } + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; - return (*nb->nb_oct)(self->wrapped); -} -#endif + if (PyObject_HasAttrString(self->wrapped, "__iadd__")) + { + object = PyNumber_InPlaceAdd(self->wrapped, other); -/* ------------------------------------------------------------------------- */ + if (!object) + return NULL; -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_hex(WraptObjectProxyObject *self) -{ - PyNumberMethods *nb; + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_Add(self->wrapped, other); - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); return NULL; } - if ((nb = self->wrapped->ob_type->tp_as_number) == NULL || - nb->nb_hex == NULL) { - PyErr_SetString(PyExc_TypeError, - "hex() argument can't be converted to hex"); - return NULL; + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; } - return (*nb->nb_hex)(self->wrapped); + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } -#endif /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_inplace_add(WraptObjectProxyObject *self, - PyObject *other) +static PyObject *WraptObjectProxy_inplace_subtract(WraptObjectProxyObject *self, + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; - object = PyNumber_InPlaceAdd(self->wrapped, other); + if (PyObject_HasAttrString(self->wrapped, "__isub__")) + { + object = PyNumber_InPlaceSubtract(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; -} + } + else + { + PyObject *result = PyNumber_Subtract(self->wrapped, other); -/* ------------------------------------------------------------------------- */ + if (!result) + return NULL; -static PyObject *WraptObjectProxy_inplace_subtract( - WraptObjectProxyObject *self, PyObject *other) -{ - PyObject *object = NULL; + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!proxy_type) + { + Py_DECREF(proxy_type); return NULL; } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + PyObject *proxy_args = PyTuple_Pack(1, result); - object = PyNumber_InPlaceSubtract(self->wrapped, other); + Py_DECREF(result); - if (!object) - return NULL; + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } - Py_DECREF(self->wrapped); - self->wrapped = object; + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); - Py_INCREF(self); - return (PyObject *)self; + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_inplace_multiply( - WraptObjectProxyObject *self, PyObject *other) +static PyObject *WraptObjectProxy_inplace_multiply(WraptObjectProxyObject *self, + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__imul__")) + { object = PyNumber_InPlaceMultiply(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; -} + } + else + { + PyObject *result = PyNumber_Multiply(self->wrapped, other); -/* ------------------------------------------------------------------------- */ + if (!result) + return NULL; -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_inplace_divide( - WraptObjectProxyObject *self, PyObject *other) -{ - PyObject *object = NULL; + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!proxy_type) + { + Py_DECREF(proxy_type); return NULL; } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + PyObject *proxy_args = PyTuple_Pack(1, result); - object = PyNumber_InPlaceDivide(self->wrapped, other); + Py_DECREF(result); - if (!object) - return NULL; + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } - Py_DECREF(self->wrapped); - self->wrapped = object; + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); - Py_INCREF(self); - return (PyObject *)self; + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } -#endif /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_inplace_remainder( - WraptObjectProxyObject *self, PyObject *other) +static PyObject * +WraptObjectProxy_inplace_remainder(WraptObjectProxyObject *self, + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__imod__")) + { object = PyNumber_InPlaceRemainder(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; -} + } + else + { + PyObject *result = PyNumber_Remainder(self->wrapped, other); -/* ------------------------------------------------------------------------- */ + if (!result) + return NULL; -static PyObject *WraptObjectProxy_inplace_power(WraptObjectProxyObject *self, - PyObject *other, PyObject *modulo) -{ - PyObject *object = NULL; + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!proxy_type) + { + Py_DECREF(proxy_type); return NULL; } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + PyObject *proxy_args = PyTuple_Pack(1, result); - object = PyNumber_InPlacePower(self->wrapped, other, modulo); - - if (!object) - return NULL; + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_power(WraptObjectProxyObject *self, + PyObject *other, + PyObject *modulo) +{ + PyObject *object = NULL; + + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + if (PyObject_HasAttrString(self->wrapped, "__ipow__")) + { + object = PyNumber_InPlacePower(self->wrapped, other, modulo); + + if (!object) + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_Power(self->wrapped, other, modulo); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_inplace_lshift(WraptObjectProxyObject *self, - PyObject *other) + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__ilshift__")) + { object = PyNumber_InPlaceLshift(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_Lshift(self->wrapped, other); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_inplace_rshift(WraptObjectProxyObject *self, - PyObject *other) + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__irshift__")) + { object = PyNumber_InPlaceRshift(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_Rshift(self->wrapped, other); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_inplace_and(WraptObjectProxyObject *self, - PyObject *other) + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__iand__")) + { object = PyNumber_InPlaceAnd(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_And(self->wrapped, other); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_inplace_xor(WraptObjectProxyObject *self, - PyObject *other) + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__ixor__")) + { object = PyNumber_InPlaceXor(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_Xor(self->wrapped, other); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_inplace_or(WraptObjectProxyObject *self, - PyObject *other) + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__ior__")) + { object = PyNumber_InPlaceOr(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_Or(self->wrapped, other); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_floor_divide(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_FloorDivide(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_FloorDivide(o1, o2); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_true_divide(PyObject *o1, PyObject *o2) { - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } - o2 = ((WraptObjectProxyObject *)o2)->wrapped; + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; } - return PyNumber_TrueDivide(o1, o2); + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_TrueDivide(o1, o2); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_inplace_floor_divide( - WraptObjectProxyObject *self, PyObject *other) +static PyObject * +WraptObjectProxy_inplace_floor_divide(WraptObjectProxyObject *self, + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__ifloordiv__")) + { object = PyNumber_InPlaceFloorDivide(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_FloorDivide(self->wrapped, other); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_inplace_true_divide( - WraptObjectProxyObject *self, PyObject *other) +static PyObject * +WraptObjectProxy_inplace_true_divide(WraptObjectProxyObject *self, + PyObject *other) { - PyObject *object = NULL; + PyObject *object = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + if (PyObject_HasAttrString(self->wrapped, "__itruediv__")) + { object = PyNumber_InPlaceTrueDivide(self->wrapped, other); if (!object) - return NULL; + return NULL; Py_DECREF(self->wrapped); self->wrapped = object; Py_INCREF(self); return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_TrueDivide(self->wrapped, other); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_index(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; + } + + return PyNumber_Index(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_matrix_multiply(PyObject *o1, PyObject *o2) +{ + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o1)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o1) == -1) + return NULL; } - return PyNumber_Index(self->wrapped); + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + } + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + { + if (!((WraptObjectProxyObject *)o2)->wrapped) + { + if (raise_uninitialized_wrapper_error((WraptObjectProxyObject *)o2) == -1) + return NULL; + } + + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + } + + return PyNumber_MatrixMultiply(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_matrix_multiply( + WraptObjectProxyObject *self, PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + if (PyObject_HasAttrString(self->wrapped, "__imatmul__")) + { + object = PyNumber_InPlaceMatrixMultiply(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; + } + else + { + PyObject *result = PyNumber_MatrixMultiply(self->wrapped, other); + + if (!result) + return NULL; + + PyObject *proxy_type = PyObject_GetAttrString((PyObject *)self, "__object_proxy__"); + + if (!proxy_type) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_args = PyTuple_Pack(1, result); + + Py_DECREF(result); + + if (!proxy_args) + { + Py_DECREF(proxy_type); + return NULL; + } + + PyObject *proxy_instance = PyObject_Call(proxy_type, proxy_args, NULL); + + Py_DECREF(proxy_type); + Py_DECREF(proxy_args); + + return proxy_instance; + } } /* ------------------------------------------------------------------------- */ static Py_ssize_t WraptObjectProxy_length(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PyObject_Length(self->wrapped); + return PyObject_Length(self->wrapped); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_contains(WraptObjectProxyObject *self, - PyObject *value) + PyObject *value) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PySequence_Contains(self->wrapped, value); + return PySequence_Contains(self->wrapped, value); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_getitem(WraptObjectProxyObject *self, - PyObject *key) + PyObject *key) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetItem(self->wrapped, key); + return PyObject_GetItem(self->wrapped, key); } /* ------------------------------------------------------------------------- */ -static int WraptObjectProxy_setitem(WraptObjectProxyObject *self, - PyObject *key, PyObject* value) +static int WraptObjectProxy_setitem(WraptObjectProxyObject *self, PyObject *key, + PyObject *value) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - if (value == NULL) - return PyObject_DelItem(self->wrapped, key); - else - return PyObject_SetItem(self->wrapped, key, value); + if (value == NULL) + return PyObject_DelItem(self->wrapped, key); + else + return PyObject_SetItem(self->wrapped, key, value); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_self_setattr( - WraptObjectProxyObject *self, PyObject *args) +static PyObject *WraptObjectProxy_self_setattr(WraptObjectProxyObject *self, + PyObject *args) { - PyObject *name = NULL; - PyObject *value = NULL; + PyObject *name = NULL; + PyObject *value = NULL; -#if PY_MAJOR_VERSION >= 3 - if (!PyArg_ParseTuple(args, "UO:__self_setattr__", &name, &value)) - return NULL; -#else - if (!PyArg_ParseTuple(args, "SO:__self_setattr__", &name, &value)) - return NULL; -#endif + if (!PyArg_ParseTuple(args, "UO:__self_setattr__", &name, &value)) + return NULL; - if (PyObject_GenericSetAttr((PyObject *)self, name, value) != 0) { - return NULL; - } + if (PyObject_GenericSetAttr((PyObject *)self, name, value) != 0) + { + return NULL; + } - Py_INCREF(Py_None); - return Py_None; + Py_INCREF(Py_None); + return Py_None; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_dir( - WraptObjectProxyObject *self, PyObject *args) +static PyObject *WraptObjectProxy_dir(WraptObjectProxyObject *self, + PyObject *args) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_Dir(self->wrapped); + return PyObject_Dir(self->wrapped); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_enter( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptObjectProxy_enter(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - PyObject *method = NULL; - PyObject *result = NULL; + PyObject *method = NULL; + PyObject *result = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - method = PyObject_GetAttrString(self->wrapped, "__enter__"); + method = PyObject_GetAttrString(self->wrapped, "__enter__"); - if (!method) - return NULL; + if (!method) + return NULL; - result = PyObject_Call(method, args, kwds); + result = PyObject_Call(method, args, kwds); - Py_DECREF(method); + Py_DECREF(method); - return result; + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_exit( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptObjectProxy_exit(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - PyObject *method = NULL; - PyObject *result = NULL; + PyObject *method = NULL; + PyObject *result = NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - method = PyObject_GetAttrString(self->wrapped, "__exit__"); + method = PyObject_GetAttrString(self->wrapped, "__exit__"); - if (!method) - return NULL; + if (!method) + return NULL; - result = PyObject_Call(method, args, kwds); + result = PyObject_Call(method, args, kwds); - Py_DECREF(method); + Py_DECREF(method); - return result; + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_copy( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptObjectProxy_aenter(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - PyErr_SetString(PyExc_NotImplementedError, - "object proxy must define __copy__()"); + PyObject *method = NULL; + PyObject *result = NULL; + + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) + return NULL; + } + + method = PyObject_GetAttrString(self->wrapped, "__aenter__"); + if (!method) return NULL; + + result = PyObject_Call(method, args, kwds); + + Py_DECREF(method); + + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_deepcopy( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptObjectProxy_aexit(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - PyErr_SetString(PyExc_NotImplementedError, - "object proxy must define __deepcopy__()"); + PyObject *method = NULL; + PyObject *result = NULL; + + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) + return NULL; + } + + method = PyObject_GetAttrString(self->wrapped, "__aexit__"); + if (!method) return NULL; + + result = PyObject_Call(method, args, kwds); + + Py_DECREF(method); + + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_reduce( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptObjectProxy_copy(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - PyErr_SetString(PyExc_NotImplementedError, - "object proxy must define __reduce_ex__()"); + PyErr_SetString(PyExc_NotImplementedError, + "object proxy must define __copy__()"); - return NULL; + return NULL; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_reduce_ex( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptObjectProxy_deepcopy(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - PyErr_SetString(PyExc_NotImplementedError, - "object proxy must define __reduce_ex__()"); + PyErr_SetString(PyExc_NotImplementedError, + "object proxy must define __deepcopy__()"); - return NULL; + return NULL; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_reduce(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_NotImplementedError, + "object proxy must define __reduce__()"); + + return NULL; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_bytes( - WraptObjectProxyObject *self, PyObject *args) +static PyObject *WraptObjectProxy_reduce_ex(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + PyErr_SetString(PyExc_NotImplementedError, + "object proxy must define __reduce_ex__()"); + + return NULL; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_bytes(WraptObjectProxyObject *self, + PyObject *args) +{ + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_Bytes(self->wrapped); + return PyObject_Bytes(self->wrapped); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_reversed( - WraptObjectProxyObject *self, PyObject *args) +static PyObject *WraptObjectProxy_format(WraptObjectProxyObject *self, + PyObject *args) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + PyObject *format_spec = NULL; + + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } + + if (!PyArg_ParseTuple(args, "|O:format", &format_spec)) + return NULL; - return PyObject_CallFunctionObjArgs((PyObject *)&PyReversed_Type, - self->wrapped, NULL); + return PyObject_Format(self->wrapped, format_spec); } /* ------------------------------------------------------------------------- */ -#if PY_MAJOR_VERSION >= 3 -static PyObject *WraptObjectProxy_round( - WraptObjectProxyObject *self, PyObject *args) +static PyObject *WraptObjectProxy_reversed(WraptObjectProxyObject *self, + PyObject *args) { - PyObject *module = NULL; - PyObject *dict = NULL; - PyObject *round = NULL; + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) + return NULL; + } - PyObject *result = NULL; + return PyObject_CallFunctionObjArgs((PyObject *)&PyReversed_Type, + self->wrapped, NULL); +} - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_round(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) +{ + PyObject *ndigits = NULL; + + PyObject *module = NULL; + PyObject *round = NULL; + + PyObject *result = NULL; + + char *const kwlist[] = {"ndigits", NULL}; + + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - module = PyImport_ImportModule("builtins"); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:ObjectProxy", kwlist, + &ndigits)) + { + return NULL; + } - if (!module) - return NULL; + module = PyImport_ImportModule("builtins"); - dict = PyModule_GetDict(module); - round = PyDict_GetItemString(dict, "round"); + if (!module) + return NULL; - if (!round) { - Py_DECREF(module); - return NULL; - } + round = PyObject_GetAttrString(module, "round"); - Py_INCREF(round); + if (!round) + { Py_DECREF(module); + return NULL; + } - result = PyObject_CallFunctionObjArgs(round, self->wrapped, NULL); + Py_INCREF(round); + Py_DECREF(module); - Py_DECREF(round); + result = PyObject_CallFunctionObjArgs(round, self->wrapped, ndigits, NULL); - return result; + Py_DECREF(round); + + return result; } -#endif /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_complex( - WraptObjectProxyObject *self, PyObject *args) +static PyObject *WraptObjectProxy_complex(WraptObjectProxyObject *self, + PyObject *args) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_CallFunctionObjArgs((PyObject *)&PyComplex_Type, - self->wrapped, NULL); + return PyObject_CallFunctionObjArgs((PyObject *)&PyComplex_Type, + self->wrapped, NULL); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_mro_entries( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptObjectProxy_mro_entries(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + PyObject *wrapped = NULL; + PyObject *mro_entries_method = NULL; + PyObject *result = NULL; + int is_type = 0; + + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; + } + + wrapped = self->wrapped; + + // Check if wrapped is a type (class). + + is_type = PyType_Check(wrapped); + + // If wrapped is not a type and has __mro_entries__, forward to it. + + if (!is_type) + { + mro_entries_method = PyObject_GetAttrString(wrapped, "__mro_entries__"); + + if (mro_entries_method) + { + // Call wrapped.__mro_entries__(bases). + + result = PyObject_Call(mro_entries_method, args, kwds); + + Py_DECREF(mro_entries_method); + + return result; + } + else + { + PyErr_Clear(); } + } - return Py_BuildValue("(O)", self->wrapped); + return Py_BuildValue("(O)", wrapped); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_get_name( - WraptObjectProxyObject *self) +static PyObject *WraptObjectProxy_get_name(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetAttrString(self->wrapped, "__name__"); + return PyObject_GetAttrString(self->wrapped, "__name__"); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_set_name(WraptObjectProxyObject *self, - PyObject *value) + PyObject *value) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PyObject_SetAttrString(self->wrapped, "__name__", value); + return PyObject_SetAttrString(self->wrapped, "__name__", value); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_get_qualname( - WraptObjectProxyObject *self) +static PyObject *WraptObjectProxy_get_qualname(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetAttrString(self->wrapped, "__qualname__"); + return PyObject_GetAttrString(self->wrapped, "__qualname__"); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_set_qualname(WraptObjectProxyObject *self, - PyObject *value) + PyObject *value) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PyObject_SetAttrString(self->wrapped, "__qualname__", value); + return PyObject_SetAttrString(self->wrapped, "__qualname__", value); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_get_module( - WraptObjectProxyObject *self) +static PyObject *WraptObjectProxy_get_module(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetAttrString(self->wrapped, "__module__"); + return PyObject_GetAttrString(self->wrapped, "__module__"); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_set_module(WraptObjectProxyObject *self, - PyObject *value) + PyObject *value) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - if (PyObject_SetAttrString(self->wrapped, "__module__", value) == -1) - return -1; + if (PyObject_SetAttrString(self->wrapped, "__module__", value) == -1) + return -1; - return PyDict_SetItemString(self->dict, "__module__", value); + return PyDict_SetItemString(self->dict, "__module__", value); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_get_doc( - WraptObjectProxyObject *self) +static PyObject *WraptObjectProxy_get_doc(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetAttrString(self->wrapped, "__doc__"); + return PyObject_GetAttrString(self->wrapped, "__doc__"); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_set_doc(WraptObjectProxyObject *self, - PyObject *value) + PyObject *value) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - if (PyObject_SetAttrString(self->wrapped, "__doc__", value) == -1) - return -1; + if (PyObject_SetAttrString(self->wrapped, "__doc__", value) == -1) + return -1; - return PyDict_SetItemString(self->dict, "__doc__", value); + return PyDict_SetItemString(self->dict, "__doc__", value); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_get_class( - WraptObjectProxyObject *self) +static PyObject *WraptObjectProxy_get_class(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetAttrString(self->wrapped, "__class__"); + return PyObject_GetAttrString(self->wrapped, "__class__"); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_set_class(WraptObjectProxyObject *self, - PyObject *value) + PyObject *value) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PyObject_SetAttrString(self->wrapped, "__class__", value); + return PyObject_SetAttrString(self->wrapped, "__class__", value); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_get_annotations( - WraptObjectProxyObject *self) +static PyObject * +WraptObjectProxy_get_annotations(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetAttrString(self->wrapped, "__annotations__"); + return PyObject_GetAttrString(self->wrapped, "__annotations__"); } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_set_annotations(WraptObjectProxyObject *self, - PyObject *value) + PyObject *value) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PyObject_SetAttrString(self->wrapped, "__annotations__", value); + return PyObject_SetAttrString(self->wrapped, "__annotations__", value); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_get_wrapped( - WraptObjectProxyObject *self) +static PyObject *WraptObjectProxy_get_wrapped(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - Py_INCREF(self->wrapped); - return self->wrapped; + Py_INCREF(self->wrapped); + return self->wrapped; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_object_proxy(WraptObjectProxyObject *self) +{ + Py_INCREF(&WraptObjectProxy_Type); + return (PyObject *)&WraptObjectProxy_Type; } /* ------------------------------------------------------------------------- */ static int WraptObjectProxy_set_wrapped(WraptObjectProxyObject *self, - PyObject *value) + PyObject *value) { - if (!value) { - PyErr_SetString(PyExc_TypeError, "__wrapped__ must be an object"); - return -1; - } + static PyObject *fixups_str = NULL; + + PyObject *fixups = NULL; + + if (!value) + { + PyErr_SetString(PyExc_TypeError, "__wrapped__ must be an object"); + return -1; + } + + Py_INCREF(value); + Py_XDECREF(self->wrapped); + + self->wrapped = value; + + if (!fixups_str) + { + fixups_str = PyUnicode_InternFromString("__wrapped_setattr_fixups__"); + } + + fixups = PyObject_GetAttr((PyObject *)self, fixups_str); - Py_INCREF(value); - Py_XDECREF(self->wrapped); + if (fixups) + { + PyObject *result = NULL; + + result = PyObject_CallObject(fixups, NULL); + Py_DECREF(fixups); + + if (!result) + return -1; - self->wrapped = value; + Py_DECREF(result); + } + else + PyErr_Clear(); - return 0; + return 0; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_getattro( - WraptObjectProxyObject *self, PyObject *name) +static PyObject *WraptObjectProxy_getattro(WraptObjectProxyObject *self, + PyObject *name) { - PyObject *object = NULL; - PyObject *result = NULL; + PyObject *object = NULL; + PyObject *result = NULL; - static PyObject *getattr_str = NULL; + static PyObject *getattr_str = NULL; - object = PyObject_GenericGetAttr((PyObject *)self, name); + object = PyObject_GenericGetAttr((PyObject *)self, name); - if (object) - return object; + if (object) + return object; - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - return NULL; + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + return NULL; - PyErr_Clear(); + PyErr_Clear(); - if (!getattr_str) { -#if PY_MAJOR_VERSION >= 3 - getattr_str = PyUnicode_InternFromString("__getattr__"); -#else - getattr_str = PyString_InternFromString("__getattr__"); -#endif - } + if (!getattr_str) + { + getattr_str = PyUnicode_InternFromString("__getattr__"); + } - object = PyObject_GenericGetAttr((PyObject *)self, getattr_str); + object = PyObject_GenericGetAttr((PyObject *)self, getattr_str); - if (!object) - return NULL; + if (!object) + return NULL; - result = PyObject_CallFunctionObjArgs(object, name, NULL); + result = PyObject_CallFunctionObjArgs(object, name, NULL); - Py_DECREF(object); + Py_DECREF(object); - return result; + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptObjectProxy_getattr( - WraptObjectProxyObject *self, PyObject *args) +static PyObject *WraptObjectProxy_getattr(WraptObjectProxyObject *self, + PyObject *args) { - PyObject *name = NULL; + PyObject *name = NULL; -#if PY_MAJOR_VERSION >= 3 - if (!PyArg_ParseTuple(args, "U:__getattr__", &name)) - return NULL; -#else - if (!PyArg_ParseTuple(args, "S:__getattr__", &name)) - return NULL; -#endif + if (!PyArg_ParseTuple(args, "U:__getattr__", &name)) + return NULL; - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetAttr(self->wrapped, name); + return PyObject_GetAttr(self->wrapped, name); } /* ------------------------------------------------------------------------- */ -static int WraptObjectProxy_setattro( - WraptObjectProxyObject *self, PyObject *name, PyObject *value) +static int WraptObjectProxy_setattro(WraptObjectProxyObject *self, + PyObject *name, PyObject *value) { - static PyObject *self_str = NULL; - static PyObject *wrapped_str = NULL; - static PyObject *startswith_str = NULL; + static PyObject *self_str = NULL; + static PyObject *startswith_str = NULL; - PyObject *match = NULL; + PyObject *match = NULL; - if (!startswith_str) { -#if PY_MAJOR_VERSION >= 3 - startswith_str = PyUnicode_InternFromString("startswith"); -#else - startswith_str = PyString_InternFromString("startswith"); -#endif - } + if (!startswith_str) + { + startswith_str = PyUnicode_InternFromString("startswith"); + } - if (!self_str) { -#if PY_MAJOR_VERSION >= 3 - self_str = PyUnicode_InternFromString("_self_"); -#else - self_str = PyString_InternFromString("_self_"); -#endif - } - - match = PyObject_CallMethodObjArgs(name, startswith_str, self_str, NULL); + if (!self_str) + { + self_str = PyUnicode_InternFromString("_self_"); + } - if (match == Py_True) { - Py_DECREF(match); + match = PyObject_CallMethodObjArgs(name, startswith_str, self_str, NULL); - return PyObject_GenericSetAttr((PyObject *)self, name, value); - } - else if (!match) - PyErr_Clear(); + if (match == Py_True) + { + Py_DECREF(match); - Py_XDECREF(match); + return PyObject_GenericSetAttr((PyObject *)self, name, value); + } + else if (!match) + PyErr_Clear(); - if (!wrapped_str) { -#if PY_MAJOR_VERSION >= 3 - wrapped_str = PyUnicode_InternFromString("__wrapped__"); -#else - wrapped_str = PyString_InternFromString("__wrapped__"); -#endif - } + Py_XDECREF(match); - if (PyObject_HasAttr((PyObject *)Py_TYPE(self), name)) - return PyObject_GenericSetAttr((PyObject *)self, name, value); + if (PyObject_HasAttr((PyObject *)Py_TYPE(self), name)) + return PyObject_GenericSetAttr((PyObject *)self, name, value); - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return -1; - } + } - return PyObject_SetAttr(self->wrapped, name, value); + return PyObject_SetAttr(self->wrapped, name, value); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_richcompare(WraptObjectProxyObject *self, - PyObject *other, int opcode) + PyObject *other, int opcode) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_RichCompare(self->wrapped, other, opcode); + return PyObject_RichCompare(self->wrapped, other, opcode); } /* ------------------------------------------------------------------------- */ static PyObject *WraptObjectProxy_iter(WraptObjectProxyObject *self) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_GetIter(self->wrapped); + return PyObject_GetIter(self->wrapped); } /* ------------------------------------------------------------------------- */ static PyNumberMethods WraptObjectProxy_as_number = { - (binaryfunc)WraptObjectProxy_add, /*nb_add*/ - (binaryfunc)WraptObjectProxy_subtract, /*nb_subtract*/ - (binaryfunc)WraptObjectProxy_multiply, /*nb_multiply*/ -#if PY_MAJOR_VERSION < 3 - (binaryfunc)WraptObjectProxy_divide, /*nb_divide*/ -#endif - (binaryfunc)WraptObjectProxy_remainder, /*nb_remainder*/ - (binaryfunc)WraptObjectProxy_divmod, /*nb_divmod*/ - (ternaryfunc)WraptObjectProxy_power, /*nb_power*/ - (unaryfunc)WraptObjectProxy_negative, /*nb_negative*/ - (unaryfunc)WraptObjectProxy_positive, /*nb_positive*/ - (unaryfunc)WraptObjectProxy_absolute, /*nb_absolute*/ - (inquiry)WraptObjectProxy_bool, /*nb_nonzero/nb_bool*/ - (unaryfunc)WraptObjectProxy_invert, /*nb_invert*/ - (binaryfunc)WraptObjectProxy_lshift, /*nb_lshift*/ - (binaryfunc)WraptObjectProxy_rshift, /*nb_rshift*/ - (binaryfunc)WraptObjectProxy_and, /*nb_and*/ - (binaryfunc)WraptObjectProxy_xor, /*nb_xor*/ - (binaryfunc)WraptObjectProxy_or, /*nb_or*/ -#if PY_MAJOR_VERSION < 3 - 0, /*nb_coerce*/ -#endif -#if PY_MAJOR_VERSION < 3 - (unaryfunc)WraptObjectProxy_int, /*nb_int*/ - (unaryfunc)WraptObjectProxy_long, /*nb_long*/ -#else - (unaryfunc)WraptObjectProxy_long, /*nb_int*/ - 0, /*nb_long/nb_reserved*/ -#endif - (unaryfunc)WraptObjectProxy_float, /*nb_float*/ -#if PY_MAJOR_VERSION < 3 - (unaryfunc)WraptObjectProxy_oct, /*nb_oct*/ - (unaryfunc)WraptObjectProxy_hex, /*nb_hex*/ -#endif - (binaryfunc)WraptObjectProxy_inplace_add, /*nb_inplace_add*/ - (binaryfunc)WraptObjectProxy_inplace_subtract, /*nb_inplace_subtract*/ - (binaryfunc)WraptObjectProxy_inplace_multiply, /*nb_inplace_multiply*/ -#if PY_MAJOR_VERSION < 3 - (binaryfunc)WraptObjectProxy_inplace_divide, /*nb_inplace_divide*/ -#endif + (binaryfunc)WraptObjectProxy_add, /*nb_add*/ + (binaryfunc)WraptObjectProxy_subtract, /*nb_subtract*/ + (binaryfunc)WraptObjectProxy_multiply, /*nb_multiply*/ + (binaryfunc)WraptObjectProxy_remainder, /*nb_remainder*/ + (binaryfunc)WraptObjectProxy_divmod, /*nb_divmod*/ + (ternaryfunc)WraptObjectProxy_power, /*nb_power*/ + (unaryfunc)WraptObjectProxy_negative, /*nb_negative*/ + (unaryfunc)WraptObjectProxy_positive, /*nb_positive*/ + (unaryfunc)WraptObjectProxy_absolute, /*nb_absolute*/ + (inquiry)WraptObjectProxy_bool, /*nb_nonzero/nb_bool*/ + (unaryfunc)WraptObjectProxy_invert, /*nb_invert*/ + (binaryfunc)WraptObjectProxy_lshift, /*nb_lshift*/ + (binaryfunc)WraptObjectProxy_rshift, /*nb_rshift*/ + (binaryfunc)WraptObjectProxy_and, /*nb_and*/ + (binaryfunc)WraptObjectProxy_xor, /*nb_xor*/ + (binaryfunc)WraptObjectProxy_or, /*nb_or*/ + (unaryfunc)WraptObjectProxy_long, /*nb_int*/ + 0, /*nb_long/nb_reserved*/ + (unaryfunc)WraptObjectProxy_float, /*nb_float*/ + (binaryfunc)WraptObjectProxy_inplace_add, /*nb_inplace_add*/ + (binaryfunc)WraptObjectProxy_inplace_subtract, /*nb_inplace_subtract*/ + (binaryfunc)WraptObjectProxy_inplace_multiply, /*nb_inplace_multiply*/ (binaryfunc)WraptObjectProxy_inplace_remainder, /*nb_inplace_remainder*/ - (ternaryfunc)WraptObjectProxy_inplace_power, /*nb_inplace_power*/ - (binaryfunc)WraptObjectProxy_inplace_lshift, /*nb_inplace_lshift*/ - (binaryfunc)WraptObjectProxy_inplace_rshift, /*nb_inplace_rshift*/ - (binaryfunc)WraptObjectProxy_inplace_and, /*nb_inplace_and*/ - (binaryfunc)WraptObjectProxy_inplace_xor, /*nb_inplace_xor*/ - (binaryfunc)WraptObjectProxy_inplace_or, /*nb_inplace_or*/ - (binaryfunc)WraptObjectProxy_floor_divide, /*nb_floor_divide*/ - (binaryfunc)WraptObjectProxy_true_divide, /*nb_true_divide*/ - (binaryfunc)WraptObjectProxy_inplace_floor_divide, /*nb_inplace_floor_divide*/ - (binaryfunc)WraptObjectProxy_inplace_true_divide, /*nb_inplace_true_divide*/ - (unaryfunc)WraptObjectProxy_index, /*nb_index*/ + (ternaryfunc)WraptObjectProxy_inplace_power, /*nb_inplace_power*/ + (binaryfunc)WraptObjectProxy_inplace_lshift, /*nb_inplace_lshift*/ + (binaryfunc)WraptObjectProxy_inplace_rshift, /*nb_inplace_rshift*/ + (binaryfunc)WraptObjectProxy_inplace_and, /*nb_inplace_and*/ + (binaryfunc)WraptObjectProxy_inplace_xor, /*nb_inplace_xor*/ + (binaryfunc)WraptObjectProxy_inplace_or, /*nb_inplace_or*/ + (binaryfunc)WraptObjectProxy_floor_divide, /*nb_floor_divide*/ + (binaryfunc)WraptObjectProxy_true_divide, /*nb_true_divide*/ + (binaryfunc) + WraptObjectProxy_inplace_floor_divide, /*nb_inplace_floor_divide*/ + (binaryfunc)WraptObjectProxy_inplace_true_divide, /*nb_inplace_true_divide*/ + (unaryfunc)WraptObjectProxy_index, /*nb_index*/ + (binaryfunc)WraptObjectProxy_matrix_multiply, /*nb_matrix_multiply*/ + (binaryfunc)WraptObjectProxy_inplace_matrix_multiply, /*nb_inplace_matrix_multiply*/ }; static PySequenceMethods WraptObjectProxy_as_sequence = { - (lenfunc)WraptObjectProxy_length, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - 0, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ + (lenfunc)WraptObjectProxy_length, /*sq_length*/ + 0, /*sq_concat*/ + 0, /*sq_repeat*/ + 0, /*sq_item*/ + 0, /*sq_slice*/ + 0, /*sq_ass_item*/ + 0, /*sq_ass_slice*/ (objobjproc)WraptObjectProxy_contains, /* sq_contains */ }; static PyMappingMethods WraptObjectProxy_as_mapping = { - (lenfunc)WraptObjectProxy_length, /*mp_length*/ - (binaryfunc)WraptObjectProxy_getitem, /*mp_subscript*/ + (lenfunc)WraptObjectProxy_length, /*mp_length*/ + (binaryfunc)WraptObjectProxy_getitem, /*mp_subscript*/ (objobjargproc)WraptObjectProxy_setitem, /*mp_ass_subscript*/ }; static PyMethodDef WraptObjectProxy_methods[] = { - { "__self_setattr__", (PyCFunction)WraptObjectProxy_self_setattr, - METH_VARARGS , 0 }, - { "__dir__", (PyCFunction)WraptObjectProxy_dir, METH_NOARGS, 0 }, - { "__enter__", (PyCFunction)WraptObjectProxy_enter, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__exit__", (PyCFunction)WraptObjectProxy_exit, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__copy__", (PyCFunction)WraptObjectProxy_copy, - METH_NOARGS, 0 }, - { "__deepcopy__", (PyCFunction)WraptObjectProxy_deepcopy, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__reduce__", (PyCFunction)WraptObjectProxy_reduce, - METH_NOARGS, 0 }, - { "__reduce_ex__", (PyCFunction)WraptObjectProxy_reduce_ex, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__getattr__", (PyCFunction)WraptObjectProxy_getattr, - METH_VARARGS , 0 }, - { "__bytes__", (PyCFunction)WraptObjectProxy_bytes, METH_NOARGS, 0 }, - { "__reversed__", (PyCFunction)WraptObjectProxy_reversed, METH_NOARGS, 0 }, -#if PY_MAJOR_VERSION >= 3 - { "__round__", (PyCFunction)WraptObjectProxy_round, METH_NOARGS, 0 }, -#endif - { "__complex__", (PyCFunction)WraptObjectProxy_complex, METH_NOARGS, 0 }, -#if PY_MAJOR_VERSION > 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7) - { "__mro_entries__", (PyCFunction)WraptObjectProxy_mro_entries, - METH_VARARGS | METH_KEYWORDS, 0 }, -#endif - { NULL, NULL }, + {"__self_setattr__", (PyCFunction)WraptObjectProxy_self_setattr, + METH_VARARGS, 0}, + {"__dir__", (PyCFunction)WraptObjectProxy_dir, METH_NOARGS, 0}, + {"__enter__", (PyCFunction)WraptObjectProxy_enter, + METH_VARARGS | METH_KEYWORDS, 0}, + {"__exit__", (PyCFunction)WraptObjectProxy_exit, + METH_VARARGS | METH_KEYWORDS, 0}, + {"__aenter__", (PyCFunction)WraptObjectProxy_aenter, + METH_VARARGS | METH_KEYWORDS, 0}, + {"__aexit__", (PyCFunction)WraptObjectProxy_aexit, + METH_VARARGS | METH_KEYWORDS, 0}, + {"__copy__", (PyCFunction)WraptObjectProxy_copy, METH_NOARGS, 0}, + {"__deepcopy__", (PyCFunction)WraptObjectProxy_deepcopy, + METH_VARARGS | METH_KEYWORDS, 0}, + {"__reduce__", (PyCFunction)WraptObjectProxy_reduce, METH_NOARGS, 0}, + {"__reduce_ex__", (PyCFunction)WraptObjectProxy_reduce_ex, + METH_VARARGS | METH_KEYWORDS, 0}, + {"__getattr__", (PyCFunction)WraptObjectProxy_getattr, METH_VARARGS, 0}, + {"__bytes__", (PyCFunction)WraptObjectProxy_bytes, METH_NOARGS, 0}, + {"__format__", (PyCFunction)WraptObjectProxy_format, METH_VARARGS, 0}, + {"__reversed__", (PyCFunction)WraptObjectProxy_reversed, METH_NOARGS, 0}, + {"__round__", (PyCFunction)WraptObjectProxy_round, + METH_VARARGS | METH_KEYWORDS, 0}, + {"__complex__", (PyCFunction)WraptObjectProxy_complex, METH_NOARGS, 0}, + {"__mro_entries__", (PyCFunction)WraptObjectProxy_mro_entries, + METH_VARARGS | METH_KEYWORDS, 0}, + {NULL, NULL}, }; static PyGetSetDef WraptObjectProxy_getset[] = { - { "__name__", (getter)WraptObjectProxy_get_name, - (setter)WraptObjectProxy_set_name, 0 }, - { "__qualname__", (getter)WraptObjectProxy_get_qualname, - (setter)WraptObjectProxy_set_qualname, 0 }, - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { "__class__", (getter)WraptObjectProxy_get_class, - (setter)WraptObjectProxy_set_class, 0 }, - { "__annotations__", (getter)WraptObjectProxy_get_annotations, - (setter)WraptObjectProxy_set_annotations, 0 }, - { "__wrapped__", (getter)WraptObjectProxy_get_wrapped, - (setter)WraptObjectProxy_set_wrapped, 0 }, - { NULL }, + {"__name__", (getter)WraptObjectProxy_get_name, + (setter)WraptObjectProxy_set_name, 0}, + {"__qualname__", (getter)WraptObjectProxy_get_qualname, + (setter)WraptObjectProxy_set_qualname, 0}, + {"__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0}, + {"__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0}, + {"__class__", (getter)WraptObjectProxy_get_class, + (setter)WraptObjectProxy_set_class, 0}, + {"__annotations__", (getter)WraptObjectProxy_get_annotations, + (setter)WraptObjectProxy_set_annotations, 0}, + {"__wrapped__", (getter)WraptObjectProxy_get_wrapped, + (setter)WraptObjectProxy_set_wrapped, 0}, + {"__object_proxy__", (getter)WraptObjectProxy_get_object_proxy, 0, 0}, + {NULL}, }; PyTypeObject WraptObjectProxy_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "ObjectProxy", /*tp_name*/ - sizeof(WraptObjectProxyObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + PyVarObject_HEAD_INIT(NULL, 0) "ObjectProxy", /*tp_name*/ + sizeof(WraptObjectProxyObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ /* methods */ - (destructor)WraptObjectProxy_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (unaryfunc)WraptObjectProxy_repr, /*tp_repr*/ - &WraptObjectProxy_as_number, /*tp_as_number*/ - &WraptObjectProxy_as_sequence, /*tp_as_sequence*/ - &WraptObjectProxy_as_mapping, /*tp_as_mapping*/ - (hashfunc)WraptObjectProxy_hash, /*tp_hash*/ - 0, /*tp_call*/ - (unaryfunc)WraptObjectProxy_str, /*tp_str*/ - (getattrofunc)WraptObjectProxy_getattro, /*tp_getattro*/ - (setattrofunc)WraptObjectProxy_setattro, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - (traverseproc)WraptObjectProxy_traverse, /*tp_traverse*/ - (inquiry)WraptObjectProxy_clear, /*tp_clear*/ - (richcmpfunc)WraptObjectProxy_richcompare, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - (getiterfunc)WraptObjectProxy_iter, /*tp_iter*/ - 0, /*tp_iternext*/ - WraptObjectProxy_methods, /*tp_methods*/ - 0, /*tp_members*/ - WraptObjectProxy_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - offsetof(WraptObjectProxyObject, dict), /*tp_dictoffset*/ - (initproc)WraptObjectProxy_init, /*tp_init*/ - PyType_GenericAlloc, /*tp_alloc*/ - WraptObjectProxy_new, /*tp_new*/ - PyObject_GC_Del, /*tp_free*/ - 0, /*tp_is_gc*/ + (destructor)WraptObjectProxy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_as_async*/ + (unaryfunc)WraptObjectProxy_repr, /*tp_repr*/ + &WraptObjectProxy_as_number, /*tp_as_number*/ + &WraptObjectProxy_as_sequence, /*tp_as_sequence*/ + &WraptObjectProxy_as_mapping, /*tp_as_mapping*/ + (hashfunc)WraptObjectProxy_hash, /*tp_hash*/ + 0, /*tp_call*/ + (unaryfunc)WraptObjectProxy_str, /*tp_str*/ + (getattrofunc)WraptObjectProxy_getattro, /*tp_getattro*/ + (setattrofunc)WraptObjectProxy_setattro, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + (traverseproc)WraptObjectProxy_traverse, /*tp_traverse*/ + (inquiry)WraptObjectProxy_clear, /*tp_clear*/ + (richcmpfunc)WraptObjectProxy_richcompare, /*tp_richcompare*/ + offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ + 0, /* (getiterfunc)WraptObjectProxy_iter, */ /*tp_iter*/ + 0, /*tp_iternext*/ + WraptObjectProxy_methods, /*tp_methods*/ + 0, /*tp_members*/ + WraptObjectProxy_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + offsetof(WraptObjectProxyObject, dict), /*tp_dictoffset*/ + (initproc)WraptObjectProxy_init, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + WraptObjectProxy_new, /*tp_new*/ + PyObject_GC_Del, /*tp_free*/ + 0, /*tp_is_gc*/ }; /* ------------------------------------------------------------------------- */ -static PyObject *WraptCallableObjectProxy_call( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptCallableObjectProxy_call(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) { - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->wrapped) + { + if (raise_uninitialized_wrapper_error(self) == -1) return NULL; - } + } - return PyObject_Call(self->wrapped, args, kwds); + return PyObject_Call(self->wrapped, args, kwds); } /* ------------------------------------------------------------------------- */; static PyGetSetDef WraptCallableObjectProxy_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { NULL }, + {"__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0}, + {"__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0}, + {NULL}, }; PyTypeObject WraptCallableObjectProxy_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "CallableObjectProxy", /*tp_name*/ - sizeof(WraptObjectProxyObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + PyVarObject_HEAD_INIT(NULL, 0) "CallableObjectProxy", /*tp_name*/ + sizeof(WraptObjectProxyObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ /* methods */ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)WraptCallableObjectProxy_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)WraptCallableObjectProxy_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - WraptCallableObjectProxy_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - (initproc)WraptObjectProxy_init, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + WraptCallableObjectProxy_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + (initproc)WraptObjectProxy_init, /*tp_init*/ + 0, /*tp_alloc*/ + 0, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ }; /* ------------------------------------------------------------------------- */ static PyObject *WraptPartialCallableObjectProxy_new(PyTypeObject *type, - PyObject *args, PyObject *kwds) + PyObject *args, + PyObject *kwds) { - WraptPartialCallableObjectProxyObject *self; + WraptPartialCallableObjectProxyObject *self; - self = (WraptPartialCallableObjectProxyObject *)WraptObjectProxy_new(type, - args, kwds); + self = (WraptPartialCallableObjectProxyObject *)WraptObjectProxy_new( + type, args, kwds); - if (!self) - return NULL; + if (!self) + return NULL; - self->args = NULL; - self->kwargs = NULL; + self->args = NULL; + self->kwargs = NULL; - return (PyObject *)self; + return (PyObject *)self; } /* ------------------------------------------------------------------------- */ static int WraptPartialCallableObjectProxy_raw_init( - WraptPartialCallableObjectProxyObject *self, - PyObject *wrapped, PyObject *args, PyObject *kwargs) + WraptPartialCallableObjectProxyObject *self, PyObject *wrapped, + PyObject *args, PyObject *kwargs) { - int result = 0; + int result = 0; - result = WraptObjectProxy_raw_init((WraptObjectProxyObject *)self, - wrapped); + result = WraptObjectProxy_raw_init((WraptObjectProxyObject *)self, wrapped); - if (result == 0) { - Py_INCREF(args); - Py_XDECREF(self->args); - self->args = args; + if (result == 0) + { + Py_INCREF(args); + Py_XDECREF(self->args); + self->args = args; - Py_XINCREF(kwargs); - Py_XDECREF(self->kwargs); - self->kwargs = kwargs; - } + Py_XINCREF(kwargs); + Py_XDECREF(self->kwargs); + self->kwargs = kwargs; + } - return result; + return result; } /* ------------------------------------------------------------------------- */ static int WraptPartialCallableObjectProxy_init( - WraptPartialCallableObjectProxyObject *self, PyObject *args, - PyObject *kwds) + WraptPartialCallableObjectProxyObject *self, PyObject *args, + PyObject *kwds) { - PyObject *wrapped = NULL; - PyObject *fnargs = NULL; + PyObject *wrapped = NULL; + PyObject *fnargs = NULL; - int result = 0; + int result = 0; - if (!PyObject_Length(args)) { - PyErr_SetString(PyExc_TypeError, - "__init__ of partial needs an argument"); - return -1; - } + if (!PyObject_Length(args)) + { + PyErr_SetString(PyExc_TypeError, "__init__ of partial needs an argument"); + return -1; + } - if (PyObject_Length(args) < 1) { - PyErr_SetString(PyExc_TypeError, - "partial type takes at least one argument"); - return -1; - } + if (PyObject_Length(args) < 1) + { + PyErr_SetString(PyExc_TypeError, + "partial type takes at least one argument"); + return -1; + } - wrapped = PyTuple_GetItem(args, 0); + wrapped = PyTuple_GetItem(args, 0); - if (!PyCallable_Check(wrapped)) { - PyErr_SetString(PyExc_TypeError, - "the first argument must be callable"); - return -1; - } + if (!PyCallable_Check(wrapped)) + { + PyErr_SetString(PyExc_TypeError, "the first argument must be callable"); + return -1; + } - fnargs = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); + fnargs = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); - if (!fnargs) - return -1; + if (!fnargs) + return -1; - result = WraptPartialCallableObjectProxy_raw_init(self, wrapped, - fnargs, kwds); + result = + WraptPartialCallableObjectProxy_raw_init(self, wrapped, fnargs, kwds); - Py_DECREF(fnargs); + Py_DECREF(fnargs); - return result; + return result; } /* ------------------------------------------------------------------------- */ static int WraptPartialCallableObjectProxy_traverse( - WraptPartialCallableObjectProxyObject *self, - visitproc visit, void *arg) + WraptPartialCallableObjectProxyObject *self, visitproc visit, void *arg) { - WraptObjectProxy_traverse((WraptObjectProxyObject *)self, visit, arg); + WraptObjectProxy_traverse((WraptObjectProxyObject *)self, visit, arg); - Py_VISIT(self->args); - Py_VISIT(self->kwargs); + Py_VISIT(self->args); + Py_VISIT(self->kwargs); - return 0; + return 0; } /* ------------------------------------------------------------------------- */ static int WraptPartialCallableObjectProxy_clear( - WraptPartialCallableObjectProxyObject *self) + WraptPartialCallableObjectProxyObject *self) { - WraptObjectProxy_clear((WraptObjectProxyObject *)self); + WraptObjectProxy_clear((WraptObjectProxyObject *)self); - Py_CLEAR(self->args); - Py_CLEAR(self->kwargs); + Py_CLEAR(self->args); + Py_CLEAR(self->kwargs); - return 0; + return 0; } /* ------------------------------------------------------------------------- */ static void WraptPartialCallableObjectProxy_dealloc( - WraptPartialCallableObjectProxyObject *self) + WraptPartialCallableObjectProxyObject *self) { - PyObject_GC_UnTrack(self); + PyObject_GC_UnTrack(self); - WraptPartialCallableObjectProxy_clear(self); + WraptPartialCallableObjectProxy_clear(self); - WraptObjectProxy_dealloc((WraptObjectProxyObject *)self); + WraptObjectProxy_dealloc((WraptObjectProxyObject *)self); } /* ------------------------------------------------------------------------- */ static PyObject *WraptPartialCallableObjectProxy_call( - WraptPartialCallableObjectProxyObject *self, PyObject *args, - PyObject *kwds) + WraptPartialCallableObjectProxyObject *self, PyObject *args, + PyObject *kwds) { - PyObject *fnargs = NULL; - PyObject *fnkwargs = NULL; + PyObject *fnargs = NULL; + PyObject *fnkwargs = NULL; - PyObject *result = NULL; + PyObject *result = NULL; - long i; - long offset; + long i; + long offset; - if (!self->object_proxy.wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->object_proxy.wrapped) + { + if (raise_uninitialized_wrapper_error(&self->object_proxy) == -1) return NULL; - } + } - fnargs = PyTuple_New(PyTuple_Size(self->args)+PyTuple_Size(args)); + fnargs = PyTuple_New(PyTuple_Size(self->args) + PyTuple_Size(args)); - for (i=0; iargs); i++) { - PyObject *item; - item = PyTuple_GetItem(self->args, i); - Py_INCREF(item); - PyTuple_SetItem(fnargs, i, item); - } - - offset = PyTuple_Size(self->args); - - for (i=0; iargs); i++) + { + PyObject *item; + item = PyTuple_GetItem(self->args, i); + Py_INCREF(item); + PyTuple_SetItem(fnargs, i, item); + } - fnkwargs = PyDict_New(); + offset = PyTuple_Size(self->args); - if (self->kwargs && PyDict_Update(fnkwargs, self->kwargs) == -1) { - Py_DECREF(fnargs); - Py_DECREF(fnkwargs); - return NULL; - } + for (i = 0; i < PyTuple_Size(args); i++) + { + PyObject *item; + item = PyTuple_GetItem(args, i); + Py_INCREF(item); + PyTuple_SetItem(fnargs, offset + i, item); + } - if (kwds && PyDict_Update(fnkwargs, kwds) == -1) { - Py_DECREF(fnargs); - Py_DECREF(fnkwargs); - return NULL; - } + fnkwargs = PyDict_New(); - result = PyObject_Call(self->object_proxy.wrapped, - fnargs, fnkwargs); + if (self->kwargs && PyDict_Update(fnkwargs, self->kwargs) == -1) + { + Py_DECREF(fnargs); + Py_DECREF(fnkwargs); + return NULL; + } + if (kwds && PyDict_Update(fnkwargs, kwds) == -1) + { Py_DECREF(fnargs); Py_DECREF(fnkwargs); + return NULL; + } - return result; + result = PyObject_Call(self->object_proxy.wrapped, fnargs, fnkwargs); + + Py_DECREF(fnargs); + Py_DECREF(fnkwargs); + + return result; } /* ------------------------------------------------------------------------- */; static PyGetSetDef WraptPartialCallableObjectProxy_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { NULL }, + {"__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0}, + {"__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0}, + {NULL}, }; PyTypeObject WraptPartialCallableObjectProxy_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "PartialCallableObjectProxy", /*tp_name*/ - sizeof(WraptPartialCallableObjectProxyObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + PyVarObject_HEAD_INIT(NULL, 0) "PartialCallableObjectProxy", /*tp_name*/ + sizeof(WraptPartialCallableObjectProxyObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ /* methods */ - (destructor)WraptPartialCallableObjectProxy_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)WraptPartialCallableObjectProxy_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - (traverseproc)WraptPartialCallableObjectProxy_traverse, /*tp_traverse*/ - (inquiry)WraptPartialCallableObjectProxy_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - WraptPartialCallableObjectProxy_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - (initproc)WraptPartialCallableObjectProxy_init, /*tp_init*/ - 0, /*tp_alloc*/ - WraptPartialCallableObjectProxy_new, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ + (destructor)WraptPartialCallableObjectProxy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)WraptPartialCallableObjectProxy_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + (traverseproc)WraptPartialCallableObjectProxy_traverse, /*tp_traverse*/ + (inquiry)WraptPartialCallableObjectProxy_clear, /*tp_clear*/ + 0, /*tp_richcompare*/ + offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + WraptPartialCallableObjectProxy_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + (initproc)WraptPartialCallableObjectProxy_init, /*tp_init*/ + 0, /*tp_alloc*/ + WraptPartialCallableObjectProxy_new, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ }; /* ------------------------------------------------------------------------- */ static PyObject *WraptFunctionWrapperBase_new(PyTypeObject *type, - PyObject *args, PyObject *kwds) + PyObject *args, PyObject *kwds) { - WraptFunctionWrapperObject *self; + WraptFunctionWrapperObject *self; - self = (WraptFunctionWrapperObject *)WraptObjectProxy_new(type, - args, kwds); + self = (WraptFunctionWrapperObject *)WraptObjectProxy_new(type, args, kwds); - if (!self) - return NULL; + if (!self) + return NULL; - self->instance = NULL; - self->wrapper = NULL; - self->enabled = NULL; - self->binding = NULL; - self->parent = NULL; + self->instance = NULL; + self->wrapper = NULL; + self->enabled = NULL; + self->binding = NULL; + self->parent = NULL; + self->owner = NULL; - return (PyObject *)self; + return (PyObject *)self; } /* ------------------------------------------------------------------------- */ -static int WraptFunctionWrapperBase_raw_init(WraptFunctionWrapperObject *self, - PyObject *wrapped, PyObject *instance, PyObject *wrapper, - PyObject *enabled, PyObject *binding, PyObject *parent) +static int WraptFunctionWrapperBase_raw_init( + WraptFunctionWrapperObject *self, PyObject *wrapped, PyObject *instance, + PyObject *wrapper, PyObject *enabled, PyObject *binding, PyObject *parent, + PyObject *owner) { - int result = 0; + int result = 0; - result = WraptObjectProxy_raw_init((WraptObjectProxyObject *)self, - wrapped); + result = WraptObjectProxy_raw_init((WraptObjectProxyObject *)self, wrapped); - if (result == 0) { - Py_INCREF(instance); - Py_XDECREF(self->instance); - self->instance = instance; + if (result == 0) + { + Py_INCREF(instance); + Py_XDECREF(self->instance); + self->instance = instance; - Py_INCREF(wrapper); - Py_XDECREF(self->wrapper); - self->wrapper = wrapper; + Py_INCREF(wrapper); + Py_XDECREF(self->wrapper); + self->wrapper = wrapper; - Py_INCREF(enabled); - Py_XDECREF(self->enabled); - self->enabled = enabled; + Py_INCREF(enabled); + Py_XDECREF(self->enabled); + self->enabled = enabled; - Py_INCREF(binding); - Py_XDECREF(self->binding); - self->binding = binding; + Py_INCREF(binding); + Py_XDECREF(self->binding); + self->binding = binding; - Py_INCREF(parent); - Py_XDECREF(self->parent); - self->parent = parent; - } + Py_INCREF(parent); + Py_XDECREF(self->parent); + self->parent = parent; - return result; + Py_INCREF(owner); + Py_XDECREF(self->owner); + self->owner = owner; + } + + return result; } /* ------------------------------------------------------------------------- */ static int WraptFunctionWrapperBase_init(WraptFunctionWrapperObject *self, - PyObject *args, PyObject *kwds) + PyObject *args, PyObject *kwds) { - PyObject *wrapped = NULL; - PyObject *instance = NULL; - PyObject *wrapper = NULL; - PyObject *enabled = Py_None; - PyObject *binding = NULL; - PyObject *parent = Py_None; - - static PyObject *function_str = NULL; - - static char *kwlist[] = { "wrapped", "instance", "wrapper", - "enabled", "binding", "parent", NULL }; - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); -#else - function_str = PyString_InternFromString("function"); -#endif - } - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OOO|OOO:FunctionWrapperBase", kwlist, &wrapped, &instance, - &wrapper, &enabled, &binding, &parent)) { - return -1; - } - - if (!binding) - binding = function_str; - - return WraptFunctionWrapperBase_raw_init(self, wrapped, instance, wrapper, - enabled, binding, parent); + PyObject *wrapped = NULL; + PyObject *instance = NULL; + PyObject *wrapper = NULL; + PyObject *enabled = Py_None; + PyObject *binding = NULL; + PyObject *parent = Py_None; + PyObject *owner = Py_None; + + static PyObject *callable_str = NULL; + + char *const kwlist[] = {"wrapped", "instance", "wrapper", "enabled", + "binding", "parent", "owner", NULL}; + + if (!callable_str) + { + callable_str = PyUnicode_InternFromString("callable"); + } + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|OOOO:FunctionWrapperBase", + kwlist, &wrapped, &instance, &wrapper, + &enabled, &binding, &parent, &owner)) + { + return -1; + } + + if (!binding) + binding = callable_str; + + return WraptFunctionWrapperBase_raw_init(self, wrapped, instance, wrapper, + enabled, binding, parent, owner); } /* ------------------------------------------------------------------------- */ static int WraptFunctionWrapperBase_traverse(WraptFunctionWrapperObject *self, - visitproc visit, void *arg) + visitproc visit, void *arg) { - WraptObjectProxy_traverse((WraptObjectProxyObject *)self, visit, arg); + WraptObjectProxy_traverse((WraptObjectProxyObject *)self, visit, arg); - Py_VISIT(self->instance); - Py_VISIT(self->wrapper); - Py_VISIT(self->enabled); - Py_VISIT(self->binding); - Py_VISIT(self->parent); + Py_VISIT(self->instance); + Py_VISIT(self->wrapper); + Py_VISIT(self->enabled); + Py_VISIT(self->binding); + Py_VISIT(self->parent); + Py_VISIT(self->owner); - return 0; + return 0; } /* ------------------------------------------------------------------------- */ static int WraptFunctionWrapperBase_clear(WraptFunctionWrapperObject *self) { - WraptObjectProxy_clear((WraptObjectProxyObject *)self); + WraptObjectProxy_clear((WraptObjectProxyObject *)self); - Py_CLEAR(self->instance); - Py_CLEAR(self->wrapper); - Py_CLEAR(self->enabled); - Py_CLEAR(self->binding); - Py_CLEAR(self->parent); + Py_CLEAR(self->instance); + Py_CLEAR(self->wrapper); + Py_CLEAR(self->enabled); + Py_CLEAR(self->binding); + Py_CLEAR(self->parent); + Py_CLEAR(self->owner); - return 0; + return 0; } /* ------------------------------------------------------------------------- */ static void WraptFunctionWrapperBase_dealloc(WraptFunctionWrapperObject *self) { - PyObject_GC_UnTrack(self); + PyObject_GC_UnTrack(self); - WraptFunctionWrapperBase_clear(self); + WraptFunctionWrapperBase_clear(self); - WraptObjectProxy_dealloc((WraptObjectProxyObject *)self); + WraptObjectProxy_dealloc((WraptObjectProxyObject *)self); } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_call( - WraptFunctionWrapperObject *self, PyObject *args, PyObject *kwds) +static PyObject *WraptFunctionWrapperBase_call(WraptFunctionWrapperObject *self, + PyObject *args, PyObject *kwds) { - PyObject *param_kwds = NULL; - - PyObject *result = NULL; - - static PyObject *function_str = NULL; - static PyObject *classmethod_str = NULL; - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); - classmethod_str = PyUnicode_InternFromString("classmethod"); -#else - function_str = PyString_InternFromString("function"); - classmethod_str = PyString_InternFromString("classmethod"); -#endif - } + PyObject *param_kwds = NULL; - if (self->enabled != Py_None) { - if (PyCallable_Check(self->enabled)) { - PyObject *object = NULL; + PyObject *result = NULL; - object = PyObject_CallFunctionObjArgs(self->enabled, NULL); + static PyObject *function_str = NULL; + static PyObject *callable_str = NULL; + static PyObject *classmethod_str = NULL; + static PyObject *instancemethod_str = NULL; - if (!object) - return NULL; + if (!function_str) + { + function_str = PyUnicode_InternFromString("function"); + callable_str = PyUnicode_InternFromString("callable"); + classmethod_str = PyUnicode_InternFromString("classmethod"); + instancemethod_str = PyUnicode_InternFromString("instancemethod"); + } - if (PyObject_Not(object)) { - Py_DECREF(object); - return PyObject_Call(self->object_proxy.wrapped, args, kwds); - } + if (self->enabled != Py_None) + { + if (PyCallable_Check(self->enabled)) + { + PyObject *object = NULL; - Py_DECREF(object); - } - else if (PyObject_Not(self->enabled)) { - return PyObject_Call(self->object_proxy.wrapped, args, kwds); - } - } + object = PyObject_CallFunctionObjArgs(self->enabled, NULL); - if (!kwds) { - param_kwds = PyDict_New(); - kwds = param_kwds; - } + if (!object) + return NULL; - if ((self->instance == Py_None) && (self->binding == function_str || - PyObject_RichCompareBool(self->binding, function_str, - Py_EQ) == 1 || self->binding == classmethod_str || - PyObject_RichCompareBool(self->binding, classmethod_str, - Py_EQ) == 1)) { + if (PyObject_Not(object)) + { + Py_DECREF(object); + return PyObject_Call(self->object_proxy.wrapped, args, kwds); + } + + Py_DECREF(object); + } + else if (PyObject_Not(self->enabled)) + { + return PyObject_Call(self->object_proxy.wrapped, args, kwds); + } + } + + if (!kwds) + { + param_kwds = PyDict_New(); + kwds = param_kwds; + } + + if ((self->instance == Py_None) && + (self->binding == function_str || + PyObject_RichCompareBool(self->binding, function_str, Py_EQ) == 1 || + self->binding == instancemethod_str || + PyObject_RichCompareBool(self->binding, instancemethod_str, Py_EQ) == + 1 || + self->binding == callable_str || + PyObject_RichCompareBool(self->binding, callable_str, Py_EQ) == 1 || + self->binding == classmethod_str || + PyObject_RichCompareBool(self->binding, classmethod_str, Py_EQ) == 1)) + { - PyObject *instance = NULL; + PyObject *instance = NULL; - instance = PyObject_GetAttrString(self->object_proxy.wrapped, - "__self__"); + instance = PyObject_GetAttrString(self->object_proxy.wrapped, "__self__"); - if (instance) { - result = PyObject_CallFunctionObjArgs(self->wrapper, - self->object_proxy.wrapped, instance, args, kwds, NULL); + if (instance) + { + result = PyObject_CallFunctionObjArgs(self->wrapper, + self->object_proxy.wrapped, + instance, args, kwds, NULL); - Py_XDECREF(param_kwds); + Py_XDECREF(param_kwds); - Py_DECREF(instance); + Py_DECREF(instance); - return result; - } - else - PyErr_Clear(); + return result; } + else + PyErr_Clear(); + } - result = PyObject_CallFunctionObjArgs(self->wrapper, - self->object_proxy.wrapped, self->instance, args, kwds, NULL); + result = + PyObject_CallFunctionObjArgs(self->wrapper, self->object_proxy.wrapped, + self->instance, args, kwds, NULL); - Py_XDECREF(param_kwds); + Py_XDECREF(param_kwds); - return result; + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_descr_get( - WraptFunctionWrapperObject *self, PyObject *obj, PyObject *type) +static PyObject * +WraptFunctionWrapperBase_descr_get(WraptFunctionWrapperObject *self, + PyObject *obj, PyObject *type) { - PyObject *bound_type = NULL; - PyObject *descriptor = NULL; - PyObject *result = NULL; - - static PyObject *bound_type_str = NULL; - static PyObject *function_str = NULL; + PyObject *bound_type = NULL; + PyObject *descriptor = NULL; + PyObject *result = NULL; + + static PyObject *bound_type_str = NULL; + static PyObject *function_str = NULL; + static PyObject *callable_str = NULL; + static PyObject *builtin_str = NULL; + static PyObject *class_str = NULL; + static PyObject *instancemethod_str = NULL; + + if (!bound_type_str) + { + bound_type_str = PyUnicode_InternFromString("__bound_function_wrapper__"); + } + + if (!function_str) + { + function_str = PyUnicode_InternFromString("function"); + callable_str = PyUnicode_InternFromString("callable"); + builtin_str = PyUnicode_InternFromString("builtin"); + class_str = PyUnicode_InternFromString("class"); + instancemethod_str = PyUnicode_InternFromString("instancemethod"); + } + + if (self->parent == Py_None) + { + if (self->binding == builtin_str || + PyObject_RichCompareBool(self->binding, builtin_str, Py_EQ) == 1) + { + Py_INCREF(self); + return (PyObject *)self; + } + + if (self->binding == class_str || + PyObject_RichCompareBool(self->binding, class_str, Py_EQ) == 1) + { + Py_INCREF(self); + return (PyObject *)self; + } + + if (Py_TYPE(self->object_proxy.wrapped)->tp_descr_get == NULL) + { + Py_INCREF(self); + return (PyObject *)self; + } + + descriptor = (Py_TYPE(self->object_proxy.wrapped)->tp_descr_get)( + self->object_proxy.wrapped, obj, type); + + if (!descriptor) + return NULL; - if (!bound_type_str) { -#if PY_MAJOR_VERSION >= 3 - bound_type_str = PyUnicode_InternFromString( - "__bound_function_wrapper__"); -#else - bound_type_str = PyString_InternFromString( - "__bound_function_wrapper__"); -#endif - } + if (Py_TYPE(self) != &WraptFunctionWrapper_Type) + { + bound_type = PyObject_GenericGetAttr((PyObject *)self, bound_type_str); - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); -#else - function_str = PyString_InternFromString("function"); -#endif + if (!bound_type) + PyErr_Clear(); } - if (self->parent == Py_None) { -#if PY_MAJOR_VERSION < 3 - if (PyObject_IsInstance(self->object_proxy.wrapped, - (PyObject *)&PyClass_Type) || PyObject_IsInstance( - self->object_proxy.wrapped, (PyObject *)&PyType_Type)) { - Py_INCREF(self); - return (PyObject *)self; - } -#else - if (PyObject_IsInstance(self->object_proxy.wrapped, - (PyObject *)&PyType_Type)) { - Py_INCREF(self); - return (PyObject *)self; - } -#endif - - if (Py_TYPE(self->object_proxy.wrapped)->tp_descr_get == NULL) { - PyErr_Format(PyExc_AttributeError, - "'%s' object has no attribute '__get__'", - Py_TYPE(self->object_proxy.wrapped)->tp_name); - return NULL; - } - - descriptor = (Py_TYPE(self->object_proxy.wrapped)->tp_descr_get)( - self->object_proxy.wrapped, obj, type); + if (obj == NULL) + obj = Py_None; - if (!descriptor) - return NULL; + result = PyObject_CallFunctionObjArgs( + bound_type ? bound_type : (PyObject *)&WraptBoundFunctionWrapper_Type, + descriptor, obj, self->wrapper, self->enabled, self->binding, self, + type, NULL); - if (Py_TYPE(self) != &WraptFunctionWrapper_Type) { - bound_type = PyObject_GenericGetAttr((PyObject *)self, - bound_type_str); - - if (!bound_type) - PyErr_Clear(); - } + Py_XDECREF(bound_type); + Py_DECREF(descriptor); - if (obj == NULL) - obj = Py_None; + return result; + } + + if (self->instance == Py_None && + (self->binding == function_str || + PyObject_RichCompareBool(self->binding, function_str, Py_EQ) == 1 || + self->binding == instancemethod_str || + PyObject_RichCompareBool(self->binding, instancemethod_str, Py_EQ) == + 1 || + self->binding == callable_str || + PyObject_RichCompareBool(self->binding, callable_str, Py_EQ) == 1)) + { - result = PyObject_CallFunctionObjArgs(bound_type ? bound_type : - (PyObject *)&WraptBoundFunctionWrapper_Type, descriptor, - obj, self->wrapper, self->enabled, self->binding, - self, NULL); + PyObject *wrapped = NULL; - Py_XDECREF(bound_type); - Py_DECREF(descriptor); + static PyObject *wrapped_str = NULL; - return result; + if (!wrapped_str) + { + wrapped_str = PyUnicode_InternFromString("__wrapped__"); } - if (self->instance == Py_None && (self->binding == function_str || - PyObject_RichCompareBool(self->binding, function_str, - Py_EQ) == 1)) { - - PyObject *wrapped = NULL; + wrapped = PyObject_GetAttr(self->parent, wrapped_str); - static PyObject *wrapped_str = NULL; - - if (!wrapped_str) { -#if PY_MAJOR_VERSION >= 3 - wrapped_str = PyUnicode_InternFromString("__wrapped__"); -#else - wrapped_str = PyString_InternFromString("__wrapped__"); -#endif - } - - wrapped = PyObject_GetAttr(self->parent, wrapped_str); + if (!wrapped) + return NULL; - if (!wrapped) - return NULL; - - if (Py_TYPE(wrapped)->tp_descr_get == NULL) { - PyErr_Format(PyExc_AttributeError, - "'%s' object has no attribute '__get__'", - Py_TYPE(wrapped)->tp_name); - Py_DECREF(wrapped); - return NULL; - } + if (Py_TYPE(wrapped)->tp_descr_get == NULL) + { + PyErr_Format(PyExc_AttributeError, + "'%s' object has no attribute '__get__'", + Py_TYPE(wrapped)->tp_name); + Py_DECREF(wrapped); + return NULL; + } - descriptor = (Py_TYPE(wrapped)->tp_descr_get)(wrapped, obj, type); + descriptor = (Py_TYPE(wrapped)->tp_descr_get)(wrapped, obj, type); - Py_DECREF(wrapped); + Py_DECREF(wrapped); - if (!descriptor) - return NULL; + if (!descriptor) + return NULL; - if (Py_TYPE(self->parent) != &WraptFunctionWrapper_Type) { - bound_type = PyObject_GenericGetAttr((PyObject *)self->parent, - bound_type_str); + if (Py_TYPE(self->parent) != &WraptFunctionWrapper_Type) + { + bound_type = + PyObject_GenericGetAttr((PyObject *)self->parent, bound_type_str); - if (!bound_type) - PyErr_Clear(); - } + if (!bound_type) + PyErr_Clear(); + } - if (obj == NULL) - obj = Py_None; + if (obj == NULL) + obj = Py_None; - result = PyObject_CallFunctionObjArgs(bound_type ? bound_type : - (PyObject *)&WraptBoundFunctionWrapper_Type, descriptor, - obj, self->wrapper, self->enabled, self->binding, - self->parent, NULL); + result = PyObject_CallFunctionObjArgs( + bound_type ? bound_type : (PyObject *)&WraptBoundFunctionWrapper_Type, + descriptor, obj, self->wrapper, self->enabled, self->binding, + self->parent, type, NULL); - Py_XDECREF(bound_type); - Py_DECREF(descriptor); + Py_XDECREF(bound_type); + Py_DECREF(descriptor); - return result; - } + return result; + } - Py_INCREF(self); - return (PyObject *)self; + Py_INCREF(self); + return (PyObject *)self; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_set_name( - WraptFunctionWrapperObject *self, PyObject *args, PyObject *kwds) +static PyObject * +WraptFunctionWrapperBase_set_name(WraptFunctionWrapperObject *self, + PyObject *args, PyObject *kwds) { - PyObject *method = NULL; - PyObject *result = NULL; + PyObject *method = NULL; + PyObject *result = NULL; - if (!self->object_proxy.wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->object_proxy.wrapped) + { + if (raise_uninitialized_wrapper_error(&self->object_proxy) == -1) return NULL; - } + } - method = PyObject_GetAttrString(self->object_proxy.wrapped, - "__set_name__"); + method = PyObject_GetAttrString(self->object_proxy.wrapped, "__set_name__"); - if (!method) { - PyErr_Clear(); - Py_INCREF(Py_None); - return Py_None; - } + if (!method) + { + PyErr_Clear(); + Py_INCREF(Py_None); + return Py_None; + } - result = PyObject_Call(method, args, kwds); + result = PyObject_Call(method, args, kwds); - Py_DECREF(method); + Py_DECREF(method); - return result; + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_instancecheck( - WraptFunctionWrapperObject *self, PyObject *instance) +static PyObject * +WraptFunctionWrapperBase_instancecheck(WraptFunctionWrapperObject *self, + PyObject *instance) { - PyObject *result = NULL; + PyObject *result = NULL; - int check = 0; + int check = 0; - if (!self->object_proxy.wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } + if (!self->object_proxy.wrapped) + { + if (raise_uninitialized_wrapper_error(&self->object_proxy) == -1) + return NULL; + } - check = PyObject_IsInstance(instance, self->object_proxy.wrapped); + check = PyObject_IsInstance(instance, self->object_proxy.wrapped); - if (check < 0) { - return NULL; - } + if (check < 0) + { + return NULL; + } - result = check ? Py_True : Py_False; + result = check ? Py_True : Py_False; - Py_INCREF(result); - return result; + Py_INCREF(result); + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_subclasscheck( - WraptFunctionWrapperObject *self, PyObject *args) +static PyObject * +WraptFunctionWrapperBase_subclasscheck(WraptFunctionWrapperObject *self, + PyObject *args) { - PyObject *subclass = NULL; - PyObject *object = NULL; - PyObject *result = NULL; + PyObject *subclass = NULL; + PyObject *object = NULL; + PyObject *result = NULL; - int check = 0; + int check = 0; - if (!self->object_proxy.wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + if (!self->object_proxy.wrapped) + { + if (raise_uninitialized_wrapper_error(&self->object_proxy) == -1) return NULL; - } + } - if (!PyArg_ParseTuple(args, "O", &subclass)) - return NULL; + if (!PyArg_ParseTuple(args, "O", &subclass)) + return NULL; - object = PyObject_GetAttrString(subclass, "__wrapped__"); + object = PyObject_GetAttrString(subclass, "__wrapped__"); - if (!object) - PyErr_Clear(); + if (!object) + PyErr_Clear(); - check = PyObject_IsSubclass(object ? object: subclass, - self->object_proxy.wrapped); + check = PyObject_IsSubclass(object ? object : subclass, + self->object_proxy.wrapped); - Py_XDECREF(object); + Py_XDECREF(object); - if (check == -1) - return NULL; + if (check == -1) + return NULL; - result = check ? Py_True : Py_False; + result = check ? Py_True : Py_False; - Py_INCREF(result); + Py_INCREF(result); - return result; + return result; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_get_self_instance( - WraptFunctionWrapperObject *self, void *closure) +static PyObject * +WraptFunctionWrapperBase_get_self_instance(WraptFunctionWrapperObject *self, + void *closure) { - if (!self->instance) { - Py_INCREF(Py_None); - return Py_None; - } + if (!self->instance) + { + Py_INCREF(Py_None); + return Py_None; + } - Py_INCREF(self->instance); - return self->instance; + Py_INCREF(self->instance); + return self->instance; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_get_self_wrapper( - WraptFunctionWrapperObject *self, void *closure) +static PyObject * +WraptFunctionWrapperBase_get_self_wrapper(WraptFunctionWrapperObject *self, + void *closure) { - if (!self->wrapper) { - Py_INCREF(Py_None); - return Py_None; - } + if (!self->wrapper) + { + Py_INCREF(Py_None); + return Py_None; + } - Py_INCREF(self->wrapper); - return self->wrapper; + Py_INCREF(self->wrapper); + return self->wrapper; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_get_self_enabled( - WraptFunctionWrapperObject *self, void *closure) +static PyObject * +WraptFunctionWrapperBase_get_self_enabled(WraptFunctionWrapperObject *self, + void *closure) { - if (!self->enabled) { - Py_INCREF(Py_None); - return Py_None; - } + if (!self->enabled) + { + Py_INCREF(Py_None); + return Py_None; + } - Py_INCREF(self->enabled); - return self->enabled; + Py_INCREF(self->enabled); + return self->enabled; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_get_self_binding( - WraptFunctionWrapperObject *self, void *closure) +static PyObject * +WraptFunctionWrapperBase_get_self_binding(WraptFunctionWrapperObject *self, + void *closure) { - if (!self->binding) { - Py_INCREF(Py_None); - return Py_None; - } + if (!self->binding) + { + Py_INCREF(Py_None); + return Py_None; + } - Py_INCREF(self->binding); - return self->binding; + Py_INCREF(self->binding); + return self->binding; } /* ------------------------------------------------------------------------- */ -static PyObject *WraptFunctionWrapperBase_get_self_parent( - WraptFunctionWrapperObject *self, void *closure) +static PyObject * +WraptFunctionWrapperBase_get_self_parent(WraptFunctionWrapperObject *self, + void *closure) { - if (!self->parent) { - Py_INCREF(Py_None); - return Py_None; - } + if (!self->parent) + { + Py_INCREF(Py_None); + return Py_None; + } + + Py_INCREF(self->parent); + return self->parent; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject * +WraptFunctionWrapperBase_get_self_owner(WraptFunctionWrapperObject *self, + void *closure) +{ + if (!self->owner) + { + Py_INCREF(Py_None); + return Py_None; + } - Py_INCREF(self->parent); - return self->parent; + Py_INCREF(self->owner); + return self->owner; } /* ------------------------------------------------------------------------- */; static PyMethodDef WraptFunctionWrapperBase_methods[] = { - { "__set_name__", (PyCFunction)WraptFunctionWrapperBase_set_name, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__instancecheck__", (PyCFunction)WraptFunctionWrapperBase_instancecheck, - METH_O, 0}, - { "__subclasscheck__", (PyCFunction)WraptFunctionWrapperBase_subclasscheck, - METH_VARARGS, 0 }, - { NULL, NULL }, + {"__set_name__", (PyCFunction)WraptFunctionWrapperBase_set_name, + METH_VARARGS | METH_KEYWORDS, 0}, + {"__instancecheck__", (PyCFunction)WraptFunctionWrapperBase_instancecheck, + METH_O, 0}, + {"__subclasscheck__", (PyCFunction)WraptFunctionWrapperBase_subclasscheck, + METH_VARARGS, 0}, + {NULL, NULL}, }; /* ------------------------------------------------------------------------- */; static PyGetSetDef WraptFunctionWrapperBase_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { "_self_instance", (getter)WraptFunctionWrapperBase_get_self_instance, - NULL, 0 }, - { "_self_wrapper", (getter)WraptFunctionWrapperBase_get_self_wrapper, - NULL, 0 }, - { "_self_enabled", (getter)WraptFunctionWrapperBase_get_self_enabled, - NULL, 0 }, - { "_self_binding", (getter)WraptFunctionWrapperBase_get_self_binding, - NULL, 0 }, - { "_self_parent", (getter)WraptFunctionWrapperBase_get_self_parent, - NULL, 0 }, - { NULL }, + {"__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0}, + {"__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0}, + {"_self_instance", (getter)WraptFunctionWrapperBase_get_self_instance, NULL, + 0}, + {"_self_wrapper", (getter)WraptFunctionWrapperBase_get_self_wrapper, NULL, + 0}, + {"_self_enabled", (getter)WraptFunctionWrapperBase_get_self_enabled, NULL, + 0}, + {"_self_binding", (getter)WraptFunctionWrapperBase_get_self_binding, NULL, + 0}, + {"_self_parent", (getter)WraptFunctionWrapperBase_get_self_parent, NULL, 0}, + {"_self_owner", (getter)WraptFunctionWrapperBase_get_self_owner, NULL, 0}, + {NULL}, }; PyTypeObject WraptFunctionWrapperBase_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_FunctionWrapperBase", /*tp_name*/ - sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + PyVarObject_HEAD_INIT(NULL, 0) "_FunctionWrapperBase", /*tp_name*/ + sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ /* methods */ - (destructor)WraptFunctionWrapperBase_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)WraptFunctionWrapperBase_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - (traverseproc)WraptFunctionWrapperBase_traverse, /*tp_traverse*/ - (inquiry)WraptFunctionWrapperBase_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - WraptFunctionWrapperBase_methods, /*tp_methods*/ - 0, /*tp_members*/ - WraptFunctionWrapperBase_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - (descrgetfunc)WraptFunctionWrapperBase_descr_get, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - (initproc)WraptFunctionWrapperBase_init, /*tp_init*/ - 0, /*tp_alloc*/ - WraptFunctionWrapperBase_new, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ + (destructor)WraptFunctionWrapperBase_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)WraptFunctionWrapperBase_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + (traverseproc)WraptFunctionWrapperBase_traverse, /*tp_traverse*/ + (inquiry)WraptFunctionWrapperBase_clear, /*tp_clear*/ + 0, /*tp_richcompare*/ + offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + WraptFunctionWrapperBase_methods, /*tp_methods*/ + 0, /*tp_members*/ + WraptFunctionWrapperBase_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + (descrgetfunc)WraptFunctionWrapperBase_descr_get, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + (initproc)WraptFunctionWrapperBase_init, /*tp_init*/ + 0, /*tp_alloc*/ + WraptFunctionWrapperBase_new, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ }; /* ------------------------------------------------------------------------- */ -static PyObject *WraptBoundFunctionWrapper_call( - WraptFunctionWrapperObject *self, PyObject *args, PyObject *kwds) +static PyObject * +WraptBoundFunctionWrapper_call(WraptFunctionWrapperObject *self, PyObject *args, + PyObject *kwds) { - PyObject *param_args = NULL; - PyObject *param_kwds = NULL; - - PyObject *wrapped = NULL; - PyObject *instance = NULL; - - PyObject *result = NULL; - - static PyObject *function_str = NULL; - - if (self->enabled != Py_None) { - if (PyCallable_Check(self->enabled)) { - PyObject *object = NULL; - - object = PyObject_CallFunctionObjArgs(self->enabled, NULL); - - if (!object) - return NULL; - - if (PyObject_Not(object)) { - Py_DECREF(object); - return PyObject_Call(self->object_proxy.wrapped, args, kwds); - } + PyObject *param_args = NULL; + PyObject *param_kwds = NULL; - Py_DECREF(object); - } - else if (PyObject_Not(self->enabled)) { - return PyObject_Call(self->object_proxy.wrapped, args, kwds); - } - } - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); -#else - function_str = PyString_InternFromString("function"); -#endif - } + PyObject *wrapped = NULL; + PyObject *instance = NULL; - /* - * We need to do things different depending on whether we are likely - * wrapping an instance method vs a static method or class method. - */ + PyObject *result = NULL; - if (self->binding == function_str || PyObject_RichCompareBool( - self->binding, function_str, Py_EQ) == 1) { + static PyObject *function_str = NULL; + static PyObject *callable_str = NULL; - if (self->instance == Py_None) { - /* - * This situation can occur where someone is calling the - * instancemethod via the class type and passing the - * instance as the first argument. We need to shift the args - * before making the call to the wrapper and effectively - * bind the instance to the wrapped function using a partial - * so the wrapper doesn't see anything as being different. - */ + if (self->enabled != Py_None) + { + if (PyCallable_Check(self->enabled)) + { + PyObject *object = NULL; - if (PyTuple_Size(args) == 0) { - PyErr_SetString(PyExc_TypeError, - "missing 1 required positional argument"); - return NULL; - } + object = PyObject_CallFunctionObjArgs(self->enabled, NULL); - instance = PyTuple_GetItem(args, 0); - - if (!instance) - return NULL; + if (!object) + return NULL; - wrapped = PyObject_CallFunctionObjArgs( - (PyObject *)&WraptPartialCallableObjectProxy_Type, - self->object_proxy.wrapped, instance, NULL); + if (PyObject_Not(object)) + { + Py_DECREF(object); + return PyObject_Call(self->object_proxy.wrapped, args, kwds); + } + + Py_DECREF(object); + } + else if (PyObject_Not(self->enabled)) + { + return PyObject_Call(self->object_proxy.wrapped, args, kwds); + } + } + + if (!function_str) + { + function_str = PyUnicode_InternFromString("function"); + callable_str = PyUnicode_InternFromString("callable"); + } + + /* + * We need to do things different depending on whether we are likely + * wrapping an instance method vs a static method or class method. + */ + + if (self->binding == function_str || + PyObject_RichCompareBool(self->binding, function_str, Py_EQ) == 1 || + self->binding == callable_str || + PyObject_RichCompareBool(self->binding, callable_str, Py_EQ) == 1) + { + + // if (self->instance == Py_None) { + // /* + // * This situation can occur where someone is calling the + // * instancemethod via the class type and passing the + // * instance as the first argument. We need to shift the args + // * before making the call to the wrapper and effectively + // * bind the instance to the wrapped function using a partial + // * so the wrapper doesn't see anything as being different. + // */ + + // if (PyTuple_Size(args) == 0) { + // PyErr_SetString(PyExc_TypeError, + // "missing 1 required positional argument"); + // return NULL; + // } + + // instance = PyTuple_GetItem(args, 0); + + // if (!instance) + // return NULL; + + // wrapped = PyObject_CallFunctionObjArgs( + // (PyObject *)&WraptPartialCallableObjectProxy_Type, + // self->object_proxy.wrapped, instance, NULL); + + // if (!wrapped) + // return NULL; + + // param_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); + + // if (!param_args) { + // Py_DECREF(wrapped); + // return NULL; + // } + + // args = param_args; + // } + + if (self->instance == Py_None && PyTuple_Size(args) != 0) + { + /* + * This situation can occur where someone is calling the + * instancemethod via the class type and passing the + * instance as the first argument. We need to shift the args + * before making the call to the wrapper and effectively + * bind the instance to the wrapped function using a partial + * so the wrapper doesn't see anything as being different. + */ + + instance = PyTuple_GetItem(args, 0); + + if (!instance) + return NULL; - if (!wrapped) - return NULL; + if (PyObject_IsInstance(instance, self->owner) == 1) + { + wrapped = PyObject_CallFunctionObjArgs( + (PyObject *)&WraptPartialCallableObjectProxy_Type, + self->object_proxy.wrapped, instance, NULL); - param_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); + if (!wrapped) + return NULL; - if (!param_args) { - Py_DECREF(wrapped); - return NULL; - } + param_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); - args = param_args; + if (!param_args) + { + Py_DECREF(wrapped); + return NULL; } - else - instance = self->instance; - if (!wrapped) { - Py_INCREF(self->object_proxy.wrapped); - wrapped = self->object_proxy.wrapped; - } + args = param_args; + } + else + { + instance = self->instance; + } + } + else + { + instance = self->instance; + } - if (!kwds) { - param_kwds = PyDict_New(); - kwds = param_kwds; - } + if (!wrapped) + { + Py_INCREF(self->object_proxy.wrapped); + wrapped = self->object_proxy.wrapped; + } - result = PyObject_CallFunctionObjArgs(self->wrapper, wrapped, - instance, args, kwds, NULL); - - Py_XDECREF(param_args); - Py_XDECREF(param_kwds); - Py_DECREF(wrapped); - - return result; - } - else { - /* - * As in this case we would be dealing with a classmethod or - * staticmethod, then _self_instance will only tell us whether - * when calling the classmethod or staticmethod they did it via - * an instance of the class it is bound to and not the case - * where done by the class type itself. We thus ignore - * _self_instance and use the __self__ attribute of the bound - * function instead. For a classmethod, this means instance will - * be the class type and for a staticmethod it will be None. - * This is probably the more useful thing we can pass through - * even though we loose knowledge of whether they were called on - * the instance vs the class type, as it reflects what they have - * available in the decoratored function. - */ - - instance = PyObject_GetAttrString(self->object_proxy.wrapped, - "__self__"); - - if (!instance) { - PyErr_Clear(); - Py_INCREF(Py_None); - instance = Py_None; - } + if (!kwds) + { + param_kwds = PyDict_New(); + kwds = param_kwds; + } - if (!kwds) { - param_kwds = PyDict_New(); - kwds = param_kwds; - } + result = PyObject_CallFunctionObjArgs(self->wrapper, wrapped, instance, + args, kwds, NULL); + + Py_XDECREF(param_args); + Py_XDECREF(param_kwds); + Py_DECREF(wrapped); - result = PyObject_CallFunctionObjArgs(self->wrapper, - self->object_proxy.wrapped, instance, args, kwds, NULL); + return result; + } + else + { + /* + * As in this case we would be dealing with a classmethod or + * staticmethod, then _self_instance will only tell us whether + * when calling the classmethod or staticmethod they did it via + * an instance of the class it is bound to and not the case + * where done by the class type itself. We thus ignore + * _self_instance and use the __self__ attribute of the bound + * function instead. For a classmethod, this means instance will + * be the class type and for a staticmethod it will be None. + * This is probably the more useful thing we can pass through + * even though we loose knowledge of whether they were called on + * the instance vs the class type, as it reflects what they have + * available in the decoratored function. + */ + + instance = PyObject_GetAttrString(self->object_proxy.wrapped, "__self__"); + + if (!instance) + { + PyErr_Clear(); + Py_INCREF(Py_None); + instance = Py_None; + } + + if (!kwds) + { + param_kwds = PyDict_New(); + kwds = param_kwds; + } + + result = PyObject_CallFunctionObjArgs( + self->wrapper, self->object_proxy.wrapped, instance, args, kwds, NULL); - Py_XDECREF(param_kwds); + Py_XDECREF(param_kwds); - Py_DECREF(instance); + Py_DECREF(instance); - return result; - } + return result; + } } /* ------------------------------------------------------------------------- */ static PyGetSetDef WraptBoundFunctionWrapper_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { NULL }, + {"__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0}, + {"__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0}, + {NULL}, }; PyTypeObject WraptBoundFunctionWrapper_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "BoundFunctionWrapper", /*tp_name*/ - sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + PyVarObject_HEAD_INIT(NULL, 0) "BoundFunctionWrapper", /*tp_name*/ + sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ /* methods */ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)WraptBoundFunctionWrapper_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)WraptBoundFunctionWrapper_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - WraptBoundFunctionWrapper_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + WraptBoundFunctionWrapper_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + 0, /*tp_alloc*/ + 0, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ }; /* ------------------------------------------------------------------------- */ static int WraptFunctionWrapper_init(WraptFunctionWrapperObject *self, - PyObject *args, PyObject *kwds) + PyObject *args, PyObject *kwds) { - PyObject *wrapped = NULL; - PyObject *wrapper = NULL; - PyObject *enabled = Py_None; - PyObject *binding = NULL; - PyObject *instance = NULL; - - static PyObject *classmethod_str = NULL; - static PyObject *staticmethod_str = NULL; - static PyObject *function_str = NULL; - - int result = 0; - - static char *kwlist[] = { "wrapped", "wrapper", "enabled", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:FunctionWrapper", - kwlist, &wrapped, &wrapper, &enabled)) { - return -1; - } - - if (!classmethod_str) { -#if PY_MAJOR_VERSION >= 3 - classmethod_str = PyUnicode_InternFromString("classmethod"); -#else - classmethod_str = PyString_InternFromString("classmethod"); -#endif - } - - if (!staticmethod_str) { -#if PY_MAJOR_VERSION >= 3 - staticmethod_str = PyUnicode_InternFromString("staticmethod"); -#else - staticmethod_str = PyString_InternFromString("staticmethod"); -#endif - } - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); -#else - function_str = PyString_InternFromString("function"); -#endif - } - - if (PyObject_IsInstance(wrapped, (PyObject *)&PyClassMethod_Type)) { + PyObject *wrapped = NULL; + PyObject *wrapper = NULL; + PyObject *enabled = Py_None; + PyObject *binding = NULL; + PyObject *instance = NULL; + + static PyObject *function_str = NULL; + static PyObject *classmethod_str = NULL; + static PyObject *staticmethod_str = NULL; + static PyObject *callable_str = NULL; + static PyObject *builtin_str = NULL; + static PyObject *class_str = NULL; + static PyObject *instancemethod_str = NULL; + + int result = 0; + + char *const kwlist[] = {"wrapped", "wrapper", "enabled", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:FunctionWrapper", kwlist, + &wrapped, &wrapper, &enabled)) + { + return -1; + } + + if (!function_str) + { + function_str = PyUnicode_InternFromString("function"); + } + + if (!classmethod_str) + { + classmethod_str = PyUnicode_InternFromString("classmethod"); + } + + if (!staticmethod_str) + { + staticmethod_str = PyUnicode_InternFromString("staticmethod"); + } + + if (!callable_str) + { + callable_str = PyUnicode_InternFromString("callable"); + } + + if (!builtin_str) + { + builtin_str = PyUnicode_InternFromString("builtin"); + } + + if (!class_str) + { + class_str = PyUnicode_InternFromString("class"); + } + + if (!instancemethod_str) + { + instancemethod_str = PyUnicode_InternFromString("instancemethod"); + } + + if (PyObject_IsInstance(wrapped, + (PyObject *)&WraptFunctionWrapperBase_Type)) + { + binding = PyObject_GetAttrString(wrapped, "_self_binding"); + } + + if (!binding) + { + if (PyCFunction_Check(wrapped)) + { + binding = builtin_str; + } + else if (PyObject_IsInstance(wrapped, (PyObject *)&PyFunction_Type)) + { + binding = function_str; + } + else if (PyObject_IsInstance(wrapped, (PyObject *)&PyClassMethod_Type)) + { + binding = classmethod_str; + } + else if (PyObject_IsInstance(wrapped, (PyObject *)&PyType_Type)) + { + binding = class_str; + } + else if (PyObject_IsInstance(wrapped, (PyObject *)&PyStaticMethod_Type)) + { + binding = staticmethod_str; + } + else if ((instance = PyObject_GetAttrString(wrapped, "__self__")) != 0) + { + if (PyObject_IsInstance(instance, (PyObject *)&PyType_Type)) + { binding = classmethod_str; - } - else if (PyObject_IsInstance(wrapped, (PyObject *)&PyStaticMethod_Type)) { - binding = staticmethod_str; - } - else if ((instance = PyObject_GetAttrString(wrapped, "__self__")) != 0) { -#if PY_MAJOR_VERSION < 3 - if (PyObject_IsInstance(instance, (PyObject *)&PyClass_Type) || - PyObject_IsInstance(instance, (PyObject *)&PyType_Type)) { - binding = classmethod_str; - } -#else - if (PyObject_IsInstance(instance, (PyObject *)&PyType_Type)) { - binding = classmethod_str; - } -#endif - else - binding = function_str; + } + else if (PyObject_IsInstance(wrapped, (PyObject *)&PyMethod_Type)) + { + binding = instancemethod_str; + } + else + binding = callable_str; - Py_DECREF(instance); + Py_DECREF(instance); } - else { - PyErr_Clear(); + else + { + PyErr_Clear(); - binding = function_str; + binding = callable_str; } + } - result = WraptFunctionWrapperBase_raw_init(self, wrapped, Py_None, - wrapper, enabled, binding, Py_None); + result = WraptFunctionWrapperBase_raw_init( + self, wrapped, Py_None, wrapper, enabled, binding, Py_None, Py_None); - return result; + return result; } /* ------------------------------------------------------------------------- */ static PyGetSetDef WraptFunctionWrapper_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { NULL }, + {"__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0}, + {"__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0}, + {NULL}, }; PyTypeObject WraptFunctionWrapper_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "FunctionWrapper", /*tp_name*/ - sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + PyVarObject_HEAD_INIT(NULL, 0) "FunctionWrapper", /*tp_name*/ + sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ /* methods */ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - WraptFunctionWrapper_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - (initproc)WraptFunctionWrapper_init, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + WraptFunctionWrapper_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + (initproc)WraptFunctionWrapper_init, /*tp_init*/ + 0, /*tp_alloc*/ + 0, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ }; /* ------------------------------------------------------------------------- */ -#if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, - "_wrappers", /* m_name */ - NULL, /* m_doc */ - -1, /* m_size */ - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + "_wrappers", /* m_name */ + NULL, /* m_doc */ + -1, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; -#endif -static PyObject * -moduleinit(void) +static PyObject *moduleinit(void) { - PyObject *module; - -#if PY_MAJOR_VERSION >= 3 - module = PyModule_Create(&moduledef); -#else - module = Py_InitModule3("_wrappers", NULL, NULL); -#endif + PyObject *module; - if (module == NULL) - return NULL; + module = PyModule_Create(&moduledef); - if (PyType_Ready(&WraptObjectProxy_Type) < 0) - return NULL; + if (module == NULL) + return NULL; - /* Ensure that inheritance relationships specified. */ + if (PyType_Ready(&WraptObjectProxy_Type) < 0) + return NULL; - WraptCallableObjectProxy_Type.tp_base = &WraptObjectProxy_Type; - WraptPartialCallableObjectProxy_Type.tp_base = &WraptObjectProxy_Type; - WraptFunctionWrapperBase_Type.tp_base = &WraptObjectProxy_Type; - WraptBoundFunctionWrapper_Type.tp_base = &WraptFunctionWrapperBase_Type; - WraptFunctionWrapper_Type.tp_base = &WraptFunctionWrapperBase_Type; + /* Ensure that inheritance relationships specified. */ - if (PyType_Ready(&WraptCallableObjectProxy_Type) < 0) - return NULL; - if (PyType_Ready(&WraptPartialCallableObjectProxy_Type) < 0) - return NULL; - if (PyType_Ready(&WraptFunctionWrapperBase_Type) < 0) - return NULL; - if (PyType_Ready(&WraptBoundFunctionWrapper_Type) < 0) - return NULL; - if (PyType_Ready(&WraptFunctionWrapper_Type) < 0) - return NULL; + WraptCallableObjectProxy_Type.tp_base = &WraptObjectProxy_Type; + WraptPartialCallableObjectProxy_Type.tp_base = &WraptObjectProxy_Type; + WraptFunctionWrapperBase_Type.tp_base = &WraptObjectProxy_Type; + WraptBoundFunctionWrapper_Type.tp_base = &WraptFunctionWrapperBase_Type; + WraptFunctionWrapper_Type.tp_base = &WraptFunctionWrapperBase_Type; - Py_INCREF(&WraptObjectProxy_Type); - PyModule_AddObject(module, "ObjectProxy", - (PyObject *)&WraptObjectProxy_Type); - Py_INCREF(&WraptCallableObjectProxy_Type); - PyModule_AddObject(module, "CallableObjectProxy", - (PyObject *)&WraptCallableObjectProxy_Type); - PyModule_AddObject(module, "PartialCallableObjectProxy", - (PyObject *)&WraptPartialCallableObjectProxy_Type); - Py_INCREF(&WraptFunctionWrapper_Type); - PyModule_AddObject(module, "FunctionWrapper", - (PyObject *)&WraptFunctionWrapper_Type); + if (PyType_Ready(&WraptCallableObjectProxy_Type) < 0) + return NULL; + if (PyType_Ready(&WraptPartialCallableObjectProxy_Type) < 0) + return NULL; + if (PyType_Ready(&WraptFunctionWrapperBase_Type) < 0) + return NULL; + if (PyType_Ready(&WraptBoundFunctionWrapper_Type) < 0) + return NULL; + if (PyType_Ready(&WraptFunctionWrapper_Type) < 0) + return NULL; - Py_INCREF(&WraptFunctionWrapperBase_Type); - PyModule_AddObject(module, "_FunctionWrapperBase", - (PyObject *)&WraptFunctionWrapperBase_Type); - Py_INCREF(&WraptBoundFunctionWrapper_Type); - PyModule_AddObject(module, "BoundFunctionWrapper", - (PyObject *)&WraptBoundFunctionWrapper_Type); + Py_INCREF(&WraptObjectProxy_Type); + PyModule_AddObject(module, "ObjectProxy", (PyObject *)&WraptObjectProxy_Type); + Py_INCREF(&WraptCallableObjectProxy_Type); + PyModule_AddObject(module, "CallableObjectProxy", + (PyObject *)&WraptCallableObjectProxy_Type); + Py_INCREF(&WraptPartialCallableObjectProxy_Type); + PyModule_AddObject(module, "PartialCallableObjectProxy", + (PyObject *)&WraptPartialCallableObjectProxy_Type); + Py_INCREF(&WraptFunctionWrapper_Type); + PyModule_AddObject(module, "FunctionWrapper", + (PyObject *)&WraptFunctionWrapper_Type); + + Py_INCREF(&WraptFunctionWrapperBase_Type); + PyModule_AddObject(module, "_FunctionWrapperBase", + (PyObject *)&WraptFunctionWrapperBase_Type); + Py_INCREF(&WraptBoundFunctionWrapper_Type); + PyModule_AddObject(module, "BoundFunctionWrapper", + (PyObject *)&WraptBoundFunctionWrapper_Type); + +#ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED); +#endif - return module; + return module; } -#if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC init_wrappers(void) -{ - moduleinit(); -} -#else -PyMODINIT_FUNC PyInit__wrappers(void) -{ - return moduleinit(); -} -#endif +PyMODINIT_FUNC PyInit__wrappers(void) { return moduleinit(); } /* ------------------------------------------------------------------------- */ diff --git a/newrelic/packages/wrapt/arguments.py b/newrelic/packages/wrapt/arguments.py index 032bc059e0..554f62cd28 100644 --- a/newrelic/packages/wrapt/arguments.py +++ b/newrelic/packages/wrapt/arguments.py @@ -1,16 +1,35 @@ -# The inspect.formatargspec() function was dropped in Python 3.11 but we need -# need it for when constructing signature changing decorators based on result of -# inspect.getargspec() or inspect.getfullargspec(). The code here implements -# inspect.formatargspec() base on Parameter and Signature from inspect module, -# which were added in Python 3.6. Thanks to Cyril Jouve for the implementation. +"""The inspect.formatargspec() function was dropped in Python 3.11 but we need +it for when constructing signature changing decorators based on result of +inspect.getfullargspec(). The code here implements inspect.formatargspec() based +on Parameter and Signature from inspect module, which were added in Python 3.6. +Thanks to Cyril Jouve for the implementation. +""" + +from typing import Any, Callable, List, Mapping, Optional, Sequence, Tuple try: from inspect import Parameter, Signature except ImportError: - from inspect import formatargspec + from inspect import formatargspec # type: ignore[attr-defined] else: - def formatargspec(args, varargs=None, varkw=None, defaults=None, - kwonlyargs=(), kwonlydefaults={}, annotations={}): + + def formatargspec( + args: List[str], + varargs: Optional[str] = None, + varkw: Optional[str] = None, + defaults: Optional[Tuple[Any, ...]] = None, + kwonlyargs: Optional[Sequence[str]] = None, + kwonlydefaults: Optional[Mapping[str, Any]] = None, + annotations: Mapping[str, Any] = {}, + formatarg: Callable[[str], str] = str, + formatvarargs: Callable[[str], str] = lambda name: "*" + name, + formatvarkw: Callable[[str], str] = lambda name: "**" + name, + formatvalue: Callable[[Any], str] = lambda value: "=" + repr(value), + formatreturns: Callable[[Any], str] = lambda text: " -> " + text, + formatannotation: Callable[[Any], str] = lambda annot: " -> " + repr(annot), + ) -> str: + if kwonlyargs is None: + kwonlyargs = () if kwonlydefaults is None: kwonlydefaults = {} ndefaults = len(defaults) if defaults else 0 @@ -18,9 +37,10 @@ def formatargspec(args, varargs=None, varkw=None, defaults=None, Parameter( arg, Parameter.POSITIONAL_OR_KEYWORD, - default=defaults[i] if i >= 0 else Parameter.empty, + default=defaults[i] if defaults and i >= 0 else Parameter.empty, annotation=annotations.get(arg, Parameter.empty), - ) for i, arg in enumerate(args, ndefaults - len(args)) + ) + for i, arg in enumerate(args, ndefaults - len(args)) ] if varargs: parameters.append(Parameter(varargs, Parameter.VAR_POSITIONAL)) @@ -30,9 +50,10 @@ def formatargspec(args, varargs=None, varkw=None, defaults=None, Parameter.KEYWORD_ONLY, default=kwonlydefaults.get(kwonlyarg, Parameter.empty), annotation=annotations.get(kwonlyarg, Parameter.empty), - ) for kwonlyarg in kwonlyargs + ) + for kwonlyarg in kwonlyargs ) if varkw: parameters.append(Parameter(varkw, Parameter.VAR_KEYWORD)) - return_annotation = annotations.get('return', Signature.empty) - return str(Signature(parameters, return_annotation=return_annotation)) \ No newline at end of file + return_annotation = annotations.get("return", Signature.empty) + return str(Signature(parameters, return_annotation=return_annotation)) diff --git a/newrelic/packages/wrapt/decorators.py b/newrelic/packages/wrapt/decorators.py index c80a4bb72e..6f5cedd2a4 100644 --- a/newrelic/packages/wrapt/decorators.py +++ b/newrelic/packages/wrapt/decorators.py @@ -4,51 +4,18 @@ """ import sys - -PY2 = sys.version_info[0] == 2 - -if PY2: - string_types = basestring, - - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - -else: - string_types = str, - - import builtins - - exec_ = getattr(builtins, "exec") - del builtins - from functools import partial -from inspect import isclass +from inspect import isclass, signature from threading import Lock, RLock +from .__wrapt__ import BoundFunctionWrapper, CallableObjectProxy, FunctionWrapper from .arguments import formatargspec -try: - from inspect import signature -except ImportError: - pass - -from .__wrapt__ import (FunctionWrapper, BoundFunctionWrapper, ObjectProxy, - CallableObjectProxy) - # Adapter wrapper for the wrapped function which will overlay certain # properties from the adapter function onto the wrapped function so that -# functions such as inspect.getargspec(), inspect.getfullargspec(), -# inspect.signature() and inspect.getsource() return the correct results -# one would expect. +# functions such as inspect.getfullargspec(), inspect.signature() and +# inspect.getsource() return the correct results one would expect. + class _AdapterFunctionCode(CallableObjectProxy): @@ -76,6 +43,7 @@ def co_kwonlyargcount(self): def co_varnames(self): return self._self_adapter_code.co_varnames + class _AdapterFunctionSurrogate(CallableObjectProxy): def __init__(self, wrapped, adapter): @@ -84,8 +52,9 @@ def __init__(self, wrapped, adapter): @property def __code__(self): - return _AdapterFunctionCode(self.__wrapped__.__code__, - self._self_adapter.__code__) + return _AdapterFunctionCode( + self.__wrapped__.__code__, self._self_adapter.__code__ + ) @property def __defaults__(self): @@ -97,41 +66,36 @@ def __kwdefaults__(self): @property def __signature__(self): - if 'signature' not in globals(): + if "signature" not in globals(): return self._self_adapter.__signature__ else: return signature(self._self_adapter) - if PY2: - func_code = __code__ - func_defaults = __defaults__ class _BoundAdapterWrapper(BoundFunctionWrapper): @property def __func__(self): - return _AdapterFunctionSurrogate(self.__wrapped__.__func__, - self._self_parent._self_adapter) + return _AdapterFunctionSurrogate( + self.__wrapped__.__func__, self._self_parent._self_adapter + ) @property def __signature__(self): - if 'signature' not in globals(): + if "signature" not in globals(): return self.__wrapped__.__signature__ else: return signature(self._self_parent._self_adapter) - if PY2: - im_func = __func__ class AdapterWrapper(FunctionWrapper): __bound_function_wrapper__ = _BoundAdapterWrapper def __init__(self, *args, **kwargs): - adapter = kwargs.pop('adapter') + adapter = kwargs.pop("adapter") super(AdapterWrapper, self).__init__(*args, **kwargs) - self._self_surrogate = _AdapterFunctionSurrogate( - self.__wrapped__, adapter) + self._self_surrogate = _AdapterFunctionSurrogate(self.__wrapped__, adapter) self._self_adapter = adapter @property @@ -146,25 +110,25 @@ def __defaults__(self): def __kwdefaults__(self): return self._self_surrogate.__kwdefaults__ - if PY2: - func_code = __code__ - func_defaults = __defaults__ - @property def __signature__(self): return self._self_surrogate.__signature__ -class AdapterFactory(object): + +class AdapterFactory: def __call__(self, wrapped): raise NotImplementedError() + class DelegatedAdapterFactory(AdapterFactory): def __init__(self, factory): super(DelegatedAdapterFactory, self).__init__() self.factory = factory + def __call__(self, wrapped): return self.factory(wrapped) + adapter_factory = DelegatedAdapterFactory # Decorator for creating other decorators. This decorator and the @@ -174,29 +138,32 @@ def __call__(self, wrapped): # function so the wrapper is effectively indistinguishable from the # original wrapped function. -def decorator(wrapper=None, enabled=None, adapter=None, proxy=FunctionWrapper): - # The decorator should be supplied with a single positional argument - # which is the wrapper function to be used to implement the - # decorator. This may be preceded by a step whereby the keyword - # arguments are supplied to customise the behaviour of the - # decorator. The 'adapter' argument is used to optionally denote a - # separate function which is notionally used by an adapter - # decorator. In that case parts of the function '__code__' and - # '__defaults__' attributes are used from the adapter function - # rather than those of the wrapped function. This allows for the - # argument specification from inspect.getfullargspec() and similar - # functions to be overridden with a prototype for a different - # function than what was wrapped. The 'enabled' argument provides a - # way to enable/disable the use of the decorator. If the type of - # 'enabled' is a boolean, then it is evaluated immediately and the - # wrapper not even applied if it is False. If not a boolean, it will - # be evaluated when the wrapper is called for an unbound wrapper, - # and when binding occurs for a bound wrapper. When being evaluated, - # if 'enabled' is callable it will be called to obtain the value to - # be checked. If False, the wrapper will not be called and instead - # the original wrapped function will be called directly instead. - # The 'proxy' argument provides a way of passing a custom version of - # the FunctionWrapper class used in decorating the function. + +def decorator(wrapper=None, /, *, enabled=None, adapter=None, proxy=FunctionWrapper): + """ + The decorator should be supplied with a single positional argument + which is the `wrapper` function to be used to implement the + decorator. This may be preceded by a step whereby the keyword + arguments are supplied to customise the behaviour of the + decorator. The `adapter` argument is used to optionally denote a + separate function which is notionally used by an adapter + decorator. In that case parts of the function `__code__` and + `__defaults__` attributes are used from the adapter function + rather than those of the wrapped function. This allows for the + argument specification from `inspect.getfullargspec()` and similar + functions to be overridden with a prototype for a different + function than what was wrapped. The `enabled` argument provides a + way to enable/disable the use of the decorator. If the type of + `enabled` is a boolean, then it is evaluated immediately and the + wrapper not even applied if it is `False`. If not a boolean, it will + be evaluated when the wrapper is called for an unbound wrapper, + and when binding occurs for a bound wrapper. When being evaluated, + if `enabled` is callable it will be called to obtain the value to + be checked. If `False`, the wrapper will not be called and instead + the original wrapped function will be called directly instead. + The `proxy` argument provides a way of passing a custom version of + the `FunctionWrapper` class used in decorating the function. + """ if wrapper is not None: # Helper function for creating wrapper of the appropriate @@ -220,14 +187,14 @@ def _build(wrapped, wrapper, enabled=None, adapter=None): annotations = {} - if not isinstance(adapter, string_types): + if not isinstance(adapter, str): if len(adapter) == 7: annotations = adapter[-1] adapter = adapter[:-1] adapter = formatargspec(*adapter) - exec_('def adapter{}: pass'.format(adapter), ns, ns) - adapter = ns['adapter'] + exec(f"def adapter{adapter}: pass", ns, ns) + adapter = ns["adapter"] # Override the annotations for the manufactured # adapter function so they match the original @@ -236,8 +203,9 @@ def _build(wrapped, wrapper, enabled=None, adapter=None): if annotations: adapter.__annotations__ = annotations - return AdapterWrapper(wrapped=wrapped, wrapper=wrapper, - enabled=enabled, adapter=adapter) + return AdapterWrapper( + wrapped=wrapped, wrapper=wrapper, enabled=enabled, adapter=adapter + ) return proxy(wrapped=wrapped, wrapper=wrapper, enabled=enabled) @@ -253,7 +221,7 @@ def _wrapper(wrapped, instance, args, kwargs): # to a class type. # # @decorator - # class mydecoratorclass(object): + # class mydecoratorclass: # def __init__(self, arg=None): # self.arg = arg # def __call__(self, wrapped, instance, args, kwargs): @@ -297,8 +265,7 @@ def _capture(target_wrapped): # Finally build the wrapper itself and return it. - return _build(target_wrapped, target_wrapper, - _enabled, adapter) + return _build(target_wrapped, target_wrapper, _enabled, adapter) return _capture @@ -328,7 +295,7 @@ def _capture(target_wrapped): # as the decorator wrapper function. # # @decorator - # class mydecoratorclass(object): + # class mydecoratorclass: # def __init__(self, arg=None): # self.arg = arg # def __call__(self, wrapped, instance, @@ -368,7 +335,7 @@ def _capture(target_wrapped): # In this case the decorator was applied to a class # method. # - # class myclass(object): + # class myclass: # @decorator # @classmethod # def decoratorclassmethod(cls, wrapped, @@ -393,7 +360,7 @@ def _capture(target_wrapped): # In this case the decorator was applied to an instance # method. # - # class myclass(object): + # class myclass: # @decorator # def decoratorclassmethod(self, wrapped, # instance, args, kwargs): @@ -432,8 +399,8 @@ def _capture(target_wrapped): # decorator again wrapped in a partial using the collected # arguments. - return partial(decorator, enabled=enabled, adapter=adapter, - proxy=proxy) + return partial(decorator, enabled=enabled, adapter=adapter, proxy=proxy) + # Decorator for implementing thread synchronization. It can be used as a # decorator, in which case the synchronization context is determined by @@ -445,14 +412,27 @@ def _capture(target_wrapped): # synchronization primitive without creating a separate lock against the # derived or supplied context. + def synchronized(wrapped): + """Depending on the nature of the `wrapped` object, will either return a + decorator which can be used to wrap a function or method, or a context + manager, both of which will act accordingly depending on how used, to + synchronize access to calling of the wrapped function, or the block of + code within the context manager. If it is an object which is a + synchronization primitive, such as a threading Lock, RLock, Semaphore, + Condition, or Event, then it is assumed that the object is to be used + directly as the synchronization primitive, otherwise a lock is created + automatically and attached to the wrapped object and used as the + synchronization primitive. + """ + # Determine if being passed an object which is a synchronization # primitive. We can't check by type for Lock, RLock, Semaphore etc, # as the means of creating them isn't the type. Therefore use the # existence of acquire() and release() methods. This is more # extensible anyway as it allows custom synchronization mechanisms. - if hasattr(wrapped, 'acquire') and hasattr(wrapped, 'release'): + if hasattr(wrapped, "acquire") and hasattr(wrapped, "release"): # We remember what the original lock is and then return a new # decorator which accesses and locks it. When returning the new # decorator we wrap it with an object proxy so we can override @@ -489,7 +469,7 @@ def __exit__(self, *args): def _synchronized_lock(context): # Attempt to retrieve the lock for the specific context. - lock = vars(context).get('_synchronized_lock', None) + lock = vars(context).get("_synchronized_lock", None) if lock is None: # There is no existing lock defined for the context we @@ -510,11 +490,11 @@ def _synchronized_lock(context): # at the same time and were competing to create the # meta lock. - lock = vars(context).get('_synchronized_lock', None) + lock = vars(context).get("_synchronized_lock", None) if lock is None: lock = RLock() - setattr(context, '_synchronized_lock', lock) + setattr(context, "_synchronized_lock", lock) return lock @@ -538,4 +518,5 @@ def __exit__(self, *args): return _FinalDecorator(wrapped=wrapped, wrapper=_synchronized_wrapper) -synchronized._synchronized_meta_lock = Lock() + +synchronized._synchronized_meta_lock = Lock() # type: ignore[attr-defined] diff --git a/newrelic/packages/wrapt/importer.py b/newrelic/packages/wrapt/importer.py index 23fcbd2f63..a1e0cb7c59 100644 --- a/newrelic/packages/wrapt/importer.py +++ b/newrelic/packages/wrapt/importer.py @@ -3,19 +3,13 @@ """ +import importlib.metadata import sys import threading +from importlib.util import find_spec +from typing import Callable, Dict, List -PY2 = sys.version_info[0] == 2 - -if PY2: - string_types = basestring, - find_spec = None -else: - string_types = str, - from importlib.util import find_spec - -from .__wrapt__ import ObjectProxy +from .__wrapt__ import BaseObjectProxy # The dictionary registering any post import hooks to be triggered once # the target module has been imported. Once a module has been imported @@ -23,7 +17,7 @@ # module will be truncated but the list left in the dictionary. This # acts as a flag to indicate that the module had already been imported. -_post_import_hooks = {} +_post_import_hooks: Dict[str, List[Callable]] = {} _post_import_hooks_init = False _post_import_hooks_lock = threading.RLock() @@ -34,22 +28,36 @@ # proxy callback being registered which will defer loading of the # specified module containing the callback function until required. + def _create_import_hook_from_string(name): def import_hook(module): - module_name, function = name.split(':') - attrs = function.split('.') + module_name, function = name.split(":") + attrs = function.split(".") __import__(module_name) callback = sys.modules[module_name] for attr in attrs: callback = getattr(callback, attr) return callback(module) + return import_hook + def register_post_import_hook(hook, name): + """ + Register a post import hook for the target module `name`. The `hook` + function will be called once the module is imported and will be passed the + module as argument. If the module is already imported, the `hook` will be + called immediately. If you also want to defer loading of the module containing + the `hook` function until required, you can specify the `hook` as a string in + the form 'module:function'. This will result in a proxy hook function being + registered which will defer loading of the specified module containing the + callback function until required. + """ + # Create a deferred import hook if hook is a string name rather than # a callable function. - if isinstance(hook, string_types): + if isinstance(hook, str): hook = _create_import_hook_from_string(hook) with _post_import_hooks_lock: @@ -78,34 +86,59 @@ def register_post_import_hook(hook, name): if module is not None: hook(module) + # Register post import hooks defined as package entry points. + def _create_import_hook_from_entrypoint(entrypoint): def import_hook(module): - __import__(entrypoint.module_name) - callback = sys.modules[entrypoint.module_name] - for attr in entrypoint.attrs: - callback = getattr(callback, attr) + entrypoint_value = entrypoint.value.split(":") + module_name = entrypoint_value[0] + __import__(module_name) + callback = sys.modules[module_name] + + if len(entrypoint_value) > 1: + attrs = entrypoint_value[1].split(".") + for attr in attrs: + callback = getattr(callback, attr) return callback(module) + return import_hook + def discover_post_import_hooks(group): - try: - import pkg_resources - except ImportError: - return + """ + Discover and register post import hooks defined as package entry points + in the specified `group`. The group should be a string that matches the + entry point group name used in the package metadata. + """ - for entrypoint in pkg_resources.iter_entry_points(group=group): - callback = _create_import_hook_from_entrypoint(entrypoint) + try: + # Python 3.10+ style with select parameter + entrypoints = importlib.metadata.entry_points(group=group) + except TypeError: + # Python 3.8-3.9 style that returns a dict + entrypoints = importlib.metadata.entry_points().get(group, ()) + + for entrypoint in entrypoints: + callback = entrypoint.load() # Use the loaded callback directly register_post_import_hook(callback, entrypoint.name) + # Indicate that a module has been loaded. Any post import hooks which # were registered against the target module will be invoked. If an # exception is raised in any of the post import hooks, that will cause # the import of the target module to fail. + def notify_module_loaded(module): - name = getattr(module, '__name__', None) + """ + Notify that a `module` has been loaded and invoke any post import hooks + registered against the module. If the module is not registered, this + function does nothing. + """ + + name = getattr(module, "__name__", None) with _post_import_hooks_lock: hooks = _post_import_hooks.pop(name, ()) @@ -117,11 +150,13 @@ def notify_module_loaded(module): for hook in hooks: hook(module) + # A custom module import finder. This intercepts attempts to import # modules and watches out for attempts to import target modules of # interest. When a module of interest is imported, then any post import # hooks which are registered will be invoked. + class _ImportHookLoader: def load_module(self, fullname): @@ -130,17 +165,18 @@ def load_module(self, fullname): return module -class _ImportHookChainedLoader(ObjectProxy): + +class _ImportHookChainedLoader(BaseObjectProxy): def __init__(self, loader): super(_ImportHookChainedLoader, self).__init__(loader) if hasattr(loader, "load_module"): - self.__self_setattr__('load_module', self._self_load_module) + self.__self_setattr__("load_module", self._self_load_module) if hasattr(loader, "create_module"): - self.__self_setattr__('create_module', self._self_create_module) + self.__self_setattr__("create_module", self._self_create_module) if hasattr(loader, "exec_module"): - self.__self_setattr__('exec_module', self._self_exec_module) + self.__self_setattr__("exec_module", self._self_exec_module) def _self_set_loader(self, module): # Set module's loader to self.__wrapped__ unless it's already set to @@ -148,13 +184,14 @@ def _self_set_loader(self, module): # None, so handle None as well. The module may not support attribute # assignment, in which case we simply skip it. Note that we also deal # with __loader__ not existing at all. This is to future proof things - # due to proposal to remove the attribue as described in the GitHub + # due to proposal to remove the attribute as described in the GitHub # issue at https://github.com/python/cpython/issues/77458. Also prior # to Python 3.3, the __loader__ attribute was only set if a custom # module loader was used. It isn't clear whether the attribute still # existed in that case or was set to None. - class UNDEFINED: pass + class UNDEFINED: + pass if getattr(module, "__loader__", UNDEFINED) in (None, self): try: @@ -162,8 +199,10 @@ class UNDEFINED: pass except AttributeError: pass - if (getattr(module, "__spec__", None) is not None - and getattr(module.__spec__, "loader", None) is self): + if ( + getattr(module, "__spec__", None) is not None + and getattr(module.__spec__, "loader", None) is self + ): module.__spec__.loader = self.__wrapped__ def _self_load_module(self, fullname): @@ -184,6 +223,7 @@ def _self_exec_module(self, module): self.__wrapped__.exec_module(module) notify_module_loaded(module) + class ImportHookFinder: def __init__(self): @@ -213,32 +253,18 @@ def find_module(self, fullname, path=None): # Now call back into the import system again. try: - if not find_spec: - # For Python 2 we don't have much choice but to - # call back in to __import__(). This will - # actually cause the module to be imported. If no - # module could be found then ImportError will be - # raised. Otherwise we return a loader which - # returns the already loaded module and invokes - # the post import hooks. - - __import__(fullname) + # For Python 3 we need to use find_spec().loader + # from the importlib.util module. It doesn't actually + # import the target module and only finds the + # loader. If a loader is found, we need to return + # our own loader which will then in turn call the + # real loader to import the module and invoke the + # post import hooks. - return _ImportHookLoader() + loader = getattr(find_spec(fullname), "loader", None) - else: - # For Python 3 we need to use find_spec().loader - # from the importlib.util module. It doesn't actually - # import the target module and only finds the - # loader. If a loader is found, we need to return - # our own loader which will then in turn call the - # real loader to import the module and invoke the - # post import hooks. - - loader = getattr(find_spec(fullname), "loader", None) - - if loader and not isinstance(loader, _ImportHookChainedLoader): - return _ImportHookChainedLoader(loader) + if loader and not isinstance(loader, _ImportHookChainedLoader): + return _ImportHookChainedLoader(loader) finally: del self.in_progress[fullname] @@ -285,11 +311,22 @@ def find_spec(self, fullname, path=None, target=None): finally: del self.in_progress[fullname] + # Decorator for marking that a function should be called as a post # import hook when the target module is imported. + def when_imported(name): + """ + Returns a decorator that registers the decorated function as a post import + hook for the module specified by `name`. The function will be called once + the module with the specified name is imported, and will be passed the + module as argument. If the module is already imported, the function will + be called immediately. + """ + def register(hook): register_post_import_hook(hook, name) return hook + return register diff --git a/newrelic/packages/wrapt/patches.py b/newrelic/packages/wrapt/patches.py index e22adf7ca8..f5f1fc3ca9 100644 --- a/newrelic/packages/wrapt/patches.py +++ b/newrelic/packages/wrapt/patches.py @@ -1,25 +1,29 @@ import inspect import sys -PY2 = sys.version_info[0] == 2 - -if PY2: - string_types = basestring, -else: - string_types = str, - from .__wrapt__ import FunctionWrapper # Helper functions for applying wrappers to existing functions. -def resolve_path(module, name): - if isinstance(module, string_types): - __import__(module) - module = sys.modules[module] - parent = module +def resolve_path(target, name): + """ + Resolves the dotted path supplied as `name` to an attribute on a target + object. The `target` can be a module, class, or instance of a class. If the + `target` argument is a string, it is assumed to be the name of a module, + which will be imported if necessary and then used as the target object. + Returns a tuple containing the parent object holding the attribute lookup + resolved to, the attribute name (path prefix removed if present), and the + original attribute value. + """ + + if isinstance(target, str): + __import__(target) + target = sys.modules[target] - path = name.split('.') + parent = target + + path = name.split(".") attribute = path[0] # We can't just always use getattr() because in doing @@ -53,22 +57,46 @@ def lookup_attribute(parent, attribute): return (parent, attribute, original) + def apply_patch(parent, attribute, replacement): + """ + Convenience function for applying a patch to an attribute. Currently this + maps to the standard setattr() function, but in the future may be extended + to support more complex patching strategies. + """ + setattr(parent, attribute, replacement) -def wrap_object(module, name, factory, args=(), kwargs={}): - (parent, attribute, original) = resolve_path(module, name) + +def wrap_object(target, name, factory, args=(), kwargs={}): + """ + Wraps an object which is the attribute of a target object with a wrapper + object created by the `factory` function. The `target` can be a module, + class, or instance of a class. In the special case of `target` being a + string, it is assumed to be the name of a module, with the module being + imported if necessary and then used as the target object. The `name` is a + string representing the dotted path to the attribute. The `factory` function + should accept the original object and may accept additional positional and + keyword arguments which will be set by unpacking input arguments using + `*args` and `**kwargs` calling conventions. The factory function should + return a new object that will replace the original object. + """ + + (parent, attribute, original) = resolve_path(target, name) wrapper = factory(original, *args, **kwargs) apply_patch(parent, attribute, wrapper) + return wrapper + # Function for applying a proxy object to an attribute of a class # instance. The wrapper works by defining an attribute of the same name # on the class which is a descriptor and which intercepts access to the # instance attribute. Note that this cannot be used on attributes which # are themselves defined by a property object. -class AttributeWrapper(object): + +class AttributeWrapper: def __init__(self, attribute, factory, args, kwargs): self.attribute = attribute @@ -86,19 +114,47 @@ def __set__(self, instance, value): def __delete__(self, instance): del instance.__dict__[self.attribute] + def wrap_object_attribute(module, name, factory, args=(), kwargs={}): - path, attribute = name.rsplit('.', 1) + """ + Wraps an object which is the attribute of a class instance with a wrapper + object created by the `factory` function. It does this by patching the + class, not the instance, with a descriptor that intercepts access to the + instance attribute. The `module` can be a module, class, or instance of a + class. In the special case of `module` being a string, it is assumed to be + the name of a module, with the module being imported if necessary and then + used as the target object. The `name` is a string representing the dotted + path to the attribute. The `factory` function should accept the original + object and may accept additional positional and keyword arguments which will + be set by unpacking input arguments using `*args` and `**kwargs` calling + conventions. The factory function should return a new object that will + replace the original object. + """ + + path, attribute = name.rsplit(".", 1) parent = resolve_path(module, path)[2] wrapper = AttributeWrapper(attribute, factory, args, kwargs) apply_patch(parent, attribute, wrapper) return wrapper + # Functions for creating a simple decorator using a FunctionWrapper, # plus short cut functions for applying wrappers to functions. These are # for use when doing monkey patching. For a more featured way of # creating decorators see the decorator decorator instead. + def function_wrapper(wrapper): + """ + Creates a decorator for wrapping a function with a `wrapper` function. + The decorator which is returned may also be applied to any other callable + objects such as lambda functions, methods, classmethods, and staticmethods, + or objects which implement the `__call__()` method. The `wrapper` function + should accept the `wrapped` function, `instance`, `args`, and `kwargs`, + arguments and return the result of calling the wrapped function or some + other appropriate value. + """ + def _wrapper(wrapped, instance, args, kwargs): target_wrapped = args[0] if instance is None: @@ -108,17 +164,55 @@ def _wrapper(wrapped, instance, args, kwargs): else: target_wrapper = wrapper.__get__(instance, type(instance)) return FunctionWrapper(target_wrapped, target_wrapper) + return FunctionWrapper(wrapper, _wrapper) -def wrap_function_wrapper(module, name, wrapper): - return wrap_object(module, name, FunctionWrapper, (wrapper,)) -def patch_function_wrapper(module, name, enabled=None): +def wrap_function_wrapper(target, name, wrapper): + """ + Wraps a function which is the attribute of a target object with a `wrapper` + function. The `target` can be a module, class, or instance of a class. In + the special case of `target` being a string, it is assumed to be the name + of a module, with the module being imported if necessary. The `name` is a + string representing the dotted path to the attribute. The `wrapper` function + should accept the `wrapped` function, `instance`, `args`, and `kwargs` + arguments, and would return the result of calling the wrapped attribute or + some other appropriate value. + """ + + return wrap_object(target, name, FunctionWrapper, (wrapper,)) + + +def patch_function_wrapper(target, name, enabled=None): + """ + Creates a decorator which can be applied to a wrapper function, where the + wrapper function will be used to wrap a function which is the attribute of + a target object. The `target` can be a module, class, or instance of a class. + In the special case of `target` being a string, it is assumed to be the name + of a module, with the module being imported if necessary. The `name` is a + string representing the dotted path to the attribute. The `enabled` + argument can be a boolean or a callable that returns a boolean. When a + callable is provided, it will be called each time the wrapper is invoked to + determine if the wrapper function should be executed or whether the wrapped + function should be called directly. If `enabled` is not provided, the + wrapper is enabled by default. + """ + def _wrapper(wrapper): - return wrap_object(module, name, FunctionWrapper, (wrapper, enabled)) + return wrap_object(target, name, FunctionWrapper, (wrapper, enabled)) + return _wrapper -def transient_function_wrapper(module, name): + +def transient_function_wrapper(target, name): + """Creates a decorator that patches a target function with a wrapper + function, but only for the duration of the call that the decorator was + applied to. The `target` can be a module, class, or instance of a class. + In the special case of `target` being a string, it is assumed to be the name + of a module, with the module being imported if necessary. The `name` is a + string representing the dotted path to the attribute. + """ + def _decorator(wrapper): def _wrapper(wrapped, instance, args, kwargs): target_wrapped = args[0] @@ -128,14 +222,18 @@ def _wrapper(wrapped, instance, args, kwargs): target_wrapper = wrapper.__get__(None, instance) else: target_wrapper = wrapper.__get__(instance, type(instance)) + def _execute(wrapped, instance, args, kwargs): - (parent, attribute, original) = resolve_path(module, name) + (parent, attribute, original) = resolve_path(target, name) replacement = FunctionWrapper(original, target_wrapper) setattr(parent, attribute, replacement) try: return wrapped(*args, **kwargs) finally: setattr(parent, attribute, original) + return FunctionWrapper(target_wrapped, _execute) + return FunctionWrapper(wrapper, _wrapper) + return _decorator diff --git a/newrelic/packages/wrapt/proxies.py b/newrelic/packages/wrapt/proxies.py new file mode 100644 index 0000000000..60261da21a --- /dev/null +++ b/newrelic/packages/wrapt/proxies.py @@ -0,0 +1,282 @@ +"""Variants of ObjectProxy for different use cases.""" + +from .__wrapt__ import BaseObjectProxy +from .decorators import synchronized + +# Define ObjectProxy which for compatibility adds `__iter__()` support which +# has been removed from `BaseObjectProxy`. + + +class ObjectProxy(BaseObjectProxy): + """A generic object proxy which forwards special methods as needed. + For backwards compatibility this class adds support for `__iter__()`. If + you don't need backward compatibility for `__iter__()` support then it is + preferable to use `BaseObjectProxy` directly. If you want automatic + support for special dunder methods for callables, iterators, and async, + then use `AutoObjectProxy`.""" + + @property + def __object_proxy__(self): + return ObjectProxy + + def __new__(cls, *args, **kwargs): + return super().__new__(cls) + + def __iter__(self): + return iter(self.__wrapped__) + + +# Define variant of ObjectProxy which can automatically adjust to the wrapped +# object and add special dunder methods. + + +def __wrapper_call__(self, *args, **kwargs): + return self.__wrapped__(*args, **kwargs) + + +def __wrapper_iter__(self): + return iter(self.__wrapped__) + + +def __wrapper_next__(self): + return self.__wrapped__.__next__() + + +def __wrapper_aiter__(self): + return self.__wrapped__.__aiter__() + + +async def __wrapper_anext__(self): + return await self.__wrapped__.__anext__() + + +def __wrapper_length_hint__(self): + return self.__wrapped__.__length_hint__() + + +def __wrapper_await__(self): + return (yield from self.__wrapped__.__await__()) + + +def __wrapper_get__(self, instance, owner): + return self.__wrapped__.__get__(instance, owner) + + +def __wrapper_set__(self, instance, value): + return self.__wrapped__.__set__(instance, value) + + +def __wrapper_delete__(self, instance): + return self.__wrapped__.__delete__(instance) + + +def __wrapper_set_name__(self, owner, name): + return self.__wrapped__.__set_name__(owner, name) + + +class AutoObjectProxy(BaseObjectProxy): + """An object proxy which can automatically adjust to the wrapped object + and add special dunder methods as needed. Note that this creates a new + class for each instance, so it has much higher memory overhead than using + `BaseObjectProxy` directly. If you know what special dunder methods you need + then it is preferable to use `BaseObjectProxy` directly and add them to a + subclass as needed. If you only need `__iter__()` support for backwards + compatibility then use `ObjectProxy` instead. + """ + + def __new__(cls, wrapped): + """Injects special dunder methods into a dynamically created subclass + as needed based on the wrapped object. + """ + + namespace = {} + + wrapped_attrs = dir(wrapped) + class_attrs = set(dir(cls)) + + if callable(wrapped) and "__call__" not in class_attrs: + namespace["__call__"] = __wrapper_call__ + + if "__iter__" in wrapped_attrs and "__iter__" not in class_attrs: + namespace["__iter__"] = __wrapper_iter__ + + if "__next__" in wrapped_attrs and "__next__" not in class_attrs: + namespace["__next__"] = __wrapper_next__ + + if "__aiter__" in wrapped_attrs and "__aiter__" not in class_attrs: + namespace["__aiter__"] = __wrapper_aiter__ + + if "__anext__" in wrapped_attrs and "__anext__" not in class_attrs: + namespace["__anext__"] = __wrapper_anext__ + + if "__length_hint__" in wrapped_attrs and "__length_hint__" not in class_attrs: + namespace["__length_hint__"] = __wrapper_length_hint__ + + # Note that not providing compatibility with generator-based coroutines + # (PEP 342) here as they are removed in Python 3.11+ and were deprecated + # in 3.8. + + if "__await__" in wrapped_attrs and "__await__" not in class_attrs: + namespace["__await__"] = __wrapper_await__ + + if "__get__" in wrapped_attrs and "__get__" not in class_attrs: + namespace["__get__"] = __wrapper_get__ + + if "__set__" in wrapped_attrs and "__set__" not in class_attrs: + namespace["__set__"] = __wrapper_set__ + + if "__delete__" in wrapped_attrs and "__delete__" not in class_attrs: + namespace["__delete__"] = __wrapper_delete__ + + if "__set_name__" in wrapped_attrs and "__set_name__" not in class_attrs: + namespace["__set_name__"] = __wrapper_set_name__ + + name = cls.__name__ + + if cls is AutoObjectProxy: + name = BaseObjectProxy.__name__ + + return super().__new__(type(name, (cls,), namespace)) + + def __wrapped_setattr_fixups__(self): + """Adjusts special dunder methods on the class as needed based on the + wrapped object, when `__wrapped__` is changed. + """ + + cls = type(self) + class_attrs = set(dir(cls)) + + if callable(self.__wrapped__): + if "__call__" not in class_attrs: + cls.__call__ = __wrapper_call__ + elif getattr(cls, "__call__", None) is __wrapper_call__: + delattr(cls, "__call__") + + if hasattr(self.__wrapped__, "__iter__"): + if "__iter__" not in class_attrs: + cls.__iter__ = __wrapper_iter__ + elif getattr(cls, "__iter__", None) is __wrapper_iter__: + delattr(cls, "__iter__") + + if hasattr(self.__wrapped__, "__next__"): + if "__next__" not in class_attrs: + cls.__next__ = __wrapper_next__ + elif getattr(cls, "__next__", None) is __wrapper_next__: + delattr(cls, "__next__") + + if hasattr(self.__wrapped__, "__aiter__"): + if "__aiter__" not in class_attrs: + cls.__aiter__ = __wrapper_aiter__ + elif getattr(cls, "__aiter__", None) is __wrapper_aiter__: + delattr(cls, "__aiter__") + + if hasattr(self.__wrapped__, "__anext__"): + if "__anext__" not in class_attrs: + cls.__anext__ = __wrapper_anext__ + elif getattr(cls, "__anext__", None) is __wrapper_anext__: + delattr(cls, "__anext__") + + if hasattr(self.__wrapped__, "__length_hint__"): + if "__length_hint__" not in class_attrs: + cls.__length_hint__ = __wrapper_length_hint__ + elif getattr(cls, "__length_hint__", None) is __wrapper_length_hint__: + delattr(cls, "__length_hint__") + + if hasattr(self.__wrapped__, "__await__"): + if "__await__" not in class_attrs: + cls.__await__ = __wrapper_await__ + elif getattr(cls, "__await__", None) is __wrapper_await__: + delattr(cls, "__await__") + + if hasattr(self.__wrapped__, "__get__"): + if "__get__" not in class_attrs: + cls.__get__ = __wrapper_get__ + elif getattr(cls, "__get__", None) is __wrapper_get__: + delattr(cls, "__get__") + + if hasattr(self.__wrapped__, "__set__"): + if "__set__" not in class_attrs: + cls.__set__ = __wrapper_set__ + elif getattr(cls, "__set__", None) is __wrapper_set__: + delattr(cls, "__set__") + + if hasattr(self.__wrapped__, "__delete__"): + if "__delete__" not in class_attrs: + cls.__delete__ = __wrapper_delete__ + elif getattr(cls, "__delete__", None) is __wrapper_delete__: + delattr(cls, "__delete__") + + if hasattr(self.__wrapped__, "__set_name__"): + if "__set_name__" not in class_attrs: + cls.__set_name__ = __wrapper_set_name__ + elif getattr(cls, "__set_name__", None) is __wrapper_set_name__: + delattr(cls, "__set_name__") + + +class LazyObjectProxy(AutoObjectProxy): + """An object proxy which can generate/create the wrapped object on demand + when it is first needed. + """ + + def __new__(cls, callback=None): + return super().__new__(cls, None) + + def __init__(self, callback=None): + """Initialize the object proxy with wrapped object as `None` but due + to presence of special `__wrapped_factory__` attribute addded first, + this will actually trigger the deferred creation of the wrapped object + when first needed. + """ + + if callback is not None: + self.__wrapped_factory__ = callback + + super().__init__(None) + + __wrapped_initialized__ = False + + def __wrapped_factory__(self): + return None + + def __wrapped_get__(self): + """Gets the wrapped object, creating it if necessary.""" + + # We synchronize on the class type, which will be unique to this instance + # since we inherit from `AutoObjectProxy` which creates a new class + # for each instance. If we synchronize on `self` or the method then + # we can end up in infinite recursion via `__getattr__()`. + + with synchronized(type(self)): + # We were called because `__wrapped__` was not set, but because of + # multiple threads we may find that it has been set by the time + # we get the lock. So check again now whether `__wrapped__` is set. + # If it is then just return it, otherwise call the factory to + # create it. + + if self.__wrapped_initialized__: + return self.__wrapped__ + + self.__wrapped__ = self.__wrapped_factory__() + + self.__wrapped_initialized__ = True + + return self.__wrapped__ + + +def lazy_import(name, attribute=None): + """Lazily imports the module `name`, returning a `LazyObjectProxy` which + will import the module when it is first needed. When `name is a dotted name, + then the full dotted name is imported and the last module is taken as the + target. If `attribute` is provided then it is used to retrieve an attribute + from the module. + """ + + def _import(): + module = __import__(name, fromlist=[""]) + + if attribute is not None: + return getattr(module, attribute) + + return module + + return LazyObjectProxy(_import) diff --git a/newrelic/packages/wrapt/py.typed b/newrelic/packages/wrapt/py.typed new file mode 100644 index 0000000000..b648ac9233 --- /dev/null +++ b/newrelic/packages/wrapt/py.typed @@ -0,0 +1 @@ +partial diff --git a/newrelic/packages/wrapt/weakrefs.py b/newrelic/packages/wrapt/weakrefs.py index f931b60d5f..dc8e7eb2d3 100644 --- a/newrelic/packages/wrapt/weakrefs.py +++ b/newrelic/packages/wrapt/weakrefs.py @@ -1,7 +1,7 @@ import functools import weakref -from .__wrapt__ import ObjectProxy, _FunctionWrapperBase +from .__wrapt__ import BaseObjectProxy, _FunctionWrapperBase # A weak function proxy. This will work on instance methods, class # methods, static methods and regular functions. Special treatment is @@ -12,6 +12,7 @@ # and the original function. The function is then rebound at the point # of a call via the weak function proxy. + def _weak_function_proxy_callback(ref, proxy, callback): if proxy._self_expired: return @@ -25,11 +26,25 @@ def _weak_function_proxy_callback(ref, proxy, callback): if callback is not None: callback(proxy) -class WeakFunctionProxy(ObjectProxy): - __slots__ = ('_self_expired', '_self_instance') +class WeakFunctionProxy(BaseObjectProxy): + """A weak function proxy.""" + + __slots__ = ("_self_expired", "_self_instance") def __init__(self, wrapped, callback=None): + """Create a proxy to object which uses a weak reference. This is + similar to the `weakref.proxy` but is designed to work with functions + and methods. It will automatically rebind the function to the instance + when called if the function was originally a bound method. This is + necessary because bound methods are transient objects and applying a + weak reference to one will immediately result in it being destroyed + and the weakref callback called. The weak reference is therefore + applied to the instance the method is bound to and the original + function. The function is then rebound at the point of a call via the + weak function proxy. + """ + # We need to determine if the wrapped function is actually a # bound method. In the case of a bound method, we need to keep a # reference to the original unbound function and the instance. @@ -43,22 +58,23 @@ def __init__(self, wrapped, callback=None): # the callback here so as not to cause any odd reference cycles. _callback = callback and functools.partial( - _weak_function_proxy_callback, proxy=self, - callback=callback) + _weak_function_proxy_callback, proxy=self, callback=callback + ) self._self_expired = False if isinstance(wrapped, _FunctionWrapperBase): - self._self_instance = weakref.ref(wrapped._self_instance, - _callback) + self._self_instance = weakref.ref(wrapped._self_instance, _callback) if wrapped._self_parent is not None: super(WeakFunctionProxy, self).__init__( - weakref.proxy(wrapped._self_parent, _callback)) + weakref.proxy(wrapped._self_parent, _callback) + ) else: super(WeakFunctionProxy, self).__init__( - weakref.proxy(wrapped, _callback)) + weakref.proxy(wrapped, _callback) + ) return @@ -66,13 +82,13 @@ def __init__(self, wrapped, callback=None): self._self_instance = weakref.ref(wrapped.__self__, _callback) super(WeakFunctionProxy, self).__init__( - weakref.proxy(wrapped.__func__, _callback)) + weakref.proxy(wrapped.__func__, _callback) + ) except AttributeError: self._self_instance = None - super(WeakFunctionProxy, self).__init__( - weakref.proxy(wrapped, _callback)) + super(WeakFunctionProxy, self).__init__(weakref.proxy(wrapped, _callback)) def __call__(*args, **kwargs): def _unpack_self(self, *args): diff --git a/newrelic/packages/wrapt/wrappers.py b/newrelic/packages/wrapt/wrappers.py index dfc3440db4..445d0b2c6e 100644 --- a/newrelic/packages/wrapt/wrappers.py +++ b/newrelic/packages/wrapt/wrappers.py @@ -1,19 +1,24 @@ -import sys -import operator import inspect +import operator +import sys -PY2 = sys.version_info[0] == 2 - -if PY2: - string_types = basestring, -else: - string_types = str, def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" return meta("NewBase", bases, {}) -class _ObjectProxyMethods(object): + +class WrapperNotInitializedError(ValueError, AttributeError): + """ + Exception raised when a wrapper is accessed before it has been initialized. + To satisfy different situations where this could arise, we inherit from both + ValueError and AttributeError. + """ + + pass + + +class _ObjectProxyMethods: # We use properties to override the values of __module__ and # __doc__. If we add these in ObjectProxy, the derived class @@ -56,6 +61,7 @@ def __dict__(self): def __weakref__(self): return self.__wrapped__.__weakref__ + class _ObjectProxyMetaType(type): def __new__(cls, name, bases, dictionary): # Copy our special properties into the class so that they @@ -67,19 +73,47 @@ def __new__(cls, name, bases, dictionary): return type.__new__(cls, name, bases, dictionary) -class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): - __slots__ = '__wrapped__' +# NOTE: Although Python 3+ supports the newer metaclass=MetaClass syntax, +# we must continue using with_metaclass() for ObjectProxy. The newer syntax +# changes how __slots__ is handled during class creation, which would break +# the ability to set _self_* attributes on ObjectProxy instances. The +# with_metaclass() approach creates an intermediate base class that allows +# the necessary attribute flexibility while still applying the metaclass. + + +class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): # type: ignore[misc] + + __slots__ = "__wrapped__" def __init__(self, wrapped): - object.__setattr__(self, '__wrapped__', wrapped) + """Create an object proxy around the given object.""" + + if wrapped is None: + try: + callback = object.__getattribute__(self, "__wrapped_factory__") + except AttributeError: + callback = None + + if callback is not None: + # If wrapped is none and class has a __wrapped_factory__ + # method, then we don't set __wrapped__ yet and instead will + # defer creation of the wrapped object until it is first + # needed. + + pass + + else: + object.__setattr__(self, "__wrapped__", wrapped) + else: + object.__setattr__(self, "__wrapped__", wrapped) # Python 3.2+ has the __qualname__ attribute, but it does not # allow it to be overridden using a property and it must instead # be an actual string object instead. try: - object.__setattr__(self, '__qualname__', wrapped.__qualname__) + object.__setattr__(self, "__qualname__", wrapped.__qualname__) except AttributeError: pass @@ -87,10 +121,14 @@ def __init__(self, wrapped): # using a property and it must instead be set explicitly. try: - object.__setattr__(self, '__annotations__', wrapped.__annotations__) + object.__setattr__(self, "__annotations__", wrapped.__annotations__) except AttributeError: pass + @property + def __object_proxy__(self): + return ObjectProxy + def __self_setattr__(self, name, value): object.__setattr__(self, name, value) @@ -116,26 +154,27 @@ def __dir__(self): def __str__(self): return str(self.__wrapped__) - if not PY2: - def __bytes__(self): - return bytes(self.__wrapped__) + def __bytes__(self): + return bytes(self.__wrapped__) def __repr__(self): - return '<{} at 0x{:x} for {} at 0x{:x}>'.format( - type(self).__name__, id(self), - type(self.__wrapped__).__name__, - id(self.__wrapped__)) + return f"<{type(self).__name__} at 0x{id(self):x} for {type(self.__wrapped__).__name__} at 0x{id(self.__wrapped__):x}>" + + def __format__(self, format_spec): + return format(self.__wrapped__, format_spec) def __reversed__(self): return reversed(self.__wrapped__) - if not PY2: - def __round__(self): - return round(self.__wrapped__) + def __round__(self, ndigits=None): + return round(self.__wrapped__, ndigits) - if sys.hexversion >= 0x03070000: - def __mro_entries__(self, bases): - return (self.__wrapped__,) + def __mro_entries__(self, bases): + if not isinstance(self.__wrapped__, type) and hasattr( + self.__wrapped__, "__mro_entries__" + ): + return self.__wrapped__.__mro_entries__(bases) + return (self.__wrapped__,) def __lt__(self, other): return self.__wrapped__ < other @@ -165,33 +204,41 @@ def __bool__(self): return bool(self.__wrapped__) def __setattr__(self, name, value): - if name.startswith('_self_'): + if name.startswith("_self_"): object.__setattr__(self, name, value) - elif name == '__wrapped__': + elif name == "__wrapped__": object.__setattr__(self, name, value) + try: - object.__delattr__(self, '__qualname__') + object.__delattr__(self, "__qualname__") except AttributeError: pass try: - object.__setattr__(self, '__qualname__', value.__qualname__) + object.__setattr__(self, "__qualname__", value.__qualname__) except AttributeError: pass try: - object.__delattr__(self, '__annotations__') + object.__delattr__(self, "__annotations__") except AttributeError: pass try: - object.__setattr__(self, '__annotations__', value.__annotations__) + object.__setattr__(self, "__annotations__", value.__annotations__) except AttributeError: pass - elif name == '__qualname__': + __wrapped_setattr_fixups__ = getattr( + self, "__wrapped_setattr_fixups__", None + ) + + if __wrapped_setattr_fixups__ is not None: + __wrapped_setattr_fixups__() + + elif name == "__qualname__": setattr(self.__wrapped__, name, value) object.__setattr__(self, name, value) - elif name == '__annotations__': + elif name == "__annotations__": setattr(self.__wrapped__, name, value) object.__setattr__(self, name, value) @@ -202,22 +249,37 @@ def __setattr__(self, name, value): setattr(self.__wrapped__, name, value) def __getattr__(self, name): - # If we are being to lookup '__wrapped__' then the - # '__init__()' method cannot have been called. + # If we need to lookup `__wrapped__` then the `__init__()` method + # cannot have been called, or this is a lazy object proxy which is + # deferring creation of the wrapped object until it is first needed. + + if name == "__wrapped__": + # Note that we use existance of `__wrapped_factory__` to gate whether + # we can attempt to initialize the wrapped object lazily, but it is + # `__wrapped_get__` that we actually call to do the initialization. + # This is so that we can handle multithreading correctly by having + # `__wrapped_get__` use a lock to protect against multiple threads + # trying to initialize the wrapped object at the same time. - if name == '__wrapped__': - raise ValueError('wrapper has not been initialised') + try: + object.__getattribute__(self, "__wrapped_factory__") + except AttributeError: + pass + else: + return object.__getattribute__(self, "__wrapped_get__")() + + raise WrapperNotInitializedError("wrapper has not been initialized") return getattr(self.__wrapped__, name) def __delattr__(self, name): - if name.startswith('_self_'): + if name.startswith("_self_"): object.__delattr__(self, name) - elif name == '__wrapped__': - raise TypeError('__wrapped__ must be an object') + elif name == "__wrapped__": + raise TypeError("__wrapped__ attribute cannot be deleted") - elif name == '__qualname__': + elif name == "__qualname__": object.__delattr__(self, name) delattr(self.__wrapped__, name) @@ -236,9 +298,6 @@ def __sub__(self, other): def __mul__(self, other): return self.__wrapped__ * other - def __div__(self, other): - return operator.div(self.__wrapped__, other) - def __truediv__(self, other): return operator.truediv(self.__wrapped__, other) @@ -278,9 +337,6 @@ def __rsub__(self, other): def __rmul__(self, other): return other * self.__wrapped__ - def __rdiv__(self, other): - return operator.div(other, self.__wrapped__) - def __rtruediv__(self, other): return operator.truediv(other, self.__wrapped__) @@ -312,56 +368,90 @@ def __ror__(self, other): return other | self.__wrapped__ def __iadd__(self, other): - self.__wrapped__ += other - return self + if hasattr(self.__wrapped__, "__iadd__"): + self.__wrapped__ += other + return self + else: + return self.__object_proxy__(self.__wrapped__ + other) def __isub__(self, other): - self.__wrapped__ -= other - return self + if hasattr(self.__wrapped__, "__isub__"): + self.__wrapped__ -= other + return self + else: + return self.__object_proxy__(self.__wrapped__ - other) def __imul__(self, other): - self.__wrapped__ *= other - return self - - def __idiv__(self, other): - self.__wrapped__ = operator.idiv(self.__wrapped__, other) - return self + if hasattr(self.__wrapped__, "__imul__"): + self.__wrapped__ *= other + return self + else: + return self.__object_proxy__(self.__wrapped__ * other) def __itruediv__(self, other): - self.__wrapped__ = operator.itruediv(self.__wrapped__, other) - return self + if hasattr(self.__wrapped__, "__itruediv__"): + self.__wrapped__ /= other + return self + else: + return self.__object_proxy__(self.__wrapped__ / other) def __ifloordiv__(self, other): - self.__wrapped__ //= other - return self + if hasattr(self.__wrapped__, "__ifloordiv__"): + self.__wrapped__ //= other + return self + else: + return self.__object_proxy__(self.__wrapped__ // other) def __imod__(self, other): - self.__wrapped__ %= other - return self + if hasattr(self.__wrapped__, "__imod__"): + self.__wrapped__ %= other + return self + else: + return self.__object_proxy__(self.__wrapped__ % other) - def __ipow__(self, other): - self.__wrapped__ **= other return self + def __ipow__(self, other): # type: ignore[misc] + if hasattr(self.__wrapped__, "__ipow__"): + self.__wrapped__ **= other + return self + else: + return self.__object_proxy__(self.__wrapped__**other) + def __ilshift__(self, other): - self.__wrapped__ <<= other - return self + if hasattr(self.__wrapped__, "__ilshift__"): + self.__wrapped__ <<= other + return self + else: + return self.__object_proxy__(self.__wrapped__ << other) def __irshift__(self, other): - self.__wrapped__ >>= other - return self + if hasattr(self.__wrapped__, "__irshift__"): + self.__wrapped__ >>= other + return self + else: + return self.__object_proxy__(self.__wrapped__ >> other) def __iand__(self, other): - self.__wrapped__ &= other - return self + if hasattr(self.__wrapped__, "__iand__"): + self.__wrapped__ &= other + return self + else: + return self.__object_proxy__(self.__wrapped__ & other) def __ixor__(self, other): - self.__wrapped__ ^= other - return self + if hasattr(self.__wrapped__, "__ixor__"): + self.__wrapped__ ^= other + return self + else: + return self.__object_proxy__(self.__wrapped__ ^ other) def __ior__(self, other): - self.__wrapped__ |= other - return self + if hasattr(self.__wrapped__, "__ior__"): + self.__wrapped__ |= other + return self + else: + return self.__object_proxy__(self.__wrapped__ | other) def __neg__(self): return -self.__wrapped__ @@ -378,9 +468,6 @@ def __invert__(self): def __int__(self): return int(self.__wrapped__) - def __long__(self): - return long(self.__wrapped__) - def __float__(self): return float(self.__wrapped__) @@ -396,6 +483,19 @@ def __hex__(self): def __index__(self): return operator.index(self.__wrapped__) + def __matmul__(self, other): + return self.__wrapped__ @ other + + def __rmatmul__(self, other): + return other @ self.__wrapped__ + + def __imatmul__(self, other): + if hasattr(self.__wrapped__, "__imatmul__"): + self.__wrapped__ @= other + return self + else: + return self.__object_proxy__(self.__wrapped__ @ other) + def __len__(self): return len(self.__wrapped__) @@ -426,22 +526,24 @@ def __enter__(self): def __exit__(self, *args, **kwargs): return self.__wrapped__.__exit__(*args, **kwargs) - def __iter__(self): - return iter(self.__wrapped__) + def __aenter__(self): + return self.__wrapped__.__aenter__() + + def __aexit__(self, *args, **kwargs): + return self.__wrapped__.__aexit__(*args, **kwargs) def __copy__(self): - raise NotImplementedError('object proxy must define __copy__()') + raise NotImplementedError("object proxy must define __copy__()") def __deepcopy__(self, memo): - raise NotImplementedError('object proxy must define __deepcopy__()') + raise NotImplementedError("object proxy must define __deepcopy__()") def __reduce__(self): - raise NotImplementedError( - 'object proxy must define __reduce_ex__()') + raise NotImplementedError("object proxy must define __reduce__()") def __reduce_ex__(self, protocol): - raise NotImplementedError( - 'object proxy must define __reduce_ex__()') + raise NotImplementedError("object proxy must define __reduce_ex__()") + class CallableObjectProxy(ObjectProxy): @@ -453,21 +555,31 @@ def _unpack_self(self, *args): return self.__wrapped__(*args, **kwargs) + class PartialCallableObjectProxy(ObjectProxy): + """A callable object proxy that supports partial application of arguments + and keywords. + """ def __init__(*args, **kwargs): + """Create a callable object proxy with partial application of the given + arguments and keywords. This behaves the same as `functools.partial`, but + implemented using the `ObjectProxy` class to provide better support for + introspection. + """ + def _unpack_self(self, *args): return self, args self, args = _unpack_self(*args) if len(args) < 1: - raise TypeError('partial type takes at least one argument') + raise TypeError("partial type takes at least one argument") wrapped, args = args[0], args[1:] if not callable(wrapped): - raise TypeError('the first argument must be callable') + raise TypeError("the first argument must be callable") super(PartialCallableObjectProxy, self).__init__(wrapped) @@ -479,7 +591,7 @@ def _unpack_self(self, *args): return self, args self, args = _unpack_self(*args) - + _args = self._self_args + args _kwargs = dict(self._self_kwargs) @@ -487,75 +599,112 @@ def _unpack_self(self, *args): return self.__wrapped__(*_args, **_kwargs) -class _FunctionWrapperBase(ObjectProxy): - __slots__ = ('_self_instance', '_self_wrapper', '_self_enabled', - '_self_binding', '_self_parent') +class _FunctionWrapperBase(ObjectProxy): - def __init__(self, wrapped, instance, wrapper, enabled=None, - binding='function', parent=None): + __slots__ = ( + "_self_instance", + "_self_wrapper", + "_self_enabled", + "_self_binding", + "_self_parent", + "_self_owner", + ) + + def __init__( + self, + wrapped, + instance, + wrapper, + enabled=None, + binding="callable", + parent=None, + owner=None, + ): super(_FunctionWrapperBase, self).__init__(wrapped) - object.__setattr__(self, '_self_instance', instance) - object.__setattr__(self, '_self_wrapper', wrapper) - object.__setattr__(self, '_self_enabled', enabled) - object.__setattr__(self, '_self_binding', binding) - object.__setattr__(self, '_self_parent', parent) + object.__setattr__(self, "_self_instance", instance) + object.__setattr__(self, "_self_wrapper", wrapper) + object.__setattr__(self, "_self_enabled", enabled) + object.__setattr__(self, "_self_binding", binding) + object.__setattr__(self, "_self_parent", parent) + object.__setattr__(self, "_self_owner", owner) def __get__(self, instance, owner): - # This method is actually doing double duty for both unbound and - # bound derived wrapper classes. It should possibly be broken up - # and the distinct functionality moved into the derived classes. - # Can't do that straight away due to some legacy code which is - # relying on it being here in this base class. + # This method is actually doing double duty for both unbound and bound + # derived wrapper classes. It should possibly be broken up and the + # distinct functionality moved into the derived classes. Can't do that + # straight away due to some legacy code which is relying on it being + # here in this base class. # - # The distinguishing attribute which determines whether we are - # being called in an unbound or bound wrapper is the parent - # attribute. If binding has never occurred, then the parent will - # be None. + # The distinguishing attribute which determines whether we are being + # called in an unbound or bound wrapper is the parent attribute. If + # binding has never occurred, then the parent will be None. # - # First therefore, is if we are called in an unbound wrapper. In - # this case we perform the binding. + # First therefore, is if we are called in an unbound wrapper. In this + # case we perform the binding. # - # We have one special case to worry about here. This is where we - # are decorating a nested class. In this case the wrapped class - # would not have a __get__() method to call. In that case we - # simply return self. + # We have two special cases to worry about here. These are where we are + # decorating a class or builtin function as neither provide a __get__() + # method to call. In this case we simply return self. # - # Note that we otherwise still do binding even if instance is - # None and accessing an unbound instance method from a class. - # This is because we need to be able to later detect that - # specific case as we will need to extract the instance from the - # first argument of those passed in. + # Note that we otherwise still do binding even if instance is None and + # accessing an unbound instance method from a class. This is because we + # need to be able to later detect that specific case as we will need to + # extract the instance from the first argument of those passed in. if self._self_parent is None: - if not inspect.isclass(self.__wrapped__): - descriptor = self.__wrapped__.__get__(instance, owner) + # Technically can probably just check for existence of __get__ on + # the wrapped object, but this is more explicit. - return self.__bound_function_wrapper__(descriptor, instance, - self._self_wrapper, self._self_enabled, - self._self_binding, self) + if self._self_binding == "builtin": + return self - return self + if self._self_binding == "class": + return self + + binder = getattr(self.__wrapped__, "__get__", None) + + if binder is None: + return self - # Now we have the case of binding occurring a second time on what - # was already a bound function. In this case we would usually - # return ourselves again. This mirrors what Python does. + descriptor = binder(instance, owner) + + return self.__bound_function_wrapper__( + descriptor, + instance, + self._self_wrapper, + self._self_enabled, + self._self_binding, + self, + owner, + ) + + # Now we have the case of binding occurring a second time on what was + # already a bound function. In this case we would usually return + # ourselves again. This mirrors what Python does. # - # The special case this time is where we were originally bound - # with an instance of None and we were likely an instance - # method. In that case we rebind against the original wrapped - # function from the parent again. + # The special case this time is where we were originally bound with an + # instance of None and we were likely an instance method. In that case + # we rebind against the original wrapped function from the parent again. - if self._self_instance is None and self._self_binding == 'function': - descriptor = self._self_parent.__wrapped__.__get__( - instance, owner) + if self._self_instance is None and self._self_binding in ( + "function", + "instancemethod", + "callable", + ): + descriptor = self._self_parent.__wrapped__.__get__(instance, owner) return self._self_parent.__bound_function_wrapper__( - descriptor, instance, self._self_wrapper, - self._self_enabled, self._self_binding, - self._self_parent) + descriptor, + instance, + self._self_wrapper, + self._self_enabled, + self._self_binding, + self._self_parent, + owner, + ) return self @@ -582,12 +731,16 @@ def _unpack_self(self, *args): # a function that was already bound to an instance. In that case # we want to extract the instance from the function and use it. - if self._self_binding in ('function', 'classmethod'): + if self._self_binding in ( + "function", + "instancemethod", + "classmethod", + "callable", + ): if self._self_instance is None: - instance = getattr(self.__wrapped__, '__self__', None) + instance = getattr(self.__wrapped__, "__self__", None) if instance is not None: - return self._self_wrapper(self.__wrapped__, instance, - args, kwargs) + return self._self_wrapper(self.__wrapped__, instance, args, kwargs) # This is generally invoked when the wrapped function is being # called as a normal function and is not bound to a class as an @@ -595,8 +748,7 @@ def _unpack_self(self, *args): # wrapped function was a method, but this wrapper was in turn # wrapped using the staticmethod decorator. - return self._self_wrapper(self.__wrapped__, self._self_instance, - args, kwargs) + return self._self_wrapper(self.__wrapped__, self._self_instance, args, kwargs) def __set_name__(self, owner, name): # This is a special method use to supply information to @@ -625,6 +777,7 @@ def __subclasscheck__(self, subclass): else: return issubclass(subclass, self.__wrapped__) + class BoundFunctionWrapper(_FunctionWrapperBase): def __call__(*args, **kwargs): @@ -633,11 +786,11 @@ def _unpack_self(self, *args): self, args = _unpack_self(*args) - # If enabled has been specified, then evaluate it at this point - # and if the wrapper is not to be executed, then simply return - # the bound function rather than a bound wrapper for the bound - # function. When evaluating enabled, if it is callable we call - # it, otherwise we evaluate it as a boolean. + # If enabled has been specified, then evaluate it at this point and if + # the wrapper is not to be executed, then simply return the bound + # function rather than a bound wrapper for the bound function. When + # evaluating enabled, if it is callable we call it, otherwise we + # evaluate it as a boolean. if self._self_enabled is not None: if callable(self._self_enabled): @@ -646,28 +799,39 @@ def _unpack_self(self, *args): elif not self._self_enabled: return self.__wrapped__(*args, **kwargs) - # We need to do things different depending on whether we are - # likely wrapping an instance method vs a static method or class - # method. + # We need to do things different depending on whether we are likely + # wrapping an instance method vs a static method or class method. + + if self._self_binding == "function": + if self._self_instance is None and args: + instance, newargs = args[0], args[1:] + if isinstance(instance, self._self_owner): + wrapped = PartialCallableObjectProxy(self.__wrapped__, instance) + return self._self_wrapper(wrapped, instance, newargs, kwargs) - if self._self_binding == 'function': + return self._self_wrapper( + self.__wrapped__, self._self_instance, args, kwargs + ) + + elif self._self_binding == "callable": if self._self_instance is None: # This situation can occur where someone is calling the - # instancemethod via the class type and passing the instance - # as the first argument. We need to shift the args before - # making the call to the wrapper and effectively bind the - # instance to the wrapped function using a partial so the - # wrapper doesn't see anything as being different. + # instancemethod via the class type and passing the instance as + # the first argument. We need to shift the args before making + # the call to the wrapper and effectively bind the instance to + # the wrapped function using a partial so the wrapper doesn't + # see anything as being different. if not args: - raise TypeError('missing 1 required positional argument') + raise TypeError("missing 1 required positional argument") instance, args = args[0], args[1:] wrapped = PartialCallableObjectProxy(self.__wrapped__, instance) return self._self_wrapper(wrapped, instance, args, kwargs) - return self._self_wrapper(self.__wrapped__, self._self_instance, - args, kwargs) + return self._self_wrapper( + self.__wrapped__, self._self_instance, args, kwargs + ) else: # As in this case we would be dealing with a classmethod or @@ -683,16 +847,32 @@ def _unpack_self(self, *args): # class type, as it reflects what they have available in the # decoratored function. - instance = getattr(self.__wrapped__, '__self__', None) + instance = getattr(self.__wrapped__, "__self__", None) + + return self._self_wrapper(self.__wrapped__, instance, args, kwargs) - return self._self_wrapper(self.__wrapped__, instance, args, - kwargs) class FunctionWrapper(_FunctionWrapperBase): + """ + A wrapper for callable objects that can be used to apply decorators to + functions, methods, classmethods, and staticmethods, or any other callable. + It handles binding and unbinding of methods, and allows for the wrapper to + be enabled or disabled. + """ __bound_function_wrapper__ = BoundFunctionWrapper def __init__(self, wrapped, wrapper, enabled=None): + """ + Initialize the `FunctionWrapper` with the `wrapped` callable, the + `wrapper` function, and an optional `enabled` argument. The `enabled` + argument can be a boolean or a callable that returns a boolean. When a + callable is provided, it will be called each time the wrapper is + invoked to determine if the wrapper function should be executed or + whether the wrapped function should be called directly. If `enabled` + is not provided, the wrapper is enabled by default. + """ + # What it is we are wrapping here could be anything. We need to # try and detect specific cases though. In particular, we need # to detect when we are given something that is a method of a @@ -733,7 +913,7 @@ def __init__(self, wrapped, wrapper, enabled=None): # # 4. The wrapper is being applied when performing monkey # patching of an instance of a class. In this case binding will - # have been perfomed where the instance was not None. + # have been performed where the instance was not None. # # This case is a problem because we can no longer tell if the # method was a static method. @@ -759,26 +939,42 @@ def __init__(self, wrapped, wrapper, enabled=None): # or patch it in the __dict__ of the class type. # # So to get the best outcome we can, whenever we aren't sure what - # it is, we label it as a 'function'. If it was already bound and + # it is, we label it as a 'callable'. If it was already bound and # that is rebound later, we assume that it will be an instance - # method and try an cope with the possibility that the 'self' + # method and try and cope with the possibility that the 'self' # argument it being passed as an explicit argument and shuffle # the arguments around to extract 'self' for use as the instance. - if isinstance(wrapped, classmethod): - binding = 'classmethod' + binding = None - elif isinstance(wrapped, staticmethod): - binding = 'staticmethod' + if isinstance(wrapped, _FunctionWrapperBase): + binding = wrapped._self_binding - elif hasattr(wrapped, '__self__'): - if inspect.isclass(wrapped.__self__): - binding = 'classmethod' - else: - binding = 'function' + if not binding: + if inspect.isbuiltin(wrapped): + binding = "builtin" - else: - binding = 'function' + elif inspect.isfunction(wrapped): + binding = "function" + + elif inspect.isclass(wrapped): + binding = "class" + + elif isinstance(wrapped, classmethod): + binding = "classmethod" + + elif isinstance(wrapped, staticmethod): + binding = "staticmethod" + + elif hasattr(wrapped, "__self__"): + if inspect.isclass(wrapped.__self__): + binding = "classmethod" + elif inspect.ismethod(wrapped): + binding = "instancemethod" + else: + binding = "callable" + + else: + binding = "callable" - super(FunctionWrapper, self).__init__(wrapped, None, wrapper, - enabled, binding) + super(FunctionWrapper, self).__init__(wrapped, None, wrapper, enabled, binding) diff --git a/tests/datastore_aiomysql/test_database.py b/tests/datastore_aiomysql/test_database.py index 20d1a48586..8cc386cfe1 100644 --- a/tests/datastore_aiomysql/test_database.py +++ b/tests/datastore_aiomysql/test_database.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import inspect + import aiomysql from testing_support.db_settings import mysql_settings from testing_support.util import instance_hostname @@ -150,3 +152,35 @@ async def _test(): await pool.wait_closed() loop.run_until_complete(_test()) + + +@background_task() +def test_connection_pool_no_double_wrap(loop): + async def _test(): + pool = await aiomysql.create_pool( + db=DB_SETTINGS["name"], + user=DB_SETTINGS["user"], + password=DB_SETTINGS["password"], + host=DB_SETTINGS["host"], + port=DB_SETTINGS["port"], + loop=loop, + ) + + # Retrieve the same connection from the pool twice to see if it gets double wrapped + async with pool.acquire() as first_connection: + first_connection_unwrapped = inspect.unwrap(first_connection) + async with pool.acquire() as second_connection: + second_connection_unwrapped = inspect.unwrap(second_connection) + + # Ensure we actually retrieved the same underlying connection object from the pool twice + assert first_connection_unwrapped is second_connection_unwrapped, "Did not get same connection from pool" + + # Check that wrapping occurred only once + assert hasattr(first_connection, "__wrapped__"), "first_connection object was not wrapped" + assert hasattr(second_connection, "__wrapped__"), "second_connection object was not wrapped" + assert not hasattr(second_connection.__wrapped__, "__wrapped__"), "second_connection was double wrapped" + + pool.close() + await pool.wait_closed() + + loop.run_until_complete(_test()) diff --git a/tests/datastore_psycopg/test_cursor.py b/tests/datastore_psycopg/test_cursor.py index ef5eb939f9..f37f00710e 100644 --- a/tests/datastore_psycopg/test_cursor.py +++ b/tests/datastore_psycopg/test_cursor.py @@ -98,7 +98,7 @@ async def _execute(connection, cursor, row_type, wrapper): # Consume inserted records to check that returning param functions records = [] while True: - records.append(cursor.fetchone()) + records.append(await maybe_await(cursor.fetchone())) if not cursor.nextset(): break assert len(records) == len(params) @@ -140,7 +140,7 @@ async def _exercise_db(connection, row_factory=None, use_cur_context=False, row_ try: cursor = connection.cursor(**kwargs) if use_cur_context: - if hasattr(cursor, "__aenter__"): + if hasattr(cursor.__wrapped__, "__aenter__"): async with cursor: await _execute(connection, cursor, row_type, wrapper) else: diff --git a/tests/datastore_psycopg/test_register.py b/tests/datastore_psycopg/test_register.py index 46ea9dfcb4..dd605774f8 100644 --- a/tests/datastore_psycopg/test_register.py +++ b/tests/datastore_psycopg/test_register.py @@ -32,7 +32,7 @@ def test(): psycopg.types.json.set_json_loads(loads=lambda x: x, context=connection) psycopg.types.json.set_json_loads(loads=lambda x: x, context=cursor) - if hasattr(connection, "__aenter__"): + if hasattr(connection.__wrapped__, "__aenter__"): async def coro(): async with connection: @@ -69,7 +69,7 @@ async def test(): await maybe_await(cursor.execute(f"DROP TYPE if exists {type_name}")) - if hasattr(connection, "__aenter__"): + if hasattr(connection.__wrapped__, "__aenter__"): async def coro(): async with connection: diff --git a/tests/datastore_psycopg/test_rollback.py b/tests/datastore_psycopg/test_rollback.py index 2d652ee1ee..41849fa8e3 100644 --- a/tests/datastore_psycopg/test_rollback.py +++ b/tests/datastore_psycopg/test_rollback.py @@ -57,7 +57,7 @@ async def _exercise_db(connection): try: - if hasattr(connection, "__aenter__"): + if hasattr(connection.__wrapped__, "__aenter__"): async with connection: raise RuntimeError("error") else: diff --git a/tests/external_botocore/test_boto3_kinesis.py b/tests/external_botocore/test_boto3_kinesis.py index 9c03fa154a..9c92c669aa 100644 --- a/tests/external_botocore/test_boto3_kinesis.py +++ b/tests/external_botocore/test_boto3_kinesis.py @@ -46,6 +46,8 @@ } } +UNINSTRUMENTED_KINESIS_METHODS = ("generate_presigned_url", "close", "get_waiter", "can_paginate", "get_paginator") + _kinesis_scoped_metrics = [ (f"MessageBroker/Kinesis/Stream/Produce/Named/{TEST_STREAM}", 2), (f"MessageBroker/Kinesis/Stream/Consume/Named/{TEST_STREAM}", 1), @@ -117,10 +119,7 @@ def test_instrumented_kinesis_methods(): region_name=AWS_REGION, ) - ignored_methods = { - ("kinesis", method) - for method in ("generate_presigned_url", "close", "get_waiter", "can_paginate", "get_paginator") - } + ignored_methods = {("kinesis", method) for method in UNINSTRUMENTED_KINESIS_METHODS} client_methods = inspect.getmembers(client, predicate=inspect.ismethod) methods = {("kinesis", name) for (name, method) in client_methods if not name.startswith("_")} diff --git a/tests/logger_structlog/test_attributes.py b/tests/logger_structlog/test_attributes.py index c41591f192..f76821cd4a 100644 --- a/tests/logger_structlog/test_attributes.py +++ b/tests/logger_structlog/test_attributes.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import sys + import pytest from testing_support.validators.validate_log_event_count import validate_log_event_count from testing_support.validators.validate_log_events import validate_log_events @@ -23,12 +25,18 @@ def logger(structlog_caplog): import structlog + # For Python < 3.11 co_qualname does not exist and causes errors. + # Remove it from the CallsiteParameterAdder input list. + _callsite_params = set(structlog.processors.CallsiteParameter) + if sys.version_info < (3, 11) and hasattr(structlog.processors.CallsiteParameter, "QUAL_NAME"): + _callsite_params.remove(structlog.processors.CallsiteParameter.QUAL_NAME) + structlog.configure( processors=[ structlog.contextvars.merge_contextvars, structlog.processors.format_exc_info, structlog.processors.StackInfoRenderer(), - structlog.processors.CallsiteParameterAdder(), + structlog.processors.CallsiteParameterAdder(parameters=_callsite_params), ], logger_factory=lambda *args, **kwargs: structlog_caplog, ) diff --git a/tox.ini b/tox.ini index 39148b657f..da52345143 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ ; framework_aiohttp-aiohttp01: aiohttp<2 ; framework_aiohttp-aiohttp0202: aiohttp<2.3 ; 3. Python version required. Uses the standard tox definitions. (https://tox.readthedocs.io/en/latest/config.html#tox-environments) -; Examples: py38,py39,py310,py311,py312,py313,py314,pypy311 +; Examples: py38,py39,py310,py311,py312,py313,py314,py314t,pypy311 ; 4. Library and version (Optional). Used when testing multiple versions of the library, and may be omitted when only testing a single version. ; Versions should be specified with 2 digits per version number, so <3 becomes 02 and <3.5 becomes 0304. latest and master are also acceptable versions. ; Examples: uvicorn03, CherryPy0302, uvicornlatest @@ -61,156 +61,156 @@ envlist = {linux,linux_arm64}-cross_agent-pypy311-without_extensions, # Windows Core Agent Test Suite - {windows,windows_arm64}-agent_features-{py313,py314}-{with,without}_extensions, + {windows,windows_arm64}-agent_features-{py313,py314,py314t}-{with,without}_extensions, # Windows grpcio wheels don't appear to be installable for Arm64 despite being available windows-agent_streaming-{py313,py314}-protobuf06-{with,without}_extensions, - {windows,windows_arm64}-agent_unittests-{py313,py314}-{with,without}_extensions, - {windows,windows_arm64}-cross_agent-{py313,py314}-{with,without}_extensions, + {windows,windows_arm64}-agent_unittests-{py313,py314,py314t}-{with,without}_extensions, + {windows,windows_arm64}-cross_agent-{py313,py314,py314t}-{with,without}_extensions, # Integration Tests (only run on Linux) cassandra-datastore_cassandradriver-py38-cassandra032903, cassandra-datastore_cassandradriver-{py39,py310,py311,py312,pypy311}-cassandralatest, - elasticsearchserver07-datastore_elasticsearch-{py38,py39,py310,py311,py312,py313,py314,pypy311}-elasticsearch07, - elasticsearchserver08-datastore_elasticsearch-{py38,py39,py310,py311,py312,py313,py314,pypy311}-elasticsearch08, - firestore-datastore_firestore-{py38,py39,py310,py311,py312,py313,py314}, - grpc-framework_grpc-{py39,py310,py311,py312,py313,py314}-grpclatest, + elasticsearchserver07-datastore_elasticsearch-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-elasticsearch07, + elasticsearchserver08-datastore_elasticsearch-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-elasticsearch08, + firestore-datastore_firestore-{py38,py39,py310,py311,py312,py313,py314,py314t}, + grpc-framework_grpc-{py39,py310,py311,py312,py313,py314,py314t}-grpclatest, kafka-messagebroker_confluentkafka-py39-confluentkafka{0108,0107,0106}, kafka-messagebroker_confluentkafka-{py38,py39,py310,py311,py312,py313}-confluentkafkalatest, ;; Package not ready for Python 3.14 (confluent-kafka wheels not released) - ; kafka-messagebroker_confluentkafka-py314-confluentkafkalatest, - kafka-messagebroker_kafkapython-{py38,py39,py310,py311,py312,py313,py314,pypy311}-kafkapythonlatest, - kafka-messagebroker_kafkapython-{py38,py39,py310,py311,py312,py313,py314,pypy311}-kafkapythonnglatest, - memcached-datastore_aiomcache-{py38,py39,py310,py311,py312,py313,py314}, - memcached-datastore_bmemcached-{py38,py39,py310,py311,py312,py313,py314}, - memcached-datastore_memcache-{py38,py39,py310,py311,py312,py313,py314,pypy311}-memcached01, + ; kafka-messagebroker_confluentkafka-{py314,py314t}-confluentkafkalatest, + kafka-messagebroker_kafkapython-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-kafkapythonlatest, + kafka-messagebroker_kafkapython-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-kafkapythonnglatest, + memcached-datastore_aiomcache-{py38,py39,py310,py311,py312,py313,py314,py314t}, + memcached-datastore_bmemcached-{py38,py39,py310,py311,py312,py313,py314,py314t}, + memcached-datastore_memcache-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-memcached01, memcached-datastore_pylibmc-{py38,py39,py310,py311}, - memcached-datastore_pymemcache-{py38,py39,py310,py311,py312,py313,py314,pypy311}, - mongodb8-datastore_motor-{py38,py39,py310,py311,py312,py313,py314}-motorlatest, + memcached-datastore_pymemcache-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, + mongodb8-datastore_motor-{py38,py39,py310,py311,py312,py313,py314,py314t}-motorlatest, mongodb3-datastore_pymongo-{py38,py39,py310,py311,py312}-pymongo03, - mongodb8-datastore_pymongo-{py38,py39,py310,py311,py312,py313,py314,pypy311}-pymongo04, - mysql-datastore_aiomysql-{py38,py39,py310,py311,py312,py313,py314,pypy311}, - mssql-datastore_pymssql-pymssqllatest-{py39,py310,py311,py312,py313,py314}, + mongodb8-datastore_pymongo-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-pymongo04, + mysql-datastore_aiomysql-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, + mssql-datastore_pymssql-pymssqllatest-{py39,py310,py311,py312,py313,py314,py314t}, mssql-datastore_pymssql-pymssql020301-py38, - mysql-datastore_mysql-mysqllatest-{py38,py39,py310,py311,py312,py313,py314}, - mysql-datastore_mysqldb-{py38,py39,py310,py311,py312,py313,py314}, - mysql-datastore_pymysql-{py38,py39,py310,py311,py312,py313,py314,pypy311}, - oracledb-datastore_oracledb-{py39,py310,py311,py312,py313,py314}-oracledblatest, - oracledb-datastore_oracledb-{py39,py313,py314}-oracledb02, + mysql-datastore_mysql-mysqllatest-{py38,py39,py310,py311,py312,py313,py314,py314t}, + mysql-datastore_mysqldb-{py38,py39,py310,py311,py312,py313,py314,py314t}, + mysql-datastore_pymysql-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, + oracledb-datastore_oracledb-{py39,py310,py311,py312,py313,py314,py314t}-oracledblatest, + oracledb-datastore_oracledb-{py39,py313,py314,py314t}-oracledb02, oracledb-datastore_oracledb-{py39,py312}-oracledb01, - nginx-external_httpx-{py38,py39,py310,py311,py312,py313,py314}, - postgres16-datastore_asyncpg-{py38,py39,py310,py311,py312,py313,py314}, - postgres16-datastore_psycopg-{py38,py39,py310,py311,py312,py313,py314,pypy311}-psycopglatest, + nginx-external_httpx-{py38,py39,py310,py311,py312,py313,py314,py314t}, + postgres16-datastore_asyncpg-{py38,py39,py310,py311,py312,py313,py314,py314t}, + postgres16-datastore_psycopg-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-psycopglatest, postgres16-datastore_psycopg-py312-psycopg_{purepython,binary,compiled}0301, postgres16-datastore_psycopg2-{py38,py39,py310,py311,py312}-psycopg2latest, postgres16-datastore_psycopg2cffi-{py38,py39,py310,py311,py312}-psycopg2cffilatest, - postgres16-datastore_pyodbc-{py38,py39,py310,py311,py312,py313,py314}-pyodbclatest, - postgres9-datastore_postgresql-{py38,py39,py310,py311,py312,py313,py314}, - python-adapter_asgiref-{py38,py39,py310,py311,py312,py313,py314,pypy311}-asgireflatest, + postgres16-datastore_pyodbc-{py38,py39,py310,py311,py312,py313,py314,py314t}-pyodbclatest, + postgres9-datastore_postgresql-{py38,py39,py310,py311,py312,py313,py314,py314t}, + python-adapter_asgiref-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-asgireflatest, python-adapter_asgiref-py310-asgiref{0303,0304,0305,0306,0307}, - python-adapter_cheroot-{py38,py39,py310,py311,py312,py313,py314}, - python-adapter_daphne-{py38,py39,py310,py311,py312,py313,py314}-daphnelatest, - python-adapter_gevent-{py38,py310,py311,py312,py313,py314}, + python-adapter_cheroot-{py38,py39,py310,py311,py312,py313,py314,py314t}, + python-adapter_daphne-{py38,py39,py310,py311,py312,py313,py314,py314t}-daphnelatest, + python-adapter_gevent-{py38,py310,py311,py312,py313,py314,py314t}, python-adapter_gunicorn-{py38,py39,py310,py311,py312,py313}-aiohttp03-gunicornlatest, ;; Package not ready for Python 3.14 (aiohttp's worker not updated) - ; python-adapter_gunicorn-py314-aiohttp03-gunicornlatest, - python-adapter_hypercorn-{py38,py39,py310,py311,py312,py313,py314}-hypercornlatest, + ; python-adapter_gunicorn-{py314,py314t}-aiohttp03-gunicornlatest, + python-adapter_hypercorn-{py38,py39,py310,py311,py312,py313,py314,py314t}-hypercornlatest, python-adapter_hypercorn-py38-hypercorn{0010,0011,0012,0013}, - python-adapter_mcp-{py310,py311,py312,py313,py314}, - python-adapter_uvicorn-{py38,py39,py310,py311,py312,py313,py314}-uvicornlatest, + python-adapter_mcp-{py310,py311,py312,py313,py314,py314t}, + python-adapter_uvicorn-{py38,py39,py310,py311,py312,py313,py314,py314t}-uvicornlatest, python-adapter_uvicorn-py38-uvicorn014, - python-adapter_waitress-{py38,py39,py310,py311,py312,py313,py314}-waitresslatest, - python-application_celery-{py38,py39,py310,py311,py312,py313,py314,pypy311}-celerylatest, + python-adapter_waitress-{py38,py39,py310,py311,py312,py313,py314,py314t}-waitresslatest, + python-application_celery-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-celerylatest, python-application_celery-py311-celery{0504,0503,0502}, - python-component_djangorestframework-{py38,py39,py310,py311,py312,py313,py314}-djangorestframeworklatest, - python-component_flask_rest-{py38,py39,py310,py311,py312,py313,py314,pypy311}-flaskrestxlatest, + python-component_djangorestframework-{py38,py39,py310,py311,py312,py313,py314,py314t}-djangorestframeworklatest, + python-component_flask_rest-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-flaskrestxlatest, python-component_graphqlserver-{py38,py39,py310,py311,py312}, ;; Tests need to be updated to support newer graphql-server/sanic versions - ; python-component_graphqlserver-{py313,py314}, - python-component_tastypie-{py38,py39,py310,py311,py312,py313,py314,pypy311}-tastypielatest, - python-coroutines_asyncio-{py38,py39,py310,py311,py312,py313,py314,pypy311}, - python-datastore_sqlite-{py38,py39,py310,py311,py312,py313,py314,pypy311}, + ; python-component_graphqlserver-{py313,py314,py314t}, + python-component_tastypie-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-tastypielatest, + python-coroutines_asyncio-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, + python-datastore_sqlite-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, python-external_aiobotocore-{py38,py39,py310,py311,py312,py313}-aiobotocorelatest, ;; Package not ready for Python 3.14 (hangs when running) - ; python-external_aiobotocore-py314-aiobotocorelatest, - python-external_botocore-{py38,py39,py310,py311,py312,py313,py314}-botocorelatest, + ; python-external_aiobotocore-{py314,py314t}-aiobotocorelatest, + python-external_botocore-{py38,py39,py310,py311,py312,py313,py314,py314t}-botocorelatest, python-external_botocore-{py311}-botocorelatest-langchain, python-external_botocore-py310-botocore0125, python-external_botocore-py311-botocore0128, - python-external_feedparser-{py38,py39,py310,py311,py312,py313,py314}-feedparser06, - python-external_http-{py38,py39,py310,py311,py312,py313,py314}, - python-external_httplib-{py38,py39,py310,py311,py312,py313,py314,pypy311}, - python-external_httplib2-{py38,py39,py310,py311,py312,py313,py314,pypy311}, + python-external_feedparser-{py38,py39,py310,py311,py312,py313,py314,py314t}-feedparser06, + python-external_http-{py38,py39,py310,py311,py312,py313,py314,py314t}, + python-external_httplib-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, + python-external_httplib2-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, # pyzeebe requires grpcio which does not support pypy - python-external_pyzeebe-{py39,py310,py311,py312,py313,py314}, - python-external_requests-{py38,py39,py310,py311,py312,py313,py314,pypy311}, - python-external_urllib3-{py38,py39,py310,py311,py312,py313,py314,pypy311}-urllib3latest, - python-external_urllib3-{py312,py313,py314,pypy311}-urllib30126, - python-framework_aiohttp-{py38,py39,py310,py311,py312,py313,py314,pypy311}-aiohttp03, - python-framework_ariadne-{py38,py39,py310,py311,py312,py313,py314}-ariadnelatest, + python-external_pyzeebe-{py39,py310,py311,py312,py313,py314,py314t}, + python-external_requests-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, + python-external_urllib3-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-urllib3latest, + python-external_urllib3-{py312,py313,py314,py314t,pypy311}-urllib30126, + python-framework_aiohttp-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-aiohttp03, + python-framework_ariadne-{py38,py39,py310,py311,py312,py313,py314,py314t}-ariadnelatest, python-framework_azurefunctions-{py39,py310,py311,py312}, - python-framework_bottle-{py38,py39,py310,py311,py312,py313,py314,pypy311}-bottle0012, - python-framework_cherrypy-{py38,py39,py310,py311,py312,py313,py314,pypy311}-CherryPylatest, - python-framework_django-{py38,py39,py310,py311,py312,py313,py314}-Djangolatest, + python-framework_bottle-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-bottle0012, + python-framework_cherrypy-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-CherryPylatest, + python-framework_django-{py38,py39,py310,py311,py312,py313,py314,py314t}-Djangolatest, python-framework_django-py39-Django{0202,0300,0301,0302,0401}, - python-framework_falcon-{py39,py310,py311,py312,py313,py314,pypy311}-falconlatest, + python-framework_falcon-{py39,py310,py311,py312,py313,py314,py314t,pypy311}-falconlatest, python-framework_falcon-py38-falcon0410, - python-framework_falcon-{py39,py310,py311,py312,py313,py314,pypy311}-falconmaster, - python-framework_fastapi-{py38,py39,py310,py311,py312,py313,py314}, + python-framework_falcon-{py39,py310,py311,py312,py313,py314,py314t,pypy311}-falconmaster, + python-framework_fastapi-{py38,py39,py310,py311,py312,py313,py314,py314t}, python-framework_flask-{py38,py39,py310,py311,py312,pypy311}-flask02, ; python-framework_flask-py38-flaskmaster fails, even with Flask-Compress<1.16 and coverage==7.61 for py38 python-framework_flask-py38-flasklatest, ; flaskmaster tests disabled until they can be fixed - python-framework_flask-{py39,py310,py311,py312,py313,py314,pypy311}-flask{latest}, - python-framework_graphene-{py38,py39,py310,py311,py312,py313,py314}-graphenelatest, - python-component_graphenedjango-{py38,py39,py310,py311,py312,py313,py314}-graphenedjangolatest, - python-framework_graphql-{py38,py39,py310,py311,py312,py313,py314,pypy311}-graphql03, - python-framework_graphql-{py38,py39,py310,py311,py312,py313,py314,pypy311}-graphqllatest, - python-framework_pyramid-{py38,py39,py310,py311,py312,py313,py314,pypy311}-Pyramidlatest, - python-framework_pyramid-{py38,py39,py310,py311,py312,py313,py314,pypy311}-cornicelatest, + python-framework_flask-{py39,py310,py311,py312,py313,py314,py314t,pypy311}-flask{latest}, + python-framework_graphene-{py38,py39,py310,py311,py312,py313,py314,py314t}-graphenelatest, + python-component_graphenedjango-{py38,py39,py310,py311,py312,py313,py314,py314t}-graphenedjangolatest, + python-framework_graphql-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-graphql03, + python-framework_graphql-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-graphqllatest, + python-framework_pyramid-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-Pyramidlatest, + python-framework_pyramid-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-cornicelatest, python-framework_sanic-py38-sanic2406, - python-framework_sanic-{py39,py310,py311,py312,py313,py314,pypy311}-saniclatest, + python-framework_sanic-{py39,py310,py311,py312,py313,py314,py314t,pypy311}-saniclatest, python-framework_sanic-py38-sanic2290, python-framework_starlette-{py310,pypy311}-starlette{0014,0015,0019,0028}, - python-framework_starlette-{py38,py39,py310,py311,py312,py313,py314,pypy311}-starlettelatest, + python-framework_starlette-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-starlettelatest, python-framework_starlette-{py38}-starlette002001, python-framework_strawberry-{py38,py39,py310,py311,py312}-strawberry02352, - python-framework_strawberry-{py38,py39,py310,py311,py312,py313,py314}-strawberrylatest, - python-framework_tornado-{py38,py39,py310,py311,py312,py313,py314}-tornadolatest, - python-framework_tornado-{py310,py311,py312,py313,py314}-tornadomaster, - python-logger_logging-{py38,py39,py310,py311,py312,py313,py314,pypy311}, - python-logger_loguru-{py38,py39,py310,py311,py312,py313,py314,pypy311}-logurulatest, - python-logger_structlog-{py38,py39,py310,py311,py312,py313,py314,pypy311}-structloglatest, - python-mlmodel_autogen-{py310,py311,py312,py313,py314,pypy311}-autogen061, - python-mlmodel_autogen-{py310,py311,py312,py313,py314,pypy311}-autogenlatest, - python-mlmodel_gemini-{py39,py310,py311,py312,py313,py314}, + python-framework_strawberry-{py38,py39,py310,py311,py312,py313,py314,py314t}-strawberrylatest, + python-framework_tornado-{py38,py39,py310,py311,py312,py313,py314,py314t}-tornadolatest, + python-framework_tornado-{py310,py311,py312,py313,py314,py314t}-tornadomaster, + python-logger_logging-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, + python-logger_loguru-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-logurulatest, + python-logger_structlog-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-structloglatest, + python-mlmodel_autogen-{py310,py311,py312,py313,py314,py314t,pypy311}-autogen061, + python-mlmodel_autogen-{py310,py311,py312,py313,py314,py314t,pypy311}-autogenlatest, + python-mlmodel_gemini-{py39,py310,py311,py312,py313,py314,py314t}, python-mlmodel_langchain-{py39,py310,py311,py312,py313}, ;; Package not ready for Python 3.14 (type annotations not updated) - ; python-mlmodel_langchain-py314, + ; python-mlmodel_langchain-{py314,py314t}, python-mlmodel_openai-openai0-{py38,py39,py310,py311,py312}, python-mlmodel_openai-openai107-py312, - python-mlmodel_openai-openailatest-{py38,py39,py310,py311,py312,py313,py314}, - python-mlmodel_sklearn-{py38,py39,py310,py311,py312,py313,py314}-scikitlearnlatest, - python-template_genshi-{py38,py39,py310,py311,py312,py313,py314}-genshilatest, - python-template_jinja2-{py38,py39,py310,py311,py312,py313,py314}-jinja2latest, - python-template_mako-{py38,py39,py310,py311,py312,py313,py314}, - rabbitmq-messagebroker_pika-{py38,py39,py310,py311,py312,py313,py314,pypy311}-pikalatest, - rabbitmq-messagebroker_kombu-{py38,py39,py310,py311,py312,py313,py314,pypy311}-kombulatest, + python-mlmodel_openai-openailatest-{py38,py39,py310,py311,py312,py313,py314,py314t}, + python-mlmodel_sklearn-{py38,py39,py310,py311,py312,py313,py314,py314t}-scikitlearnlatest, + python-template_genshi-{py38,py39,py310,py311,py312,py313,py314,py314t}-genshilatest, + python-template_jinja2-{py38,py39,py310,py311,py312,py313,py314,py314t}-jinja2latest, + python-template_mako-{py38,py39,py310,py311,py312,py313,py314,py314t}, + rabbitmq-messagebroker_pika-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-pikalatest, + rabbitmq-messagebroker_kombu-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-kombulatest, rabbitmq-messagebroker_kombu-{py38,py39,py310,pypy311}-kombu050204, redis-datastore_redis-{py38,py39,py310,py311,pypy311}-redis04, redis-datastore_redis-{py38,py39,py310,py311,py312,pypy311}-redis05, - redis-datastore_redis-{py38,py39,py310,py311,py312,py313,py314,pypy311}-redislatest, - rediscluster-datastore_rediscluster-{py312,py313,py314,pypy311}-redislatest, - valkey-datastore_valkey-{py38,py39,py310,py311,py312,py313,py314,pypy311}-valkeylatest, - solr-datastore_pysolr-{py38,py39,py310,py311,py312,py313,py314,pypy311}, + redis-datastore_redis-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-redislatest, + rediscluster-datastore_rediscluster-{py312,py313,py314,py314t,pypy311}-redislatest, + valkey-datastore_valkey-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}-valkeylatest, + solr-datastore_pysolr-{py38,py39,py310,py311,py312,py313,py314,py314t,pypy311}, [testenv] deps = # Base Dependencies - {py39,py310,py311,py312,py313,py314,pypy311}: pytest==8.4.1 + {py39,py310,py311,py312,py313,py314,py314t,pypy311}: pytest==8.4.1 py38: pytest==8.3.5 - {py39,py310,py311,py312,py313,py314,pypy311}: WebTest==3.0.6 + {py39,py310,py311,py312,py313,py314,py314t,pypy311}: WebTest==3.0.6 py38: WebTest==3.0.1 - py313,py314: legacy-cgi==2.6.1 # cgi was removed from the stdlib in 3.13, and is required for WebTest + py313,py314,py314t: legacy-cgi==2.6.1 # cgi was removed from the stdlib in 3.13, and is required for WebTest iniconfig coverage @@ -275,7 +275,7 @@ deps = component_tastypie-tastypielatest: django-tastypie component_tastypie-tastypielatest: django<4.1 component_tastypie-tastypielatest: asgiref<3.7.1 # asgiref==3.7.1 only suppport Python 3.10+ - coroutines_asyncio-{py38,py39,py310,py311,py312,py313,py314}: uvloop + coroutines_asyncio-{py38,py39,py310,py311,py312,py313,py314,py314t}: uvloop cross_agent: requests datastore_asyncpg: asyncpg datastore_aiomcache: aiomcache