tox.ini•15.1 kB
[tox]
isolated_build = True
skipsdist = True
[testenv]
package = wheel
wheel_build_env = .pkg
[testenv:phoenix_client]
description = Run tests for the arize-phoenix-client package
changedir = packages/phoenix-client/
deps =
  -r requirements/packages/phoenix-client.txt
commands_pre = uv pip install --strict --reinstall-package arize-phoenix-client .
commands =
  uv pip list -v
  {envbindir}/pyright .
  {envbindir}/mypy --strict .
  {envbindir}/pytest {posargs} tests/client
[testenv:phoenix_client_canary_tests_sdk_openai]
description = Run phoenix-client canary tests for third-party SDK: anthropic
changedir = packages/phoenix-client/
setenv =
  SDK = openai
  MOD = chat
  TESTS = tests/canary/sdk
  HELPERS = src/phoenix/client/helpers/sdk
  SDK_TESTS = {env:TESTS}/{env:SDK}
  SDK_HELPERS = {env:HELPERS}/{env:SDK}
  REQ = {toxinidir}/requirements
  SDK_REQ = {env:REQ}/canary/sdk/{env:SDK}.txt
commands_pre =
  uv pip install --strict -U --reinstall-package arize-phoenix-client .
  uv pip uninstall -r {toxinidir}/requirements/canary/sdk/{env:SDK}.txt
  uv pip list -v
commands =
  python -c "import phoenix.client.helpers.sdk.{env:SDK}.{env:MOD}"
  uv pip install --strict -U -r {env:REQ}/ci.txt
  uv pip install --strict -U -r {env:SDK_REQ}
  uv pip list -v
  pyright -p {env:HELPERS}/pyrightconfig.json {env:SDK_HELPERS}
  pyright -p {env:TESTS}/pyrightconfig.json {env:SDK_TESTS}
  mypy --strict --follow-untyped-imports {env:SDK_HELPERS}/{env:MOD}.py
  mypy --strict --follow-untyped-imports {env:SDK_TESTS}/test_{env:MOD}.py
  pytest --disable-socket {posargs} {env:SDK_TESTS}
[testenv:phoenix_client_canary_tests_sdk_anthropic]
description = Run phoenix-client canary tests for third-party SDK: anthropic
changedir = packages/phoenix-client/
setenv =
  SDK = anthropic
  MOD = messages
  TESTS = tests/canary/sdk
  HELPERS = src/phoenix/client/helpers/sdk
  SDK_TESTS = {env:TESTS}/{env:SDK}
  SDK_HELPERS = {env:HELPERS}/{env:SDK}
  REQ = {toxinidir}/requirements
  SDK_REQ = {env:REQ}/canary/sdk/{env:SDK}.txt
commands_pre =
  uv pip install --strict -U --reinstall-package arize-phoenix-client .
  uv pip uninstall -r {toxinidir}/requirements/canary/sdk/{env:SDK}.txt
  uv pip list -v
commands =
  python -c "import phoenix.client.helpers.sdk.{env:SDK}.{env:MOD}"
  uv pip install --strict -U -r {env:REQ}/ci.txt
  uv pip install --strict -U -r {env:SDK_REQ}
  uv pip list -v
  pyright -p {env:HELPERS}/pyrightconfig.json {env:SDK_HELPERS}
  pyright -p {env:TESTS}/pyrightconfig.json {env:SDK_TESTS}
  mypy --strict --follow-untyped-imports {env:SDK_HELPERS}/{env:MOD}.py
  mypy --strict --follow-untyped-imports {env:SDK_TESTS}/test_{env:MOD}.py
  pytest --disable-socket {posargs} {env:SDK_TESTS}
[testenv:phoenix_client_canary_tests_sdk_google_generativeai]
description = Run phoenix-client canary tests for third-party SDK: google_generativeai
changedir = packages/phoenix-client/
setenv =
  SDK = google_generativeai
  MOD = generate_content
  TESTS = tests/canary/sdk
  HELPERS = src/phoenix/client/helpers/sdk
  SDK_TESTS = {env:TESTS}/{env:SDK}
  SDK_HELPERS = {env:HELPERS}/{env:SDK}
  REQ = {toxinidir}/requirements
  SDK_REQ = {env:REQ}/canary/sdk/{env:SDK}.txt
commands_pre =
  uv pip install --strict -U --reinstall-package arize-phoenix-client .
  uv pip uninstall -r {toxinidir}/requirements/canary/sdk/{env:SDK}.txt
  uv pip list -v
commands =
  python -c "import phoenix.client.helpers.sdk.{env:SDK}.{env:MOD}"
  uv pip install --strict -U -r {env:REQ}/ci.txt
  uv pip install --strict -U -r {env:SDK_REQ}
  uv pip list -v
  pyright -p {env:HELPERS}/pyrightconfig.json {env:SDK_HELPERS}
  pyright -p {env:TESTS}/pyrightconfig.json {env:SDK_TESTS}
  mypy --strict --follow-untyped-imports {env:SDK_HELPERS}/{env:MOD}.py
  mypy --strict --follow-untyped-imports {env:SDK_TESTS}/test_{env:MOD}.py
  pytest --disable-socket {posargs} {env:SDK_TESTS}
[testenv:phoenix_evals]
description = Run tests for the arize-phoenix-evals package
changedir = packages/phoenix-evals/
deps =
  -r requirements/packages/phoenix-evals.txt
commands_pre = uv pip install --strict --reinstall-package arize-phoenix-evals .[test]
commands =
  uv pip list -v
  mypy .
  pytest {posargs} .
[testenv:phoenix_otel]
description = Run tests for the arize-phoenix-otel package
changedir = packages/phoenix-otel/
deps =
  -r requirements/ci.txt
commands_pre = uv pip install --strict --reinstall-package arize-phoenix-otel .[test]
commands =
  uv pip list -v
  mypy .
  pytest -ra {posargs:.}
[testenv:type_check_integration_tests]
description = Run type checking with mypy on integration tests
changedir = tests/integration
deps =
  -r requirements/integration-tests.txt
commands_pre =
  uv pip install --strict --reinstall-package arize-phoenix {toxinidir}
  uv pip install --strict --reinstall-package arize-phoenix-client {toxinidir}/packages/phoenix-client
commands =
  uv pip list -v
  pyright -p pyrightconfig.json client/
  mypy --strict .
[testenv:integration_tests]
description = Run integration tests
pass_env =
  CI_TEST_DB_BACKEND
changedir = tests/integration
deps =
  -r requirements/integration-tests.txt
setenv =
  PHOENIX_MASK_INTERNAL_SERVER_ERRORS = false
commands_pre =
  uv pip install --strict --reinstall-package arize-phoenix {toxinidir}
  uv pip install --strict --reinstall-package arize-phoenix-client {toxinidir}/packages/phoenix-client
commands =
  uv pip list -v
  pytest {posargs} .
[testenv:type_check_unit_tests]
description = Run type checking with mypy on unit tests
changedir = tests/
deps =
  -r requirements/unit-tests.txt
commands_pre =
  uv pip install --strict --reinstall-package arize-phoenix {toxinidir}
commands =
  uv pip list -v
  mypy --strict unit/
[testenv:unit_tests]
description = Run unit tests
changedir = tests
deps =
  -r requirements/unit-tests.txt
setenv =
  PHOENIX_MASK_INTERNAL_SERVER_ERRORS = false
commands_pre =
  uv pip install --strict --reinstall-package arize-phoenix {toxinidir}
commands =
  uv pip list -v
  pytest {posargs} unit/
[testenv:unit_tests_local_evals]
description = Run unit tests with phoenix-evals installed from local source
changedir = tests
deps =
  -r requirements/unit-tests.txt
commands_pre =
  uv pip install --strict --reinstall-package arize-phoenix --reinstall-package arize-phoenix-evals ../. arize-phoenix-evals@../packages/phoenix-evals
commands =
  uv pip list -v
  pytest {posargs} unit/
[testenv:type_check]
description = Run type checking with mypy on src/phoenix
deps =
  -r requirements/type-check.txt
commands_pre =
  uv pip install --strict --reinstall-package arize-phoenix .
  uv pip install --strict --reinstall-package arize-phoenix-client {toxinidir}/packages/phoenix-client
commands =
  uv pip list -v
  mypy --strict src/phoenix/
[testenv:ensure_graphql_mutations_have_permission_classes]
description = Ensure each GraphQL mutation and subscription is decorated with permission classes
changedir = src/phoenix/server/api
commands =
  python {toxinidir}/scripts/ci/ensure_graphql_mutations_have_permission_classes.py
[testenv:clean_jupyter_notebooks]
description = Clear output and metadata from Jupyter notebooks
deps =
  -r requirements/clean-jupyter-notebooks.txt
commands =
  uv pip list -v
  find . -type f -name "*.ipynb" -not -path "*/tutorials/evals/*" -not -path "*/tutorials/ai_evals_course/*" -exec jupyter nbconvert --ClearOutputPreprocessor.enabled=True --ClearMetadataPreprocessor.enabled=True --inplace {} \;
allowlist_externals =
  find
[testenv:build_graphql_schema]
description = Export GraphQL schema to a file (Python 3.9)
recreate = true
basepython = python3.9
changedir = app
deps =
  -r requirements/build-graphql-schema.txt
commands_pre =
  uv pip install --strict --reinstall-package arize-phoenix {toxinidir}
  uv pip install 'libcst<1.8' # https://github.com/strawberry-graphql/strawberry/issues/3874
commands =
  uv pip list -v
  strawberry export-schema phoenix.server.api.schema:_EXPORTED_GRAPHQL_SCHEMA -o schema.graphql
[testenv:build_openapi_schema]
description = Export OpenAPI schema to a file (Python 3.9)
recreate = true
basepython = python3.9
changedir = schemas
commands_pre =
  uv pip install --strict --reinstall-package arize-phoenix {toxinidir}
commands =
  uv pip list -v
  python -m phoenix.server.api.openapi.main -o openapi.json
[testenv:compile_protobuf]
description = Compile protobuf files (Python 3.9)
basepython = python3.9
deps =
  -r requirements/compile-protobuf.txt
commands =
  uv pip list -v
  python -m grpc_tools.protoc -I src/phoenix/proto --python_out=src/phoenix --mypy_out=src/phoenix src/phoenix/proto/trace/v1/evaluation.proto
[testenv:add_symlinks]
description = Add symlinks to packages (for editable install)
changedir = src/phoenix
allowlist_externals =
  sh
commands =
  sh -c '[ -e client ] || ln -s ../../packages/phoenix-client/src/phoenix/client client'
  sh -c '[ -e evals ] || ln -s ../../packages/phoenix-evals/src/phoenix/evals evals'
  sh -c '[ -e otel ] || ln -s ../../packages/phoenix-otel/src/phoenix/otel otel'
[testenv:remove_symlinks]
description = Remove symlinks to packages
changedir = src/phoenix
allowlist_externals = find
commands =
  find . -maxdepth 1 -type l -exec unlink {} \;
[testenv:phoenix_main]
description = Run Phoenix server
pass_env =
  PHOENIX_PORT
  PHOENIX_GRPC_PORT
  PHOENIX_HOST_ROOT_PATH
  PHOENIX_SQL_DATABASE_URL
  PHOENIX_SQL_DATABASE_SCHEMA
  PHOENIX_ENABLE_AUTH
  PHOENIX_SECRET
  PHOENIX_DISABLE_BASIC_AUTH
  PHOENIX_ADMINS
  PHOENIX_COOKIES_PATH
  PHOENIX_DISABLE_LOGIN_FORM
  PHOENIX_OAUTH2_ARIZE_CLIENT_SECRET
  PHOENIX_OAUTH2_ARIZE_CLIENT_ID
  PHOENIX_OAUTH2_ARIZE_OIDC_CONFIG_URL
  PHOENIX_OAUTH2_ARIZE_ALLOW_SIGN_UP
  PHOENIX_OAUTH2_ARIZE_AUTO_LOGIN
  PHOENIX_OAUTH2_GOOGLE_CLIENT_ID
  PHOENIX_OAUTH2_GOOGLE_CLIENT_SECRET
  PHOENIX_OAUTH2_GOOGLE_OIDC_CONFIG_URL
  PHOENIX_OAUTH2_GOOGLE_ALLOW_SIGN_UP
  PHOENIX_OAUTH2_GOOGLE_AUTO_LOGIN
  PHOENIX_OAUTH_GITHUB_CLIENT_ID
  PHOENIX_OAUTH_GITHUB_CLIENT_SECRET
  PHOENIX_OAUTH2_AUTH0_CLIENT_ID
  PHOENIX_OAUTH2_AUTH0_CLIENT_SECRET
  PHOENIX_OAUTH2_AUTH0_OIDC_CONFIG_URL
  PHOENIX_OAUTH2_AUTH0_ALLOW_SIGN_UP
  PHOENIX_OAUTH2_AUTH0_AUTO_LOGIN
  PHOENIX_OAUTH2_AZURE_AD_OIDC_CONFIG_URL
  PHOENIX_OAUTH2_AZURE_AD_CLIENT_ID
  PHOENIX_OAUTH2_AZURE_AD_CLIENT_SECRET
  PHOENIX_OAUTH2_AZURE_AD_ALLOW_SIGN_UP
  PHOENIX_OAUTH2_AZURE_AD_AUTO_LOGIN
  PHOENIX_OAUTH2_AWS_COGNITO_CLIENT_ID
  PHOENIX_OAUTH2_AWS_COGNITO_CLIENT_SECRET
  PHOENIX_OAUTH2_AWS_COGNITO_OIDC_CONFIG_URL
  PHOENIX_OAUTH2_AWS_COGNITO_ALLOW_SIGN_UP
  PHOENIX_OAUTH2_AWS_COGNITO_AUTO_LOGIN
  PHOENIX_SMTP_HOSTNAME
  PHOENIX_SMTP_PORT
  PHOENIX_SMTP_USERNAME
  PHOENIX_SMTP_PASSWORD
  PHOENIX_ACCESS_TOKEN_EXPIRY_MINUTES
  PHOENIX_DATABASE_ALLOCATED_STORAGE_CAPACITY_GIBIBYTES
  PHOENIX_DANGEROUSLY_DISABLE_MIGRATIONS
  PHOENIX_DISABLE_BASIC_AUTH
  PHOENIX_ALLOWED_ORIGINS
  PHOENIX_LOGGING_LEVEL
  PHOENIX_FULLSTORY_ORG
commands_pre =
  uv tool install -U --force arize-phoenix@. \
    --reinstall-package arize-phoenix \
    --with-requirements requirements/dev.txt \
    --compile-bytecode
commands =
  uv tool run arize-phoenix {posargs:serve}
[testenv:ruff]
description = Run ruff for formatting and linting
commands_pre =
  uv tool install ruff@0.12.5
commands =
  uv tool run ruff format
  uv tool run ruff check --fix
[testenv:openapi_codegen_for_python_client]
description = Generate data models from OpenAPI schema for Python client
recreate = true
changedir = packages/phoenix-client/src/phoenix/client/__generated__/
commands_pre =
  uv tool install --force ruff@0.12.5
commands =
  uv pip list -v
  uv pip install datamodel-code-generator==0.32.0 pydantic==2.11.0
  python -c "import pathlib; pathlib.Path('v1/__init__.py').unlink(missing_ok=True)"
  datamodel-codegen \
    --input {toxinidir}/schemas/openapi.json \
    --input-file-type openapi \
    --output v1/.dataclass.py \
    --output-model-type dataclasses.dataclass \
    --collapse-root-models \
    --enum-field-as-literal all \
    --target-python-version 3.9 \
    --use-default-kwarg \
    --use-double-quotes \
    --use-generic-container-types \
    --wrap-string-literal \
    --disable-timestamp
  python -c "import re; file = 'v1/.dataclass.py'; lines = [re.sub(r'\\bSequence]', 'Sequence[Any]]', line) for line in open(file).readlines()]; open(file, 'w').writelines(lines)"
  python {toxinidir}/packages/phoenix-client/scripts/codegen/transform.py v1
  uv pip install --strict --reinstall-package arize-phoenix-client {toxinidir}/packages/phoenix-client
  uv pip list -v
  python -c "import phoenix.client.__generated__.v1"
  uv tool run ruff format v1
  uv tool run ruff check --fix v1
[testenv:graphql_codegen_for_python_tests]
description = Generate data models from GraphQL schema for Python tests
recreate = true
changedir = tests/__generated__/graphql/
commands =
  uv pip list -v
  python -c "import pathlib; pathlib.Path('__init__.py').unlink(missing_ok=True)"
  uv tool run --from 'datamodel-code-generator[graphql]' datamodel-codegen \
    --input {toxinidir}/app/schema.graphql \
    --input-file-type graphql \
    --output __init__.py \
    --output-model-type pydantic_v2.BaseModel \
    --collapse-root-models \
    --enable-faux-immutability \
    --enum-field-as-literal all \
    --target-python-version 3.9 \
    --use-default-kwarg \
    --use-double-quotes \
    --use-generic-container-types \
    --use-standard-collections \
    --wrap-string-literal \
    --disable-timestamp
  python __main__.py
[testenv:sync_models]
description = Sync model cost manifest from remote sources
recreate = true
commands_pre =
  uv pip install pydantic
commands =
  python {toxinidir}/.github/.scripts/sync_models.py
[testenv:ddl_extract]
description = Extract DDL schema from PostgreSQL database
basepython = python3.13
changedir = scripts/ddl
pass_env =
  PGHOST
  PGPORT
  PGDATABASE
  PGUSER
  PGPASSWORD
commands_pre =
  uv pip install --strict psycopg[binary] testing.postgresql pglast ty
  uv pip install --strict --reinstall-package arize-phoenix {toxinidir}
commands =
  uv pip list -v
  ty check generate_ddl_postgresql.py
  python generate_ddl_postgresql.py {posargs}
[testenv:docker_devops]
description = Run Docker devops environment
changedir = scripts/docker/devops
allowlist_externals =
  bash
commands =
  bash dev.sh {posargs:up}
[testenv:alembic]
description = Run alembic commands for database migrations
pass_env =
  PHOENIX_SQL_DATABASE_URL
  PHOENIX_SQL_DATABASE_SCHEMA
changedir = src/phoenix/db
commands_pre =
  uv pip install -q --strict --reinstall-package arize-phoenix {toxinidir}
commands =
  alembic {posargs:--help}
  # View migration history (shows available versions to upgrade/downgrade to): tox -e alembic -- history
  # Backward migrations: tox -e alembic -- downgrade -1
  # Forward migrations: tox -e alembic -- upgrade head
  # View current version: tox -e alembic -- current
[testenv:helm_tests]
description = Run comprehensive Helm chart tests
basepython = python3.14
changedir = scripts/ci
commands_pre =
  uv pip install ty PyYAML>=6.0
commands =
  uv pip list -v
  ty check test_helm.py {posargs}
  python test_helm.py {posargs}