From e4b3cb2fcb63a7e7f0dbde31851eba7a1fca5d55 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Thu, 9 Jan 2025 17:31:08 +0100 Subject: [PATCH] add missing files --- .github/workflows/test-integrations-flags.yml | 99 +++++++ scripts/populate_tox/dependencies.py | 251 ++++++++++++++++++ scripts/populate_tox/tox.jinja | 211 +++++++++++++++ 3 files changed, 561 insertions(+) create mode 100644 .github/workflows/test-integrations-flags.yml create mode 100644 scripts/populate_tox/dependencies.py create mode 100644 scripts/populate_tox/tox.jinja diff --git a/.github/workflows/test-integrations-flags.yml b/.github/workflows/test-integrations-flags.yml new file mode 100644 index 0000000000..91d5d94888 --- /dev/null +++ b/.github/workflows/test-integrations-flags.yml @@ -0,0 +1,99 @@ +# 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/** + - sentry-sdk-2.0 + 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.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-20.04] + steps: + - uses: actions/checkout@v4.2.2 + - uses: actions/setup-python@v5 + 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 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.1.2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.xml + # make sure no plugins alter our coverage reports + plugin: 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-20.04 + steps: + - name: Check for failures + if: contains(needs.test-flags.result, 'failure') || contains(needs.test-flags.result, 'skipped') + run: | + echo "One of the dependent jobs has failed. You may need to re-run it." && exit 1 diff --git a/scripts/populate_tox/dependencies.py b/scripts/populate_tox/dependencies.py new file mode 100644 index 0000000000..2cebb973a0 --- /dev/null +++ b/scripts/populate_tox/dependencies.py @@ -0,0 +1,251 @@ +# XXX move this to conftest? +DEPENDENCIES = { + # package: [test_dependency_1, test_dependency_2, ...] + # + # The main package (e.g. aiohttp for the aiohttp test suite) needs to be + # the first dependency listed. The script will then query PYPI for releases + # of the package and will pick a handful to test against. + "aiohttp": [ + "aiohttp", + "pytest-aiohttp", + "pytest-asyncio", + ], + "anthropic": [ + "anthropic", + "httpx", # TODO has an upper bound anthropic-v{0.16,0.28}: httpx<0.28.0 + "pytest-asyncio", + ], + "ariadne": [ + "ariadne", + "fastapi", + "flask", + "httpx", + ], + "arq": [ + "arq", + "pydantic", # TODO arq-v0.23: pydantic<2 + "fakeredis>=2.2.0,<2.8", + "pytest-asyncio", + "async-timeout", + ], + "asyncpg": [ + "asyncpg", + "pytest-asyncio", + ], + "aws_lambda": [ + "boto3", + ], + "beam": ["apache-beam"], + "boto3": [ + "boto3", + ], + "bottle": [ + "bottle", + "werkzeug<2.1.0", + ], + "celery": [ + "celery", + "importlib-metadata", # {py3.7}-celery: importlib-metadata<5.0 + "newrelic", + "redis", + ], + "chalice": [ + "chalice", + "pytest-chalice==0.0.5", + ], + "clickhouse-driver": [ + "clickhouse-driver", + ], + "cohere": [ + "cohere", + ], + "django": [ + "django", + "channels[daphne]", # django-v{2.0,2.2,3.0,3.2,4.0,4.1,4.2,5.0,5.1}: channels[daphne] + "djangorestframework", # django-v{1.11,2.0,2.1,2.2,3.0,3.1,3.2}: djangorestframework>=3.0.0,<4.0.0 + "psycopg2-binary", + "pytest-asyncio", + "pytest-django", # django-v{1.11,2.0,2.2,3.0}: pytest-django<4.0 + "six", # django-v{2.2,3.0}: six + "werkzeug", # django-v{1.11,2.0,2.2,3.0,3.2}: Werkzeug<2.1.0 + ], + "dramatiq": [ + "dramatiq", + ], + "falcon": [ + "falcon", + ], + "fastapi": [ + "fastapi", + "httpx", + "anyio<4.0.0", + "python-multipart", + "pytest-asyncio", + "requests", + ], + "flask": [ + "flask", + "flask-login", + "werkzeug", # flask-v{1,2.0}: Werkzeug<2.1.0 + "markupsafe", # flask-v{1,2.0}: markupsafe<2.1.0 + ], + "gql": [ + "gql[all]", + ], + "graphene": [ + "graphene", + "blinker", + "fastapi", + "flask", + "httpx", + ], + "grpc": [ + "grpcio", + "protobuf", + "mypy-protobuf", + "types-protobuf", + "pytest-asyncio", + ], + "httpx": [ + "httpx", + "anyio<4.0.0", + ], + "huey": [ + "huey", + ], + "huggingface_hub": [ + "huggingface_hub", + ], + "langchain": [ + "langchain", + "langchain-community", + "openai", + "tiktoken", + "httpx", + ], + "langchain-notiktoken": [ + "langchain", + "langchain-openai", + "openai", + ], + "litestar": [ + "litestar", + "pytest-asyncio", + "python-multipart", + "requests", + "cryptography", + "httpx", + ], + "loguru": [ + "loguru", + ], + "openai": [ + "openai", + "pytest-asyncio", + "tiktoken", + "httpx", + ], + "openai-notiktoken": [ + "openai", + "pytest-asyncio", + ], + "openfeature": [ + "openfeature-sdk", + ], + "launchdarkly": [ + "launchdarkly-server-sdk", + ], + "opentelemetry": [ + "opentelemetry-distro", + ], + "pure_eval": [ + "pure_eval", + ], + "pymongo": [ + "pymongo", + "mockupdb", + ], + "pyramid": [ + "pyramid", + "werkzeug<2.1.0", + ], + "quart": [ + "quart", + "quart-auth", + "pytest-asyncio", + "blinker", + "jinja2", + "hypercorn", + "taskgroup", + ], + "ray": [ + "ray", + ], + "redis": [ + "redis", + "fakeredis", + "pytest<8.0.0", + "pytest-asyncio", + ], + "redis-py-cluster-legacy": [ + "redis-py-cluster", + ], + "requests": [ + "requests", + ], + "rq": [ + "rq", + "fakeredis", + ], + "sanic": [ + "sanic", + "websockets<11.0", + "aiohttp", + "sanic_testing", + "aiocontextvars", + ], + "spark": [ + "pyspark", + ], + "starlette": [ + "starlette", + "pytest-asyncio", + "python-multipart", + "requests", + "anyio<4.0.0", + "jinja2", + "httpx", + ], + "starlite": [ + "starlite", + "pytest-asyncio", + "pytest-multipart", + "requests", + "cryptography", + "pydantic<2.0.0", + "httpx<0.28", + ], + "sqlalchemy": [ + "sqlalchemy", + ], + "strawberry": [ + "strawberry-graphql[fastapi,flask]", + "fastapi", + "flask", + "httpx", + ], + "tornado": [ + "tornado", + "pytest", + ], + "trytond": [ + "trytond", + "werkzeug", + ], + "typer": [ + "typer", + ], + "unleash": [ + "UnleashClient", + ], +} diff --git a/scripts/populate_tox/tox.jinja b/scripts/populate_tox/tox.jinja new file mode 100644 index 0000000000..6f373a64a2 --- /dev/null +++ b/scripts/populate_tox/tox.jinja @@ -0,0 +1,211 @@ +# Tox (http://codespeak.net/~hpk/tox/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. +# +# This file has been generated from a template +# by scripts/populate_tox/populate_tox.py. Any changes to the file should be made +# in the script and the file regenerated. + +[tox] +requires = + # This version introduced using pip 24.1 which does not work with older Celery and HTTPX versions. + virtualenv<20.26.3 +envlist = + # === Common === + {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-common + + # === Gevent === + {py3.6,py3.8,py3.10,py3.11,py3.12}-gevent + + # === Cloud Resource Context === + {py3.6,py3.12,py3.13}-cloud_resource_context + + # ==== GCP === + {py3.7}-gcp + + # === Asgi === + {py3.7,py3.12,py3.13}-asgi + + # OpenTelemetry Experimental (POTel) + {py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-potel + + # === Integrations === + {% for group, integrations in groups.items() %} + # ~~~ {{ group }} ~~~ + {% for integration in integrations %} + {% for release in integration.releases %} + {{ release.rendered_python_versions }}-{{ integration.name }}-v{{ release }} + {% endfor %} + + {% endfor %} + {% endfor %} + +[testenv] +deps = + # if you change requirements-testing.txt and your change is not being reflected + # in what's installed by tox (when running tox locally), try running tox + # with the -r flag + -r requirements-testing.txt + + linters: -r requirements-linting.txt + linters: werkzeug<2.3.0 + + # === Common === + py3.8-common: hypothesis + common: pytest-asyncio + # See https://github.com/pytest-dev/pytest/issues/9621 + # 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 + + # === Gevent === + {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11}-gevent: gevent>=22.10.0, <22.11.0 + {py3.12}-gevent: gevent + # See https://github.com/pytest-dev/pytest/issues/9621 + # and https://github.com/pytest-dev/pytest-forked/issues/67 + # for justification of the upper bound on pytest + {py3.6,py3.7}-gevent: pytest<7.0.0 + {py3.8,py3.9,py3.10,py3.11,py3.12}-gevent: pytest + + # === Asgi === + asgi: pytest-asyncio + asgi: async-asgi-testclient + + # OpenTelemetry Experimental (POTel) + potel: -e .[opentelemetry-experimental] + + # === Integrations === + {% for group, integrations in groups.items() %} + # ~~~ {{ group }} ~~~ + {% for integration in integrations %} + {% for release in integration.releases %} + {% if integration.extra %} + {{ integration.name }}-v{{ release }}: {{ integration.package }}[{{ integration.extra }}]=={{ release }} + {% else %} + {{ integration.name }}-v{{ release }}: {{ integration.package }}=={{ release }} + {% endif %} + {% endfor %} + {% for dependency in integration.dependencies %} + {{ integration.name }}: {{ dependency }} + {% endfor %} + + {% endfor %} + {% endfor %} + + +setenv = + PYTHONDONTWRITEBYTECODE=1 + OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES + COVERAGE_FILE=.coverage-sentry-{envname} + py3.6: COVERAGE_RCFILE=.coveragerc36 + + django: DJANGO_SETTINGS_MODULE=tests.integrations.django.myapp.settings + + common: TESTPATH=tests + gevent: TESTPATH=tests + aiohttp: TESTPATH=tests/integrations/aiohttp + anthropic: TESTPATH=tests/integrations/anthropic + ariadne: TESTPATH=tests/integrations/ariadne + arq: TESTPATH=tests/integrations/arq + asgi: TESTPATH=tests/integrations/asgi + asyncpg: TESTPATH=tests/integrations/asyncpg + aws_lambda: TESTPATH=tests/integrations/aws_lambda + beam: TESTPATH=tests/integrations/beam + boto3: TESTPATH=tests/integrations/boto3 + bottle: TESTPATH=tests/integrations/bottle + celery: TESTPATH=tests/integrations/celery + chalice: TESTPATH=tests/integrations/chalice + clickhouse_driver: TESTPATH=tests/integrations/clickhouse_driver + cohere: TESTPATH=tests/integrations/cohere + cloud_resource_context: TESTPATH=tests/integrations/cloud_resource_context + django: TESTPATH=tests/integrations/django + dramatiq: TESTPATH=tests/integrations/dramatiq + falcon: TESTPATH=tests/integrations/falcon + fastapi: TESTPATH=tests/integrations/fastapi + flask: TESTPATH=tests/integrations/flask + gcp: TESTPATH=tests/integrations/gcp + gql: TESTPATH=tests/integrations/gql + graphene: TESTPATH=tests/integrations/graphene + grpc: TESTPATH=tests/integrations/grpc + httpx: TESTPATH=tests/integrations/httpx + huey: TESTPATH=tests/integrations/huey + huggingface_hub: TESTPATH=tests/integrations/huggingface_hub + langchain: TESTPATH=tests/integrations/langchain + launchdarkly: TESTPATH=tests/integrations/launchdarkly + litestar: TESTPATH=tests/integrations/litestar + loguru: TESTPATH=tests/integrations/loguru + openai: TESTPATH=tests/integrations/openai + openfeature: TESTPATH=tests/integrations/openfeature + opentelemetry: TESTPATH=tests/integrations/opentelemetry + potel: TESTPATH=tests/integrations/opentelemetry + pure_eval: TESTPATH=tests/integrations/pure_eval + pymongo: TESTPATH=tests/integrations/pymongo + pyramid: TESTPATH=tests/integrations/pyramid + quart: TESTPATH=tests/integrations/quart + ray: TESTPATH=tests/integrations/ray + redis: TESTPATH=tests/integrations/redis + redis_py_cluster_legacy: TESTPATH=tests/integrations/redis_py_cluster_legacy + requests: TESTPATH=tests/integrations/requests + rq: TESTPATH=tests/integrations/rq + sanic: TESTPATH=tests/integrations/sanic + spark: TESTPATH=tests/integrations/spark + starlette: TESTPATH=tests/integrations/starlette + starlite: TESTPATH=tests/integrations/starlite + sqlalchemy: TESTPATH=tests/integrations/sqlalchemy + strawberry: TESTPATH=tests/integrations/strawberry + tornado: TESTPATH=tests/integrations/tornado + trytond: TESTPATH=tests/integrations/trytond + typer: TESTPATH=tests/integrations/typer + socket: TESTPATH=tests/integrations/socket + +passenv = + SENTRY_PYTHON_TEST_AWS_ACCESS_KEY_ID + SENTRY_PYTHON_TEST_AWS_SECRET_ACCESS_KEY + SENTRY_PYTHON_TEST_POSTGRES_HOST + SENTRY_PYTHON_TEST_POSTGRES_USER + SENTRY_PYTHON_TEST_POSTGRES_PASSWORD + SENTRY_PYTHON_TEST_POSTGRES_NAME + +usedevelop = True + +extras = + bottle: bottle + falcon: falcon + flask: flask + pymongo: pymongo + +basepython = + py3.6: python3.6 + py3.7: python3.7 + py3.8: python3.8 + py3.9: python3.9 + py3.10: python3.10 + py3.11: python3.11 + py3.12: python3.12 + py3.13: python3.13 + + # Python version is pinned here because flake8 actually behaves differently + # depending on which version is used. You can patch this out to point to + # some random Python 3 binary, but then you get guaranteed mismatches with + # CI. Other tools such as mypy and black have options that pin the Python + # version. + linters: python3.12 + +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 {env:TESTPATH} -o junit_suite_name={envname} {posargs} + +[testenv:linters] +commands = + flake8 tests sentry_sdk + black --check tests sentry_sdk + mypy sentry_sdk