diff --git a/.github/workflows/test-integrations-ai.yml b/.github/workflows/test-integrations-ai.yml deleted file mode 100644 index fcbb464078..0000000000 --- a/.github/workflows/test-integrations-ai.yml +++ /dev/null @@ -1,130 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test AI -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-ai: - name: AI - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test anthropic - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-anthropic" - - name: Test cohere - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-cohere" - - name: Test langchain-base - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-langchain-base" - - name: Test langchain-notiktoken - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-langchain-notiktoken" - - name: Test litellm - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-litellm" - - name: Test openai-base - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-openai-base" - - name: Test openai-notiktoken - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-openai-notiktoken" - - name: Test langgraph - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-langgraph" - - name: Test openai_agents - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-openai_agents" - - name: Test huggingface_hub - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-huggingface_hub" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All AI tests passed - needs: test-ai - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-ai.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-cloud.yml b/.github/workflows/test-integrations-cloud.yml deleted file mode 100644 index 48a2881ffc..0000000000 --- a/.github/workflows/test-integrations-cloud.yml +++ /dev/null @@ -1,114 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test Cloud -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-cloud: - name: Cloud - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - services: - docker: - image: docker:dind # Required for Docker network management - options: --privileged # Required for Docker-in-Docker operations - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test aws_lambda - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-aws_lambda" - - name: Test boto3 - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-boto3" - - name: Test chalice - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-chalice" - - name: Test cloud_resource_context - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-cloud_resource_context" - - name: Test gcp - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-gcp" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All Cloud tests passed - needs: test-cloud - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-cloud.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-common.yml b/.github/workflows/test-integrations-common.yml index eb5dde8b17..7fb65035fe 100644 --- a/.github/workflows/test-integrations-common.yml +++ b/.github/workflows/test-integrations-common.yml @@ -29,7 +29,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] + python-version: ["3.14"] # python3.6 reached EOL and is no longer being supported on # new versions of hosted runners on Github Actions # ubuntu-20.04 is the last version that supported python3.6 diff --git a/.github/workflows/test-integrations-dbs.yml b/.github/workflows/test-integrations-dbs.yml deleted file mode 100644 index a778ce86d5..0000000000 --- a/.github/workflows/test-integrations-dbs.yml +++ /dev/null @@ -1,134 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test DBs -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-dbs: - name: DBs - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - services: - postgres: - image: postgres - env: - POSTGRES_PASSWORD: sentry - # Set health checks to wait until postgres has started - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - # Maps tcp port 5432 on service container to the host - ports: - - 5432:5432 - env: - SENTRY_PYTHON_TEST_POSTGRES_HOST: ${{ matrix.python-version == '3.6' && 'postgres' || 'localhost' }} - SENTRY_PYTHON_TEST_POSTGRES_USER: postgres - SENTRY_PYTHON_TEST_POSTGRES_PASSWORD: sentry - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: "Setup ClickHouse Server" - uses: getsentry/action-clickhouse-in-ci@v1.6 - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test asyncpg - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-asyncpg" - - name: Test clickhouse_driver - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-clickhouse_driver" - - name: Test pymongo - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-pymongo" - - name: Test redis - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-redis" - - name: Test redis_py_cluster_legacy - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-redis_py_cluster_legacy" - - name: Test sqlalchemy - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-sqlalchemy" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All DBs tests passed - needs: test-dbs - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-dbs.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-flags.yml b/.github/workflows/test-integrations-flags.yml deleted file mode 100644 index ce622d4258..0000000000 --- a/.github/workflows/test-integrations-flags.yml +++ /dev/null @@ -1,106 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test Flags -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-flags: - name: Flags - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.7","3.8","3.9","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test launchdarkly - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-launchdarkly" - - name: Test openfeature - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-openfeature" - - name: Test statsig - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-statsig" - - name: Test unleash - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-unleash" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All Flags tests passed - needs: test-flags - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-flags.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-gevent.yml b/.github/workflows/test-integrations-gevent.yml deleted file mode 100644 index 8b077f357c..0000000000 --- a/.github/workflows/test-integrations-gevent.yml +++ /dev/null @@ -1,94 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test Gevent -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-gevent: - name: Gevent - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.8","3.10","3.11","3.12"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test gevent - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-gevent" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All Gevent tests passed - needs: test-gevent - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-gevent.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-graphql.yml b/.github/workflows/test-integrations-graphql.yml deleted file mode 100644 index f1a43dc77d..0000000000 --- a/.github/workflows/test-integrations-graphql.yml +++ /dev/null @@ -1,106 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test GraphQL -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-graphql: - name: GraphQL - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test ariadne - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-ariadne" - - name: Test gql - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-gql" - - name: Test graphene - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-graphene" - - name: Test strawberry - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-strawberry" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All GraphQL tests passed - needs: test-graphql - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-graphql.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-misc.yml b/.github/workflows/test-integrations-misc.yml deleted file mode 100644 index 2aaf2f07fe..0000000000 --- a/.github/workflows/test-integrations-misc.yml +++ /dev/null @@ -1,114 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test Misc -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-misc: - name: Misc - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test loguru - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-loguru" - - name: Test opentelemetry - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-opentelemetry" - - name: Test potel - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-potel" - - name: Test pure_eval - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-pure_eval" - - name: Test trytond - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-trytond" - - name: Test typer - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-typer" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All Misc tests passed - needs: test-misc - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-misc.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-network.yml b/.github/workflows/test-integrations-network.yml deleted file mode 100644 index e8b5b36c98..0000000000 --- a/.github/workflows/test-integrations-network.yml +++ /dev/null @@ -1,102 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test Network -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-network: - name: Network - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test grpc - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-grpc" - - name: Test httpx - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-httpx" - - name: Test requests - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-requests" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All Network tests passed - needs: test-network - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-network.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-tasks.yml b/.github/workflows/test-integrations-tasks.yml deleted file mode 100644 index 2dfae9c9a3..0000000000 --- a/.github/workflows/test-integrations-tasks.yml +++ /dev/null @@ -1,129 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test Tasks -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-tasks: - name: Tasks - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Start Redis - uses: supercharge/redis-github-action@1.8.0 - - name: Install Java - uses: actions/setup-java@v5 - with: - distribution: 'temurin' - java-version: '21' - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test arq - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-arq" - - name: Test beam - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-beam" - - name: Test celery - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-celery" - - name: Test dramatiq - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-dramatiq" - - name: Test huey - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-huey" - - name: Test ray - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-ray" - - name: Test rq - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-rq" - - name: Test spark - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-spark" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All Tasks tests passed - needs: test-tasks - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-tasks.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-web-1.yml b/.github/workflows/test-integrations-web-1.yml deleted file mode 100644 index 455f15723a..0000000000 --- a/.github/workflows/test-integrations-web-1.yml +++ /dev/null @@ -1,124 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test Web 1 -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-web_1: - name: Web 1 - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - services: - postgres: - image: postgres - env: - POSTGRES_PASSWORD: sentry - # Set health checks to wait until postgres has started - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - # Maps tcp port 5432 on service container to the host - ports: - - 5432:5432 - env: - SENTRY_PYTHON_TEST_POSTGRES_HOST: ${{ matrix.python-version == '3.6' && 'postgres' || 'localhost' }} - SENTRY_PYTHON_TEST_POSTGRES_USER: postgres - SENTRY_PYTHON_TEST_POSTGRES_PASSWORD: sentry - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test django - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-django" - - name: Test flask - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-flask" - - name: Test starlette - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-starlette" - - name: Test fastapi - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-fastapi" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All Web 1 tests passed - needs: test-web_1 - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-web_1.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/.github/workflows/test-integrations-web-2.yml b/.github/workflows/test-integrations-web-2.yml deleted file mode 100644 index 98cf4456e8..0000000000 --- a/.github/workflows/test-integrations-web-2.yml +++ /dev/null @@ -1,130 +0,0 @@ -# Do not edit this YAML file. This file is generated automatically by executing -# python scripts/split_tox_gh_actions/split_tox_gh_actions.py -# The template responsible for it is in -# scripts/split_tox_gh_actions/templates/base.jinja -name: Test Web 2 -on: - push: - branches: - - master - - release/** - - potel-base - pull_request: -# Cancel in progress workflows on pull_requests. -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true -permissions: - contents: read -env: - BUILD_CACHE_KEY: ${{ github.sha }} - CACHED_BUILD_PATHS: | - ${{ github.workspace }}/dist-serverless -jobs: - test-web_2: - name: Web 2 - timeout-minutes: 30 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13"] - # python3.6 reached EOL and is no longer being supported on - # new versions of hosted runners on Github Actions - # ubuntu-20.04 is the last version that supported python3.6 - # see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877 - os: [ubuntu-22.04] - # Use Docker container only for Python 3.6 - container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }} - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-python@v6 - if: ${{ matrix.python-version != '3.6' }} - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - - name: Setup Test Env - run: | - pip install "coverage[toml]" tox - - name: Erase coverage - run: | - coverage erase - - name: Test aiohttp - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-aiohttp" - - name: Test asgi - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-asgi" - - name: Test bottle - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-bottle" - - name: Test falcon - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-falcon" - - name: Test litestar - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-litestar" - - name: Test pyramid - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-pyramid" - - name: Test quart - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-quart" - - name: Test sanic - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-sanic" - - name: Test starlite - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-starlite" - - name: Test tornado - run: | - set -x # print commands that are executed - ./scripts/runtox.sh "py${{ matrix.python-version }}-tornado" - - name: Generate coverage XML (Python 3.6) - if: ${{ !cancelled() && matrix.python-version == '3.6' }} - run: | - export COVERAGE_RCFILE=.coveragerc36 - coverage combine .coverage-sentry-* - coverage xml --ignore-errors - - name: Generate coverage XML - if: ${{ !cancelled() && matrix.python-version != '3.6' }} - run: | - coverage combine .coverage-sentry-* - coverage xml - - name: Upload coverage to Codecov - if: ${{ !cancelled() }} - uses: codecov/codecov-action@v5.5.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - # make sure no plugins alter our coverage reports - plugins: noop - verbose: true - - name: Upload test results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: .junitxml - verbose: true - check_required_tests: - name: All Web 2 tests passed - needs: test-web_2 - # Always run this, even if a dependent job failed - if: always() - runs-on: ubuntu-22.04 - steps: - - name: Check for failures - if: needs.test-web_2.result != 'success' - run: | - echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/scripts/populate_tox/releases.jsonl b/scripts/populate_tox/releases.jsonl index 9f937e5e77..9dffc0e7f9 100644 --- a/scripts/populate_tox/releases.jsonl +++ b/scripts/populate_tox/releases.jsonl @@ -46,7 +46,7 @@ {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7"], "name": "boto3", "requires_python": "", "version": "1.12.49", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9"], "name": "boto3", "requires_python": ">= 3.6", "version": "1.20.54", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9"], "name": "boto3", "requires_python": ">= 3.7", "version": "1.28.85", "yanked": false}} -{"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.9"], "name": "boto3", "requires_python": ">=3.9", "version": "1.40.46", "yanked": false}} +{"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.9"], "name": "boto3", "requires_python": ">=3.9", "version": "1.40.47", "yanked": false}} {"info": {"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2.5", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", "Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware", "Topic :: Internet :: WWW/HTTP :: WSGI :: Server", "Topic :: Software Development :: Libraries :: Application Frameworks"], "name": "bottle", "requires_python": "", "version": "0.12.25", "yanked": false}} {"info": {"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", "Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware", "Topic :: Internet :: WWW/HTTP :: WSGI :: Server", "Topic :: Software Development :: Libraries :: Application Frameworks"], "name": "bottle", "requires_python": null, "version": "0.13.4", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Object Brokering", "Topic :: System :: Distributed Computing"], "name": "celery", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "version": "4.4.7", "yanked": false}} @@ -66,7 +66,7 @@ {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Cython", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Software Development :: Libraries :: Application Frameworks"], "name": "falcon", "requires_python": ">=3.5", "version": "3.1.3", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Cython", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Software Development :: Libraries :: Application Frameworks", "Typing :: Typed"], "name": "falcon", "requires_python": ">=3.8", "version": "4.1.0", "yanked": false}} {"info": {"classifiers": ["Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: AsyncIO", "Framework :: FastAPI", "Framework :: Pydantic", "Framework :: Pydantic :: 1", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Internet", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Software Development", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", "Typing :: Typed"], "name": "fastapi", "requires_python": ">=3.8", "version": "0.105.0", "yanked": false}} -{"info": {"classifiers": ["Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: AsyncIO", "Framework :: FastAPI", "Framework :: Pydantic", "Framework :: Pydantic :: 1", "Framework :: Pydantic :: 2", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Internet", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Software Development", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", "Typing :: Typed"], "name": "fastapi", "requires_python": ">=3.8", "version": "0.118.0", "yanked": false}} +{"info": {"classifiers": ["Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: AsyncIO", "Framework :: FastAPI", "Framework :: Pydantic", "Framework :: Pydantic :: 1", "Framework :: Pydantic :: 2", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Internet", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Software Development", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", "Typing :: Typed"], "name": "fastapi", "requires_python": ">=3.8", "version": "0.118.1", "yanked": false}} {"info": {"classifiers": ["Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: AsyncIO", "Framework :: FastAPI", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Internet", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Software Development", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", "Typing :: Typed"], "name": "fastapi", "requires_python": ">=3.6.1", "version": "0.79.1", "yanked": false}} {"info": {"classifiers": ["Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: AsyncIO", "Framework :: FastAPI", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Internet", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Software Development", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", "Typing :: Typed"], "name": "fastapi", "requires_python": ">=3.7", "version": "0.92.0", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries"], "name": "gql", "requires_python": "", "version": "3.4.1", "yanked": false}} @@ -95,11 +95,11 @@ {"info": {"classifiers": ["Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering :: Artificial Intelligence"], "name": "huggingface-hub", "requires_python": ">=3.8.0", "version": "0.28.1", "yanked": false}} {"info": {"classifiers": ["Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering :: Artificial Intelligence"], "name": "huggingface-hub", "requires_python": ">=3.8.0", "version": "0.32.6", "yanked": false}} {"info": {"classifiers": ["Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering :: Artificial Intelligence"], "name": "huggingface-hub", "requires_python": ">=3.8.0", "version": "0.35.3", "yanked": false}} -{"info": {"classifiers": ["Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering :: Artificial Intelligence"], "name": "huggingface-hub", "requires_python": ">=3.9.0", "version": "1.0.0rc2", "yanked": false}} +{"info": {"classifiers": ["Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering :: Artificial Intelligence"], "name": "huggingface-hub", "requires_python": ">=3.9.0", "version": "1.0.0rc4", "yanked": false}} {"info": {"classifiers": ["License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.9"], "name": "langchain", "requires_python": "<4.0,>=3.8.1", "version": "0.1.20", "yanked": false}} {"info": {"classifiers": ["License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.9"], "name": "langchain", "requires_python": "<4.0,>=3.8.1", "version": "0.2.17", "yanked": false}} {"info": {"classifiers": [], "name": "langchain", "requires_python": "<4.0,>=3.9", "version": "0.3.27", "yanked": false}} -{"info": {"classifiers": [], "name": "langgraph", "requires_python": ">=3.9", "version": "0.6.8", "yanked": false}} +{"info": {"classifiers": [], "name": "langgraph", "requires_python": ">=3.9", "version": "0.6.9", "yanked": false}} {"info": {"classifiers": [], "name": "langgraph", "requires_python": ">=3.10", "version": "1.0.0a4", "yanked": false}} {"info": {"classifiers": ["Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.9", "Topic :: Software Development", "Topic :: Software Development :: Libraries"], "name": "launchdarkly-server-sdk", "requires_python": ">=3.9", "version": "9.12.1", "yanked": false}} {"info": {"classifiers": ["Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Software Development", "Topic :: Software Development :: Libraries"], "name": "launchdarkly-server-sdk", "requires_python": ">=3.8", "version": "9.8.1", "yanked": false}} @@ -128,7 +128,7 @@ {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Database"], "name": "pymongo", "requires_python": "", "version": "3.5.1", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Database"], "name": "pymongo", "requires_python": "", "version": "3.6.1", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Database"], "name": "pymongo", "requires_python": ">=3.6", "version": "4.0.2", "yanked": false}} -{"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Database", "Typing :: Typed"], "name": "pymongo", "requires_python": ">=3.9", "version": "4.15.2", "yanked": false}} +{"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Database", "Typing :: Typed"], "name": "pymongo", "requires_python": ">=3.9", "version": "4.15.3", "yanked": false}} {"info": {"classifiers": ["Framework :: Pylons", "Intended Audience :: Developers", "License :: Repoze Public License", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI"], "name": "pyramid", "requires_python": null, "version": "1.0.2", "yanked": false}} {"info": {"classifiers": ["Development Status :: 6 - Mature", "Framework :: Pyramid", "Intended Audience :: Developers", "License :: Repoze Public License", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI"], "name": "pyramid", "requires_python": ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", "version": "1.10.8", "yanked": false}} {"info": {"classifiers": ["Development Status :: 6 - Mature", "Framework :: Pyramid", "Intended Audience :: Developers", "License :: Repoze Public License", "Programming Language :: Python", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI"], "name": "pyramid", "requires_python": "", "version": "1.6.5", "yanked": false}} @@ -155,7 +155,7 @@ {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"], "name": "redis", "requires_python": ">=3.7", "version": "4.6.0", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"], "name": "redis", "requires_python": ">=3.8", "version": "5.3.1", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"], "name": "redis", "requires_python": ">=3.9", "version": "6.4.0", "yanked": false}} -{"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"], "name": "redis", "requires_python": ">=3.9", "version": "7.0.0b2", "yanked": false}} +{"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"], "name": "redis", "requires_python": ">=3.9", "version": "7.0.0b3", "yanked": false}} {"info": {"classifiers": ["Development Status :: 3 - Alpha", "Environment :: Web Environment", "Operating System :: POSIX", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4"], "name": "redis-py-cluster", "requires_python": null, "version": "0.1.0", "yanked": false}} {"info": {"classifiers": [], "name": "redis-py-cluster", "requires_python": null, "version": "1.1.0", "yanked": false}} {"info": {"classifiers": [], "name": "redis-py-cluster", "requires_python": null, "version": "1.2.0", "yanked": false}} @@ -191,7 +191,7 @@ {"info": {"classifiers": ["Intended Audience :: Developers", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries"], "name": "statsig", "requires_python": ">=3.7", "version": "0.55.3", "yanked": false}} {"info": {"classifiers": ["Intended Audience :: Developers", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries"], "name": "statsig", "requires_python": ">=3.7", "version": "0.65.0", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules"], "name": "strawberry-graphql", "requires_python": ">=3.8,<4.0", "version": "0.209.8", "yanked": false}} -{"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules"], "name": "strawberry-graphql", "requires_python": "<4.0,>=3.9", "version": "0.283.1", "yanked": false}} +{"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules"], "name": "strawberry-graphql", "requires_python": "<4.0,>=3.9", "version": "0.283.2", "yanked": false}} {"info": {"classifiers": ["License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"], "name": "tornado", "requires_python": ">= 3.5", "version": "6.0.4", "yanked": false}} {"info": {"classifiers": ["License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"], "name": "tornado", "requires_python": ">=3.9", "version": "6.5.2", "yanked": false}} {"info": {"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: No Input/Output (Daemon)", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License (GPL)", "Natural Language :: English", "Natural Language :: French", "Natural Language :: German", "Natural Language :: Spanish", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Application Frameworks"], "name": "trytond", "requires_python": null, "version": "1.2.10", "yanked": false}} diff --git a/scripts/populate_tox/tox.jinja b/scripts/populate_tox/tox.jinja index b86da57c24..ccf4c0e98b 100755 --- a/scripts/populate_tox/tox.jinja +++ b/scripts/populate_tox/tox.jinja @@ -18,7 +18,7 @@ requires = virtualenv<20.26.3 envlist = # === Common === - {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-common + {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12,py3.13,py3.14}-common # === Gevent === {py3.6,py3.8,py3.10,py3.11,py3.12}-gevent @@ -26,7 +26,7 @@ envlist = # === Integrations === # Asgi - {py3.7,py3.12,py3.13}-asgi + {py3.7,py3.12,py3.13,py3.14}-asgi # AWS Lambda {py3.8,py3.9,py3.11,py3.13}-aws_lambda @@ -38,7 +38,7 @@ envlist = {py3.7}-gcp # OpenTelemetry (OTel) - {py3.7,py3.9,py3.12,py3.13}-opentelemetry + {py3.7,py3.9,py3.12,py3.13,py3.14}-opentelemetry # OpenTelemetry Experimental (POTel) {py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-potel @@ -74,7 +74,7 @@ deps = # and https://github.com/pytest-dev/pytest-forked/issues/67 # for justification of the upper bound on pytest {py3.6,py3.7}-common: pytest<7.0.0 - {py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-common: pytest + {py3.8,py3.9,py3.10,py3.11,py3.12,py3.13,py3.14}-common: pytest # === Gevent === {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11}-gevent: gevent>=22.10.0, <22.11.0 @@ -177,6 +177,7 @@ basepython = py3.11: python3.11 py3.12: python3.12 py3.13: python3.13 + py3.14: python3.14 # Python version is pinned here for consistency across environments. # Tools like ruff and mypy have options that pin the target Python diff --git a/tests/test_client.py b/tests/test_client.py index ff3f61d702..fbdb35fbba 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -53,704 +53,6 @@ def capture_envelope(self, envelope): raise EnvelopeCapturedError(envelope) -def test_transport_option(monkeypatch): - if "SENTRY_DSN" in os.environ: - monkeypatch.delenv("SENTRY_DSN") - - dsn = "https://foo@sentry.io/123" - dsn2 = "https://bar@sentry.io/124" - assert str(Client(dsn=dsn).dsn) == dsn - assert Client().dsn is None - - monkeypatch.setenv("SENTRY_DSN", dsn) - transport = _TestTransport({"dsn": dsn2}) - assert str(transport.parsed_dsn) == dsn2 - assert str(Client(transport=transport).dsn) == dsn - - -@pytest.mark.parametrize( - "testcase", - [ - { - "dsn": "http://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "arg_http_proxy": "http://localhost/123", - "arg_https_proxy": None, - "expected_proxy_scheme": "http", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "arg_http_proxy": "https://localhost/123", - "arg_https_proxy": None, - "expected_proxy_scheme": "https", - }, - { - "dsn": "http://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "arg_http_proxy": "http://localhost/123", - "arg_https_proxy": "https://localhost/123", - "expected_proxy_scheme": "http", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "arg_http_proxy": "http://localhost/123", - "arg_https_proxy": "https://localhost/123", - "expected_proxy_scheme": "https", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "arg_http_proxy": "http://localhost/123", - "arg_https_proxy": None, - "expected_proxy_scheme": "http", - }, - { - "dsn": "http://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": None, - }, - { - "dsn": "http://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": None, - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": "http", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": "https://localhost/123", - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": "https", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": None, - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": "http", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": "https://localhost/123", - "arg_http_proxy": "", - "arg_https_proxy": "", - "expected_proxy_scheme": None, - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": "https://localhost/123", - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": "https", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": None, - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": "http", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": "https://localhost/123", - "arg_http_proxy": None, - "arg_https_proxy": "", - "expected_proxy_scheme": "http", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": "https://localhost/123", - "arg_http_proxy": "", - "arg_https_proxy": None, - "expected_proxy_scheme": "https", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": "https://localhost/123", - "arg_http_proxy": None, - "arg_https_proxy": "", - "expected_proxy_scheme": None, - }, - { - "dsn": "http://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": "https://localhost/123", - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": "http", - }, - # NO_PROXY testcases - { - "dsn": "http://foo@sentry.io/123", - "env_http_proxy": "http://localhost/123", - "env_https_proxy": None, - "env_no_proxy": "sentry.io,example.com", - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": None, - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": "https://localhost/123", - "env_no_proxy": "example.com,sentry.io", - "arg_http_proxy": None, - "arg_https_proxy": None, - "expected_proxy_scheme": None, - }, - { - "dsn": "http://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "env_no_proxy": "sentry.io,example.com", - "arg_http_proxy": "http://localhost/123", - "arg_https_proxy": None, - "expected_proxy_scheme": "http", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "env_no_proxy": "sentry.io,example.com", - "arg_http_proxy": None, - "arg_https_proxy": "https://localhost/123", - "expected_proxy_scheme": "https", - }, - { - "dsn": "https://foo@sentry.io/123", - "env_http_proxy": None, - "env_https_proxy": None, - "env_no_proxy": "sentry.io,example.com", - "arg_http_proxy": None, - "arg_https_proxy": "https://localhost/123", - "expected_proxy_scheme": "https", - "arg_proxy_headers": {"Test-Header": "foo-bar"}, - }, - ], -) -@pytest.mark.parametrize( - "http2", [True, False] if sys.version_info >= (3, 8) else [False] -) -def test_proxy(monkeypatch, testcase, http2): - if testcase["env_http_proxy"] is not None: - monkeypatch.setenv("HTTP_PROXY", testcase["env_http_proxy"]) - if testcase["env_https_proxy"] is not None: - monkeypatch.setenv("HTTPS_PROXY", testcase["env_https_proxy"]) - if testcase.get("env_no_proxy") is not None: - monkeypatch.setenv("NO_PROXY", testcase["env_no_proxy"]) - - kwargs = {} - - if http2: - kwargs["_experiments"] = {"transport_http2": True} - - if testcase["arg_http_proxy"] is not None: - kwargs["http_proxy"] = testcase["arg_http_proxy"] - if testcase["arg_https_proxy"] is not None: - kwargs["https_proxy"] = testcase["arg_https_proxy"] - if testcase.get("arg_proxy_headers") is not None: - kwargs["proxy_headers"] = testcase["arg_proxy_headers"] - - client = Client(testcase["dsn"], **kwargs) - - proxy = getattr( - client.transport._pool, - "proxy", - getattr(client.transport._pool, "_proxy_url", None), - ) - if testcase["expected_proxy_scheme"] is None: - assert proxy is None - else: - scheme = ( - proxy.scheme.decode("ascii") - if isinstance(proxy.scheme, bytes) - else proxy.scheme - ) - assert scheme == testcase["expected_proxy_scheme"] - - if testcase.get("arg_proxy_headers") is not None: - proxy_headers = ( - dict( - (k.decode("ascii"), v.decode("ascii")) - for k, v in client.transport._pool._proxy_headers - ) - if http2 - else client.transport._pool.proxy_headers - ) - assert proxy_headers == testcase["arg_proxy_headers"] - - -@pytest.mark.parametrize( - "testcase", - [ - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": "http://localhost/123", - "arg_https_proxy": None, - "should_be_socks_proxy": False, - }, - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": "socks4a://localhost/123", - "arg_https_proxy": None, - "should_be_socks_proxy": True, - }, - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": "socks4://localhost/123", - "arg_https_proxy": None, - "should_be_socks_proxy": True, - }, - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": "socks5h://localhost/123", - "arg_https_proxy": None, - "should_be_socks_proxy": True, - }, - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": "socks5://localhost/123", - "arg_https_proxy": None, - "should_be_socks_proxy": True, - }, - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": None, - "arg_https_proxy": "socks4a://localhost/123", - "should_be_socks_proxy": True, - }, - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": None, - "arg_https_proxy": "socks4://localhost/123", - "should_be_socks_proxy": True, - }, - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": None, - "arg_https_proxy": "socks5h://localhost/123", - "should_be_socks_proxy": True, - }, - { - "dsn": "https://foo@sentry.io/123", - "arg_http_proxy": None, - "arg_https_proxy": "socks5://localhost/123", - "should_be_socks_proxy": True, - }, - ], -) -@pytest.mark.parametrize( - "http2", [True, False] if sys.version_info >= (3, 8) else [False] -) -def test_socks_proxy(testcase, http2): - kwargs = {} - - if http2: - kwargs["_experiments"] = {"transport_http2": True} - - if testcase["arg_http_proxy"] is not None: - kwargs["http_proxy"] = testcase["arg_http_proxy"] - if testcase["arg_https_proxy"] is not None: - kwargs["https_proxy"] = testcase["arg_https_proxy"] - - client = Client(testcase["dsn"], **kwargs) - assert ("socks" in str(type(client.transport._pool)).lower()) == testcase[ - "should_be_socks_proxy" - ], ( - f"Expected {kwargs} to result in SOCKS == {testcase['should_be_socks_proxy']}" - f"but got {str(type(client.transport._pool))}" - ) - - -def test_simple_transport(sentry_init): - events = [] - sentry_init(transport=events.append) - capture_message("Hello World!") - assert events[0]["message"] == "Hello World!" - - -def test_ignore_errors(sentry_init, capture_events): - sentry_init(ignore_errors=[ZeroDivisionError]) - events = capture_events() - - class MyDivisionError(ZeroDivisionError): - pass - - def e(exc): - try: - raise exc - except Exception: - capture_exception() - - e(ZeroDivisionError()) - e(MyDivisionError()) - e(ValueError()) - - assert len(events) == 1 - assert events[0]["exception"]["values"][0]["type"] == "ValueError" - - -def test_include_local_variables_enabled(sentry_init, capture_events): - sentry_init(include_local_variables=True) - events = capture_events() - try: - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - - assert all( - frame["vars"] - for frame in event["exception"]["values"][0]["stacktrace"]["frames"] - ) - - -def test_include_local_variables_disabled(sentry_init, capture_events): - sentry_init(include_local_variables=False) - events = capture_events() - try: - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - - assert all( - "vars" not in frame - for frame in event["exception"]["values"][0]["stacktrace"]["frames"] - ) - - -def test_include_source_context_enabled(sentry_init, capture_events): - sentry_init(include_source_context=True) - events = capture_events() - try: - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - - frame = event["exception"]["values"][0]["stacktrace"]["frames"][0] - assert "post_context" in frame - assert "pre_context" in frame - assert "context_line" in frame - - -def test_include_source_context_disabled(sentry_init, capture_events): - sentry_init(include_source_context=False) - events = capture_events() - try: - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - - frame = event["exception"]["values"][0]["stacktrace"]["frames"][0] - assert "post_context" not in frame - assert "pre_context" not in frame - assert "context_line" not in frame - - -@pytest.mark.parametrize("integrations", [[], [ExecutingIntegration()]]) -def test_function_names(sentry_init, capture_events, integrations): - sentry_init(integrations=integrations) - events = capture_events() - - def foo(): - try: - bar() - except Exception: - capture_exception() - - def bar(): - 1 / 0 - - foo() - - (event,) = events - (thread,) = event["exception"]["values"] - functions = [x["function"] for x in thread["stacktrace"]["frames"]] - - if integrations: - assert functions == [ - "test_function_names..foo", - "test_function_names..bar", - ] - else: - assert functions == ["foo", "bar"] - - -def test_attach_stacktrace_enabled(sentry_init, capture_events): - sentry_init(attach_stacktrace=True) - events = capture_events() - - def foo(): - bar() - - def bar(): - capture_message("HI") - - foo() - - (event,) = events - (thread,) = event["threads"]["values"] - functions = [x["function"] for x in thread["stacktrace"]["frames"]] - - assert functions[-2:] == ["foo", "bar"] - - -def test_attach_stacktrace_enabled_no_locals(sentry_init, capture_events): - sentry_init(attach_stacktrace=True, include_local_variables=False) - events = capture_events() - - def foo(): - bar() - - def bar(): - capture_message("HI") - - foo() - - (event,) = events - (thread,) = event["threads"]["values"] - local_vars = [x.get("vars") for x in thread["stacktrace"]["frames"]] - assert local_vars[-2:] == [None, None] - - -def test_attach_stacktrace_in_app(sentry_init, capture_events): - sentry_init(attach_stacktrace=True, in_app_exclude=["_pytest"]) - events = capture_events() - - capture_message("hi") - - (event,) = events - (thread,) = event["threads"]["values"] - frames = thread["stacktrace"]["frames"] - pytest_frames = [f for f in frames if f["module"].startswith("_pytest")] - assert pytest_frames - assert all(f["in_app"] is False for f in pytest_frames) - - -def test_attach_stacktrace_disabled(sentry_init, capture_events): - sentry_init(attach_stacktrace=False) - events = capture_events() - capture_message("HI") - - (event,) = events - assert "threads" not in event - - -def test_attach_stacktrace_transaction(sentry_init, capture_events): - sentry_init(traces_sample_rate=1.0, attach_stacktrace=True) - events = capture_events() - with start_transaction(name="transaction"): - pass - (event,) = events - assert "threads" not in event - - -def test_capture_event_works(sentry_init): - sentry_init(transport=_TestTransport()) - pytest.raises(EnvelopeCapturedError, lambda: capture_event({})) - pytest.raises(EnvelopeCapturedError, lambda: capture_event({})) - - -@pytest.mark.parametrize("num_messages", [10, 20]) -@pytest.mark.parametrize( - "http2", [True, False] if sys.version_info >= (3, 8) else [False] -) -def test_atexit(tmpdir, monkeypatch, num_messages, http2): - if http2: - options = '_experiments={"transport_http2": True}' - transport = "Http2Transport" - else: - options = "" - transport = "HttpTransport" - - app = tmpdir.join("app.py") - app.write( - dedent( - """ - import time - from sentry_sdk import init, transport, capture_message - - def capture_envelope(self, envelope): - time.sleep(0.1) - event = envelope.get_event() or dict() - message = event.get("message", "") - print(message) - - transport.{transport}.capture_envelope = capture_envelope - init("http://foobar@localhost/123", shutdown_timeout={num_messages}, {options}) - - for _ in range({num_messages}): - capture_message("HI") - """.format(transport=transport, options=options, num_messages=num_messages) - ) - ) - - start = time.time() - output = subprocess.check_output([sys.executable, str(app)]) - end = time.time() - - # Each message takes at least 0.1 seconds to process - assert int(end - start) >= num_messages / 10 - - assert output.count(b"HI") == num_messages - - -def test_configure_scope_available( - sentry_init, request, monkeypatch, suppress_deprecation_warnings -): - """ - Test that scope is configured if client is configured - - This test can be removed once configure_scope and the Hub are removed. - """ - sentry_init() - - with configure_scope() as scope: - assert scope is Hub.current.scope - scope.set_tag("foo", "bar") - - calls = [] - - def callback(scope): - calls.append(scope) - scope.set_tag("foo", "bar") - - assert configure_scope(callback) is None - assert len(calls) == 1 - assert calls[0] is Hub.current.scope - - -@pytest.mark.tests_internal_exceptions -def test_client_debug_option_enabled(sentry_init, caplog): - sentry_init(debug=True) - - capture_internal_exception((ValueError, ValueError("OK"), None)) - assert "OK" in caplog.text - - -@pytest.mark.tests_internal_exceptions -@pytest.mark.parametrize("with_client", (True, False)) -def test_client_debug_option_disabled(with_client, sentry_init, caplog): - if with_client: - sentry_init() - - capture_internal_exception((ValueError, ValueError("OK"), None)) - assert "OK" not in caplog.text - - -@pytest.mark.skip( - reason="New behavior in SDK 2.0: You have a scope before init and add data to it." -) -def test_scope_initialized_before_client(sentry_init, capture_events): - """ - This is a consequence of how configure_scope() works. We must - make `configure_scope()` a noop if no client is configured. Even - if the user later configures a client: We don't know that. - """ - with configure_scope() as scope: - scope.set_tag("foo", 42) - - sentry_init() - - events = capture_events() - capture_message("hi") - (event,) = events - - assert "tags" not in event - - -def test_weird_chars(sentry_init, capture_events): - sentry_init() - events = capture_events() - capture_message("föö".encode("latin1")) - (event,) = events - assert json.loads(json.dumps(event)) == event - - -def test_nan(sentry_init, capture_events): - sentry_init() - events = capture_events() - - try: - # should_repr_strings=False - set_tag("mynan", float("nan")) - - # should_repr_strings=True - nan = float("nan") # noqa - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - frames = event["exception"]["values"][0]["stacktrace"]["frames"] - (frame,) = frames - assert frame["vars"]["nan"] == "nan" - assert event["tags"]["mynan"] == "nan" - - -def test_cyclic_frame_vars(sentry_init, capture_events): - sentry_init() - events = capture_events() - - try: - a = {} - a["a"] = a - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - assert event["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]["a"] == { - "a": "" - } - - -def test_cyclic_data(sentry_init, capture_events): - sentry_init() - events = capture_events() - - data = {} - data["is_cyclic"] = data - - other_data = "" - data["not_cyclic"] = other_data - data["not_cyclic2"] = other_data - sentry_sdk.get_isolation_scope().set_extra("foo", data) - - capture_message("hi") - (event,) = events - - data = event["extra"]["foo"] - assert data == {"not_cyclic2": "", "not_cyclic": "", "is_cyclic": ""} - - def test_databag_depth_stripping(sentry_init, capture_events, benchmark): sentry_init() events = capture_events() @@ -811,764 +113,3 @@ def inner(): == MAX_DATABAG_BREADTH ) assert len(json.dumps(event)) < 10000 - - -def test_chained_exceptions(sentry_init, capture_events): - sentry_init() - events = capture_events() - - try: - try: - raise ValueError() - except Exception: - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - - e1, e2 = event["exception"]["values"] - - # This is the order all other SDKs send chained exceptions in. Including - # Raven-Python. - - assert e1["type"] == "ValueError" - assert e2["type"] == "ZeroDivisionError" - - -@pytest.mark.tests_internal_exceptions -def test_broken_mapping(sentry_init, capture_events): - sentry_init() - events = capture_events() - - class C(Mapping): - def broken(self, *args, **kwargs): - raise Exception("broken") - - __getitem__ = broken - __setitem__ = broken - __delitem__ = broken - __iter__ = broken - __len__ = broken - - def __repr__(self): - return "broken" - - try: - a = C() # noqa - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - assert ( - event["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]["a"] - == "" - ) - - -def test_mapping_sends_exception(sentry_init, capture_events): - sentry_init() - events = capture_events() - - class C(Mapping): - def __iter__(self): - try: - 1 / 0 - except ZeroDivisionError: - capture_exception() - yield "hi" - - def __len__(self): - """List length""" - return 1 - - def __getitem__(self, ii): - """Get a list item""" - if ii == "hi": - return "hi" - - raise KeyError() - - try: - a = C() # noqa - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - - assert event["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]["a"] == { - "hi": "'hi'" - } - - -def test_object_sends_exception(sentry_init, capture_events): - sentry_init() - events = capture_events() - - class C: - def __repr__(self): - try: - 1 / 0 - except ZeroDivisionError: - capture_exception() - return "hi, i am a repr" - - try: - a = C() # noqa - 1 / 0 - except Exception: - capture_exception() - - (event,) = events - - assert ( - event["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]["a"] - == "hi, i am a repr" - ) - - -def test_errno_errors(sentry_init, capture_events): - sentry_init() - events = capture_events() - - class FooError(Exception): - errno = 69 - - capture_exception(FooError()) - - (event,) = events - - (exception,) = event["exception"]["values"] - assert exception["mechanism"]["meta"]["errno"]["number"] == 69 - - -@maximum_python_312 -def test_non_string_variables(sentry_init, capture_events): - """There is some extremely terrible code in the wild that - inserts non-strings as variable names into `locals()`.""" - - sentry_init() - events = capture_events() - - try: - locals()[42] = True - 1 / 0 - except ZeroDivisionError: - capture_exception() - - (event,) = events - - (exception,) = event["exception"]["values"] - assert exception["type"] == "ZeroDivisionError" - (frame,) = exception["stacktrace"]["frames"] - assert frame["vars"]["42"] == "True" - - -def test_dict_changed_during_iteration(sentry_init, capture_events): - """ - Some versions of Bottle modify the WSGI environment inside of this __repr__ - impl: https://github.com/bottlepy/bottle/blob/0.12.16/bottle.py#L1386 - - See https://github.com/getsentry/sentry-python/pull/298 for discussion - """ - sentry_init(send_default_pii=True) - events = capture_events() - - class TooSmartClass: - def __init__(self, environ): - self.environ = environ - - def __repr__(self): - if "my_representation" in self.environ: - return self.environ["my_representation"] - - self.environ["my_representation"] = "" - return self.environ["my_representation"] - - try: - environ = {} - environ["a"] = TooSmartClass(environ) - 1 / 0 - except ZeroDivisionError: - capture_exception() - - (event,) = events - (exception,) = event["exception"]["values"] - (frame,) = exception["stacktrace"]["frames"] - assert frame["vars"]["environ"] == {"a": ""} - - -def test_custom_repr_on_vars(sentry_init, capture_events): - class Foo: - pass - - class Fail: - pass - - def custom_repr(value): - if isinstance(value, Foo): - return "custom repr" - elif isinstance(value, Fail): - raise ValueError("oops") - else: - return None - - sentry_init(custom_repr=custom_repr) - events = capture_events() - - try: - my_vars = {"foo": Foo(), "fail": Fail(), "normal": 42} - 1 / 0 - except ZeroDivisionError: - capture_exception() - - (event,) = events - (exception,) = event["exception"]["values"] - (frame,) = exception["stacktrace"]["frames"] - my_vars = frame["vars"]["my_vars"] - assert my_vars["foo"] == "custom repr" - assert my_vars["normal"] == "42" - assert "Fail object" in my_vars["fail"] - - -@pytest.mark.parametrize( - "dsn", - [ - "http://894b7d594095440f8dfea9b300e6f572@localhost:8000/2", - "http://894b7d594095440f8dfea9b300e6f572@localhost:8000/2", - ], -) -def test_init_string_types(dsn, sentry_init): - # Allow unicode strings on Python 3 and both on Python 2 (due to - # unicode_literals) - # - # Supporting bytes on Python 3 is not really wrong but probably would be - # extra code - sentry_init(dsn) - assert ( - sentry_sdk.get_client().dsn - == "http://894b7d594095440f8dfea9b300e6f572@localhost:8000/2" - ) - - -@pytest.mark.parametrize( - "sdk_options, expected_breadcrumbs", - [({}, DEFAULT_MAX_BREADCRUMBS), ({"max_breadcrumbs": 50}, 50)], -) -def test_max_breadcrumbs_option( - sentry_init, capture_events, sdk_options, expected_breadcrumbs -): - sentry_init(sdk_options) - events = capture_events() - - for _ in range(1231): - add_breadcrumb({"type": "sourdough"}) - - capture_message("dogs are great") - - assert len(events[0]["breadcrumbs"]["values"]) == expected_breadcrumbs - - -def test_multiple_positional_args(sentry_init): - with pytest.raises(TypeError) as exinfo: - sentry_init(1, None) - assert "Only single positional argument is expected" in str(exinfo.value) - - -@pytest.mark.parametrize( - "sdk_options, expected_data_length", - [ - ({}, DEFAULT_MAX_VALUE_LENGTH), - ( - {"max_value_length": DEFAULT_MAX_VALUE_LENGTH + 1000}, - DEFAULT_MAX_VALUE_LENGTH + 1000, - ), - ], -) -def test_max_value_length_option( - sentry_init, capture_events, sdk_options, expected_data_length -): - sentry_init(sdk_options) - events = capture_events() - - capture_message("a" * (DEFAULT_MAX_VALUE_LENGTH + 2000)) - - assert len(events[0]["message"]) == expected_data_length - - -@pytest.mark.parametrize( - "client_option,env_var_value,debug_output_expected", - [ - (None, "", False), - (None, "t", True), - (None, "1", True), - (None, "True", True), - (None, "true", True), - (None, "f", False), - (None, "0", False), - (None, "False", False), - (None, "false", False), - (None, "xxx", False), - (True, "", True), - (True, "t", True), - (True, "1", True), - (True, "True", True), - (True, "true", True), - (True, "f", True), - (True, "0", True), - (True, "False", True), - (True, "false", True), - (True, "xxx", True), - (False, "", False), - (False, "t", False), - (False, "1", False), - (False, "True", False), - (False, "true", False), - (False, "f", False), - (False, "0", False), - (False, "False", False), - (False, "false", False), - (False, "xxx", False), - ], -) -@pytest.mark.tests_internal_exceptions -def test_debug_option( - sentry_init, - monkeypatch, - caplog, - client_option, - env_var_value, - debug_output_expected, -): - monkeypatch.setenv("SENTRY_DEBUG", env_var_value) - - if client_option is None: - sentry_init() - else: - sentry_init(debug=client_option) - - capture_internal_exception((ValueError, ValueError("something is wrong"), None)) - if debug_output_expected: - assert "something is wrong" in caplog.text - else: - assert "something is wrong" not in caplog.text - - -@pytest.mark.parametrize( - "client_option,env_var_value,spotlight_url_expected", - [ - (None, None, None), - (None, "", None), - (None, "F", None), - (False, None, None), - (False, "", None), - (False, "t", None), - (None, "t", DEFAULT_SPOTLIGHT_URL), - (None, "1", DEFAULT_SPOTLIGHT_URL), - (True, None, DEFAULT_SPOTLIGHT_URL), - (True, "http://localhost:8080/slurp", DEFAULT_SPOTLIGHT_URL), - ("http://localhost:8080/slurp", "f", "http://localhost:8080/slurp"), - (None, "http://localhost:8080/slurp", "http://localhost:8080/slurp"), - ], -) -def test_spotlight_option( - sentry_init, - monkeypatch, - client_option, - env_var_value, - spotlight_url_expected, -): - if env_var_value is None: - monkeypatch.delenv("SENTRY_SPOTLIGHT", raising=False) - else: - monkeypatch.setenv("SENTRY_SPOTLIGHT", env_var_value) - - if client_option is None: - sentry_init() - else: - sentry_init(spotlight=client_option) - - client = sentry_sdk.get_client() - url = client.spotlight.url if client.spotlight else None - assert url == spotlight_url_expected, ( - f"With config {client_option} and env {env_var_value}" - ) - - -class IssuesSamplerTestConfig: - def __init__( - self, - expected_events, - sampler_function=None, - sample_rate=None, - exception_to_raise=Exception, - ): - # type: (int, Optional[Callable[[Event], Union[float, bool]]], Optional[float], type[Exception]) -> None - self.sampler_function_mock = ( - None - if sampler_function is None - else mock.MagicMock(side_effect=sampler_function) - ) - self.expected_events = expected_events - self.sample_rate = sample_rate - self.exception_to_raise = exception_to_raise - - def init_sdk(self, sentry_init): - # type: (Callable[[*Any], None]) -> None - sentry_init( - error_sampler=self.sampler_function_mock, sample_rate=self.sample_rate - ) - - def raise_exception(self): - # type: () -> None - raise self.exception_to_raise() - - -@mock.patch("sentry_sdk.client.random.random", return_value=0.618) -@pytest.mark.parametrize( - "test_config", - ( - # Baseline test with error_sampler only, both floats and bools - IssuesSamplerTestConfig(sampler_function=lambda *_: 1.0, expected_events=1), - IssuesSamplerTestConfig(sampler_function=lambda *_: 0.7, expected_events=1), - IssuesSamplerTestConfig(sampler_function=lambda *_: 0.6, expected_events=0), - IssuesSamplerTestConfig(sampler_function=lambda *_: 0.0, expected_events=0), - IssuesSamplerTestConfig(sampler_function=lambda *_: True, expected_events=1), - IssuesSamplerTestConfig(sampler_function=lambda *_: False, expected_events=0), - # Baseline test with sample_rate only - IssuesSamplerTestConfig(sample_rate=1.0, expected_events=1), - IssuesSamplerTestConfig(sample_rate=0.7, expected_events=1), - IssuesSamplerTestConfig(sample_rate=0.6, expected_events=0), - IssuesSamplerTestConfig(sample_rate=0.0, expected_events=0), - # error_sampler takes precedence over sample_rate - IssuesSamplerTestConfig( - sampler_function=lambda *_: 1.0, sample_rate=0.0, expected_events=1 - ), - IssuesSamplerTestConfig( - sampler_function=lambda *_: 0.0, sample_rate=1.0, expected_events=0 - ), - # Different sample rates based on exception, retrieved both from event and hint - IssuesSamplerTestConfig( - sampler_function=lambda event, _: { - "ZeroDivisionError": 1.0, - "AttributeError": 0.0, - }[event["exception"]["values"][0]["type"]], - exception_to_raise=ZeroDivisionError, - expected_events=1, - ), - IssuesSamplerTestConfig( - sampler_function=lambda event, _: { - "ZeroDivisionError": 1.0, - "AttributeError": 0.0, - }[event["exception"]["values"][0]["type"]], - exception_to_raise=AttributeError, - expected_events=0, - ), - IssuesSamplerTestConfig( - sampler_function=lambda _, hint: { - ZeroDivisionError: 1.0, - AttributeError: 0.0, - }[hint["exc_info"][0]], - exception_to_raise=ZeroDivisionError, - expected_events=1, - ), - IssuesSamplerTestConfig( - sampler_function=lambda _, hint: { - ZeroDivisionError: 1.0, - AttributeError: 0.0, - }[hint["exc_info"][0]], - exception_to_raise=AttributeError, - expected_events=0, - ), - # If sampler returns invalid value, we should still send the event - IssuesSamplerTestConfig( - sampler_function=lambda *_: "This is an invalid return value for the sampler", - expected_events=1, - ), - ), -) -def test_error_sampler(_, sentry_init, capture_events, test_config): - test_config.init_sdk(sentry_init) - - events = capture_events() - - try: - test_config.raise_exception() - except Exception: - capture_exception() - - assert len(events) == test_config.expected_events - - if test_config.sampler_function_mock is not None: - assert test_config.sampler_function_mock.call_count == 1 - - # Ensure two arguments (the event and hint) were passed to the sampler function - assert len(test_config.sampler_function_mock.call_args[0]) == 2 - - -@pytest.mark.parametrize( - "opt,missing_flags", - [ - # lazy mode with enable-threads, no warning - [{"enable-threads": True, "lazy-apps": True}, []], - [{"enable-threads": "true", "lazy-apps": b"1"}, []], - # preforking mode with enable-threads and py-call-uwsgi-fork-hooks, no warning - [{"enable-threads": True, "py-call-uwsgi-fork-hooks": True}, []], - [{"enable-threads": b"true", "py-call-uwsgi-fork-hooks": b"on"}, []], - # lazy mode, no enable-threads, warning - [{"lazy-apps": True}, ["--enable-threads"]], - [{"enable-threads": b"false", "lazy-apps": True}, ["--enable-threads"]], - [{"enable-threads": b"0", "lazy": True}, ["--enable-threads"]], - # preforking mode, no enable-threads or py-call-uwsgi-fork-hooks, warning - [{}, ["--enable-threads", "--py-call-uwsgi-fork-hooks"]], - [{"processes": b"2"}, ["--enable-threads", "--py-call-uwsgi-fork-hooks"]], - [{"enable-threads": True}, ["--py-call-uwsgi-fork-hooks"]], - [{"enable-threads": b"1"}, ["--py-call-uwsgi-fork-hooks"]], - [ - {"enable-threads": b"false"}, - ["--enable-threads", "--py-call-uwsgi-fork-hooks"], - ], - [{"py-call-uwsgi-fork-hooks": True}, ["--enable-threads"]], - ], -) -def test_uwsgi_warnings(sentry_init, recwarn, opt, missing_flags): - uwsgi = mock.MagicMock() - uwsgi.opt = opt - with mock.patch.dict("sys.modules", uwsgi=uwsgi): - sentry_init(profiles_sample_rate=1.0) - if missing_flags: - assert len(recwarn) == 1 - record = recwarn.pop() - for flag in missing_flags: - assert flag in str(record.message) - else: - assert not recwarn - - -class TestSpanClientReports: - """ - Tests for client reports related to spans. - """ - - __test__ = False - - @staticmethod - def span_dropper(spans_to_drop): - """ - Returns a function that can be used to drop spans from an event. - """ - - def drop_spans(event, _): - event["spans"] = event["spans"][spans_to_drop:] - return event - - return drop_spans - - @staticmethod - def mock_transaction_event(span_count): - """ - Returns a mock transaction event with the given number of spans. - """ - - return defaultdict( - mock.MagicMock, - type="transaction", - spans=[mock.MagicMock() for _ in range(span_count)], - ) - - def __init__(self, span_count): - """Configures a test case with the number of spans dropped and whether the transaction was dropped.""" - self.span_count = span_count - self.expected_record_lost_event_calls = Counter() - self.before_send = lambda event, _: event - self.event_processor = lambda event, _: event - - def _update_resulting_calls(self, reason, drops_transactions=0, drops_spans=0): - """ - Updates the expected calls with the given resulting calls. - """ - if drops_transactions > 0: - self.expected_record_lost_event_calls[ - (reason, "transaction", None, drops_transactions) - ] += 1 - - if drops_spans > 0: - self.expected_record_lost_event_calls[ - (reason, "span", None, drops_spans) - ] += 1 - - def with_before_send( - self, - before_send, - *, - drops_transactions=0, - drops_spans=0, - ): - self.before_send = before_send - self._update_resulting_calls( - "before_send", - drops_transactions, - drops_spans, - ) - - return self - - def with_event_processor( - self, - event_processor, - *, - drops_transactions=0, - drops_spans=0, - ): - self.event_processor = event_processor - self._update_resulting_calls( - "event_processor", - drops_transactions, - drops_spans, - ) - - return self - - def run(self, sentry_init, capture_record_lost_event_calls): - """Runs the test case with the configured parameters.""" - sentry_init(before_send_transaction=self.before_send) - record_lost_event_calls = capture_record_lost_event_calls() - - with sentry_sdk.isolation_scope() as scope: - scope.add_event_processor(self.event_processor) - event = self.mock_transaction_event(self.span_count) - sentry_sdk.get_client().capture_event(event, scope=scope) - - # We use counters to ensure that the calls are made the expected number of times, disregarding order. - assert Counter(record_lost_event_calls) == self.expected_record_lost_event_calls - - -@pytest.mark.parametrize( - "test_config", - ( - TestSpanClientReports(span_count=10), # No spans dropped - TestSpanClientReports(span_count=0).with_before_send( - lambda e, _: None, - drops_transactions=1, - drops_spans=1, - ), - TestSpanClientReports(span_count=10).with_before_send( - lambda e, _: None, - drops_transactions=1, - drops_spans=11, - ), - TestSpanClientReports(span_count=10).with_before_send( - TestSpanClientReports.span_dropper(3), - drops_spans=3, - ), - TestSpanClientReports(span_count=10).with_before_send( - TestSpanClientReports.span_dropper(10), - drops_spans=10, - ), - TestSpanClientReports(span_count=10).with_event_processor( - lambda e, _: None, - drops_transactions=1, - drops_spans=11, - ), - TestSpanClientReports(span_count=10).with_event_processor( - TestSpanClientReports.span_dropper(3), - drops_spans=3, - ), - TestSpanClientReports(span_count=10).with_event_processor( - TestSpanClientReports.span_dropper(10), - drops_spans=10, - ), - TestSpanClientReports(span_count=10) - .with_event_processor( - TestSpanClientReports.span_dropper(3), - drops_spans=3, - ) - .with_before_send( - TestSpanClientReports.span_dropper(5), - drops_spans=5, - ), - TestSpanClientReports(10) - .with_event_processor( - TestSpanClientReports.span_dropper(3), - drops_spans=3, - ) - .with_before_send( - lambda e, _: None, - drops_transactions=1, - drops_spans=8, # 3 of the 11 (incl. transaction) spans already dropped - ), - ), -) -def test_dropped_transaction(sentry_init, capture_record_lost_event_calls, test_config): - test_config.run(sentry_init, capture_record_lost_event_calls) - - -@pytest.mark.parametrize("enable_tracing", [True, False]) -def test_enable_tracing_deprecated(sentry_init, enable_tracing): - with pytest.warns(DeprecationWarning): - sentry_init(enable_tracing=enable_tracing) - - -def make_options_transport_cls(): - """Make an options transport class that captures the options passed to it.""" - # We need a unique class for each test so that the options are not - # shared between tests. - - class OptionsTransport(Transport): - """Transport that captures the options passed to it.""" - - def __init__(self, options): - super().__init__(options) - type(self).options = options - - def capture_envelope(self, _): - pass - - return OptionsTransport - - -@contextlib.contextmanager -def clear_env_var(name): - """Helper to clear the a given environment variable, - and restore it to its original value on exit.""" - old_value = os.environ.pop(name, None) - - try: - yield - finally: - if old_value is not None: - os.environ[name] = old_value - elif name in os.environ: - del os.environ[name] - - -@pytest.mark.parametrize( - ("env_value", "arg_value", "expected_value"), - [ - (None, None, False), # default - ("0", None, False), # env var false - ("1", None, True), # env var true - (None, False, False), # arg false - (None, True, True), # arg true - # Argument overrides environment variable - ("0", True, True), # env false, arg true - ("1", False, False), # env true, arg false - ], -) -def test_keep_alive(env_value, arg_value, expected_value): - transport_cls = make_options_transport_cls() - keep_alive_kwarg = {} if arg_value is None else {"keep_alive": arg_value} - - with clear_env_var("SENTRY_KEEP_ALIVE"): - if env_value is not None: - os.environ["SENTRY_KEEP_ALIVE"] = env_value - - sentry_sdk.init( - dsn="http://foo@sentry.io/123", - transport=transport_cls, - **keep_alive_kwarg, - ) - - assert transport_cls.options["keep_alive"] is expected_value diff --git a/tox.ini b/tox.ini index 4bfc90cee9..c22ee1ac5f 100644 --- a/tox.ini +++ b/tox.ini @@ -18,7 +18,7 @@ requires = virtualenv<20.26.3 envlist = # === Common === - {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-common + {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12,py3.13,py3.14}-common # === Gevent === {py3.6,py3.8,py3.10,py3.11,py3.12}-gevent @@ -26,7 +26,7 @@ envlist = # === Integrations === # Asgi - {py3.7,py3.12,py3.13}-asgi + {py3.7,py3.12,py3.13,py3.14}-asgi # AWS Lambda {py3.8,py3.9,py3.11,py3.13}-aws_lambda @@ -38,7 +38,7 @@ envlist = {py3.7}-gcp # OpenTelemetry (OTel) - {py3.7,py3.9,py3.12,py3.13}-opentelemetry + {py3.7,py3.9,py3.12,py3.13,py3.14}-opentelemetry # OpenTelemetry Experimental (POTel) {py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-potel @@ -75,7 +75,7 @@ envlist = {py3.8,py3.12,py3.13}-openai-notiktoken-v1.109.1 {py3.8,py3.12,py3.13}-openai-notiktoken-v2.2.0 - {py3.9,py3.12,py3.13}-langgraph-v0.6.8 + {py3.9,py3.12,py3.13}-langgraph-v0.6.9 {py3.10,py3.12,py3.13}-langgraph-v1.0.0a4 {py3.10,py3.11,py3.12}-openai_agents-v0.0.19 @@ -87,14 +87,14 @@ envlist = {py3.8,py3.12,py3.13}-huggingface_hub-v0.28.1 {py3.8,py3.12,py3.13}-huggingface_hub-v0.32.6 {py3.8,py3.12,py3.13}-huggingface_hub-v0.35.3 - {py3.9,py3.12,py3.13}-huggingface_hub-v1.0.0rc2 + {py3.9,py3.12,py3.13}-huggingface_hub-v1.0.0rc4 # ~~~ Cloud ~~~ {py3.6,py3.7}-boto3-v1.12.49 {py3.6,py3.9,py3.10}-boto3-v1.20.54 {py3.7,py3.11,py3.12}-boto3-v1.28.85 - {py3.9,py3.12,py3.13}-boto3-v1.40.46 + {py3.9,py3.12,py3.13}-boto3-v1.40.47 {py3.6,py3.7,py3.8}-chalice-v1.16.0 {py3.9,py3.12,py3.13}-chalice-v1.32.0 @@ -110,14 +110,14 @@ envlist = {py3.6}-pymongo-v3.5.1 {py3.6,py3.10,py3.11}-pymongo-v3.13.0 - {py3.9,py3.12,py3.13}-pymongo-v4.15.2 + {py3.9,py3.12,py3.13}-pymongo-v4.15.3 {py3.6}-redis-v2.10.6 {py3.6,py3.7,py3.8}-redis-v3.5.3 {py3.7,py3.10,py3.11}-redis-v4.6.0 {py3.8,py3.11,py3.12}-redis-v5.3.1 {py3.9,py3.12,py3.13}-redis-v6.4.0 - {py3.9,py3.12,py3.13}-redis-v7.0.0b2 + {py3.9,py3.12,py3.13}-redis-v7.0.0b3 {py3.6}-redis_py_cluster_legacy-v1.3.6 {py3.6,py3.7,py3.8}-redis_py_cluster_legacy-v2.1.3 @@ -153,7 +153,7 @@ envlist = {py3.8,py3.12,py3.13}-graphene-v3.4.3 {py3.8,py3.10,py3.11}-strawberry-v0.209.8 - {py3.9,py3.12,py3.13}-strawberry-v0.283.1 + {py3.9,py3.12,py3.13}-strawberry-v0.283.2 # ~~~ Network ~~~ @@ -222,7 +222,7 @@ envlist = {py3.6,py3.9,py3.10}-fastapi-v0.79.1 {py3.7,py3.10,py3.11}-fastapi-v0.92.0 {py3.8,py3.10,py3.11}-fastapi-v0.105.0 - {py3.8,py3.12,py3.13}-fastapi-v0.118.0 + {py3.8,py3.12,py3.13}-fastapi-v0.118.1 # ~~~ Web 2 ~~~ @@ -297,7 +297,7 @@ deps = # and https://github.com/pytest-dev/pytest-forked/issues/67 # for justification of the upper bound on pytest {py3.6,py3.7}-common: pytest<7.0.0 - {py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-common: pytest + {py3.8,py3.9,py3.10,py3.11,py3.12,py3.13,py3.14}-common: pytest # === Gevent === {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11}-gevent: gevent>=22.10.0, <22.11.0 @@ -378,7 +378,7 @@ deps = openai-notiktoken: pytest-asyncio openai-notiktoken-v1.0.1: httpx<0.28 - langgraph-v0.6.8: langgraph==0.6.8 + langgraph-v0.6.9: langgraph==0.6.9 langgraph-v1.0.0a4: langgraph==1.0.0a4 openai_agents-v0.0.19: openai-agents==0.0.19 @@ -391,7 +391,7 @@ deps = huggingface_hub-v0.28.1: huggingface_hub==0.28.1 huggingface_hub-v0.32.6: huggingface_hub==0.32.6 huggingface_hub-v0.35.3: huggingface_hub==0.35.3 - huggingface_hub-v1.0.0rc2: huggingface_hub==1.0.0rc2 + huggingface_hub-v1.0.0rc4: huggingface_hub==1.0.0rc4 huggingface_hub: responses huggingface_hub: pytest-httpx @@ -400,7 +400,7 @@ deps = boto3-v1.12.49: boto3==1.12.49 boto3-v1.20.54: boto3==1.20.54 boto3-v1.28.85: boto3==1.28.85 - boto3-v1.40.46: boto3==1.40.46 + boto3-v1.40.47: boto3==1.40.47 {py3.7,py3.8}-boto3: urllib3<2.0.0 chalice-v1.16.0: chalice==1.16.0 @@ -419,7 +419,7 @@ deps = pymongo-v3.5.1: pymongo==3.5.1 pymongo-v3.13.0: pymongo==3.13.0 - pymongo-v4.15.2: pymongo==4.15.2 + pymongo-v4.15.3: pymongo==4.15.3 pymongo: mockupdb redis-v2.10.6: redis==2.10.6 @@ -427,7 +427,7 @@ deps = redis-v4.6.0: redis==4.6.0 redis-v5.3.1: redis==5.3.1 redis-v6.4.0: redis==6.4.0 - redis-v7.0.0b2: redis==7.0.0b2 + redis-v7.0.0b3: redis==7.0.0b3 redis: fakeredis!=1.7.4 redis: pytest<8.0.0 redis-v4.6.0: fakeredis<2.31.0 @@ -477,7 +477,7 @@ deps = {py3.6}-graphene: aiocontextvars strawberry-v0.209.8: strawberry-graphql[fastapi,flask]==0.209.8 - strawberry-v0.283.1: strawberry-graphql[fastapi,flask]==0.283.1 + strawberry-v0.283.2: strawberry-graphql[fastapi,flask]==0.283.2 strawberry: httpx strawberry-v0.209.8: pydantic<2.11 @@ -604,7 +604,7 @@ deps = fastapi-v0.79.1: fastapi==0.79.1 fastapi-v0.92.0: fastapi==0.92.0 fastapi-v0.105.0: fastapi==0.105.0 - fastapi-v0.118.0: fastapi==0.118.0 + fastapi-v0.118.1: fastapi==0.118.1 fastapi: httpx fastapi: pytest-asyncio fastapi: python-multipart @@ -808,6 +808,7 @@ basepython = py3.11: python3.11 py3.12: python3.12 py3.13: python3.13 + py3.14: python3.14 # Python version is pinned here for consistency across environments. # Tools like ruff and mypy have options that pin the target Python @@ -815,15 +816,7 @@ basepython = linters: python3.14 commands = - {py3.7,py3.8}-boto3: pip install urllib3<2.0.0 - - ; https://github.com/pallets/flask/issues/4455 - {py3.7,py3.8,py3.9,py3.10,py3.11}-flask-v{1}: pip install "itsdangerous>=0.24,<2.0" "markupsafe<2.0.0" "jinja2<3.1.1" - - ; Running `pytest` as an executable suffers from an import error - ; when loading tests in scenarios. In particular, django fails to - ; load the settings from the test module. - python -m pytest -W error::pytest.PytestUnraisableExceptionWarning {env:TESTPATH} -o junit_suite_name={envname} {posargs} + python -m pytest -W error::pytest.PytestUnraisableExceptionWarning tests tests/test_client.py [testenv:linters] commands =