[tox]
min_version = 4
# list of environments to run by default with tox run
# using Python 3.14 as the default, this needs to be kept in line with
# .github/actions/set-dev-env/action.yml (default Python version)
env_list =
    lint,
    compile-assets,
    i18n-compile,
    py314-docs,
    py314-tests,
    a11y-tests

# convenience label for running tests with a given Python version, aimed at
# helping contributors run common tasks without needing to call all the steps
# For example to run the tests: tox run -m tests
labels =
    tests = compile-assets, i18n-compile, py314-tests
    a11y = compile-assets, i18n-compile, py314-docs, a11y-tests
    i18n = i18n-extract, i18n-compile
    live-server = compile-assets, i18n-compile, docs-live

# general tox env configuration
# these can be run with any py3{10,14} version, for example:
# tox run -e py310-lint
[testenv]
deps =
    lint: pre-commit
    compile-assets: sphinx-theme-builder[cli]
    profile-docs: py-spy
extras =
    {docs-no-checks, docs-linkcheck, profile-docs}: doc
skip_install =
    lint: true # do not need to install to lint
    profile-docs: true # avoids issues with py-spy and setting the git repo
    compile-assets: false
package = editable
commands =
    lint: pre-commit run -a
    compile-assets: stb compile  # bundle JavaScript and Sass
    # can substitute the target directory with any other directory by calling:
    # tox run -e docs-no-checks -- path/to/other/directory
    docs-no-checks: sphinx-build {posargs:audit}/site {posargs:audit}/_build
    # example tox run -e py310-profile-docs -- -o profile.svg -n 100
    profile-docs: python ./tools/profile.py {posargs}

# tests can be ran with or without coverage (see examples below),
# it is recommended to run compile-assets before running tests
# i18n-compile MUST be run before running tests
# (see examples below),
# tox run -e compile-assets,i18n-compile,py310-tests
# if you want to skip the assets and translations compilation step you can run
# the tests without `compile-assets,i18n-compile`, for example:
# tox run -e py310-tests
# run tests with a specific Sphinx version
# tox run -e compile-assets,i18n-compile,py310-sphinx70-tests
# run tests without coverage
# tox run -e compile-assets,i18n-compile,py310-tests-no-cov
# by default we will retain playwright traces on failure
[testenv:py3{10,11,12,13,14}{,-sphinx70,-sphinxdev,}-tests{,-no-cov}]
description = "Run tests Python and Sphinx versions. If a Sphinx version is specified, it will use that version vs the default in pyproject.toml"
# need to ensure the package is installed in editable mode
package = editable
extras =
    test # install dependencies, includes pytest-playwright - defined in pyproject.toml
pass_env = GITHUB_ACTIONS # so we can check if this is run on GitHub Actions
deps =
    coverage[toml]
    py310-sphinx70-tests: sphinx~=7.0.0
    py314-sphinxdev: sphinx[test] @ git+https://github.com/sphinx-doc/sphinx.git@master
depends =
    compile-assets,
    i18n-compile
allowlist_externals=
    playwright
    bash
commands =
    bash -c 'if [[ "{env:GITHUB_ACTIONS:}" == "true" ]]; then playwright install --with-deps; else playwright install; fi'
    py3{10,11,12,13,14}{,-sphinx70,-sphinxdev,}-tests: coverage run -m pytest -m "not a11y" {posargs:--tracing=retain-on-failure}
    py3{10,11,12,13,14}{,-sphinx70,-sphinxdev,}-tests-no-cov: pytest -m "not a11y" {posargs:--tracing=retain-on-failure}

# run accessibility tests with Playwright and axe-core
# compiling the assets is needed before running the tests
# tox run -e compile,py314-docs,a11y-tests
# by default we will retain playwright traces on failure and run the tests on chromium
# to run the tests on firefox you can call:
# tox run -e compile,py314-docs,a11y-tests-firefox
[testenv:a11y-tests{-chromium,-firefox}]
description = "run accessibility tests with Playwright and axe-core"
base_python = py314 # keep in sync with tests.yml
pass_env = GITHUB_ACTIONS # so we can check if this is run on GitHub Actions
extras =
    test # install dependencies, includes pytest-playwright - defined in pyproject.toml
depends =
    compile-assets,
    i18n-compile
    py314-docs
allowlist_externals=
    playwright
    bash
commands =
    bash -c 'if [[ "{env:GITHUB_ACTIONS:}" == "true" ]]; then playwright install --with-deps; else playwright install; fi'
    bash -c 'test -d docs/_build/html/ && echo "--- Directory exists ---" || exit -1'
    a11y-tests{,-chromium}: pytest -m "a11y" --maxfail=1 --browser=chromium {posargs:--tracing=retain-on-failure}
    a11y-tests-firefox: pytest -m "a11y" --maxfail=5 --browser=firefox {posargs:--tracing=retain-on-failure}

# build PST documentation with the default or a specific Sphinx version
# since we are building the documentation we install the packaged dev version of PST
# tox run -e py310-docs
# tox run -e py310-sphinx70-docs
[testenv:py3{10,14}{,-sphinx70}-docs]
description = build the documentation and place in docs/_build/html
# suppress Py3.11's new "can't debug frozen modules" warning
set_env = PYDEVD_DISABLE_FILE_VALIDATION=1
# keep this in sync across all docs environments
extras = {[testenv:docs-no-checks]extras}
deps =
    py310-sphinx70-docs: sphinx~=7.0.0
    py310-sphinx70-docs: astroid>=3.0,!=4.0.3
depends =
    compile-assets,
    i18n-compile
commands =
    sphinx-build -b html docs/ docs/_build/html -nTv -w warnings.txt
    python tests/utils/check_warnings.py

# build the docs without checking for warnings
# tox run -e docs-no-checks
[testenv:docs-no-checks]
description = "Build documentation without checking for warnings"
extras = doc
package = editable
set_env = PYDEVD_DISABLE_FILE_VALIDATION=1
depends =
    compile-assets,
    i18n-compile
commands =
    sphinx-build {posargs:audit}/site {posargs:audit}/_build

# recommended for local development, this command will build the PST documentation
# with the default Sphinx version and the PST installed in editable mode
# tox run -e docs-dev
[testenv:docs-dev]
description = build the documentation and place in docs/_build/html (dev mode)
# suppress Py3.11's new "can't debug frozen modules" warning
set_env = PYDEVD_DISABLE_FILE_VALIDATION=1
# keep this in sync across all docs environments
extras = {[testenv:docs-no-checks]extras}
package = editable
depends =
    compile-assets,
    i18n-compile
commands =
    sphinx-build -b html docs/ docs/_build/html -nTv -w warnings.txt {posargs}
    python tests/utils/check_warnings.py

# build the docs with live-reload, if you are working on the docs only (no theme changes) the best option is to call
# tox run -e docs-live
# this will only watch the docs directory and rebuild the docs when changes are detected
# if you are working on the theme (HTML, jinja templates, JS, CSS) and the docs, you can call
# tox run -e docs-live-theme
[testenv:docs-live{,-theme}]
description = "Build and serve the documentation with live-reload"
extras =
    dev
package = editable
deps =
    sphinx-theme-builder[cli]
# suppress Py3.11's new "can't debug frozen modules" warning
set_env = PYDEVD_DISABLE_FILE_VALIDATION=1
depends =
    compile-assets,
    i18n-compile
commands =
    docs-live-theme: stb serve docs --open-browser --re-ignore=locale|api|_build|\.jupyterlite\.doit\.db
    docs-live: sphinx-autobuild docs/ docs/_build/html --open-browser --re-ignore=locale|api|_build|\.jupyterlite\.doit\.db

# check external links in the documentation
# tox run -e docs-linkcheck
[testenv:docs-linkcheck]
description = "Check external links in the documentation"
extras = doc
allowlist_externals = bash
basepython = py314
package = editable
set_env = PYDEVD_DISABLE_FILE_VALIDATION=1
depends =
    compile-assets,
    i18n-compile
commands =
    sphinx-build -b linkcheck docs/ docs/_build/linkcheck -w warnings.txt --keep-going -q
    bash -c "echo 'Linkcheck complete; see docs/_build/linkcheck/output.txt for any errors'"

# extract translatable files into the POT file and update locale PO files
# tox run -e i18n-extract
# this will update all locales, to update a single locale you can
# pass the locale code, for example to update the Spanish locale only:
# tox run -e i18n-extract -- --locale=es
[testenv:i18n-extract]
description = "Extract translatable messages from the source code and update locale files"
extras = i18n
package = editable
allowlist_externals = bash
commands =
    # explicitly pass this as a bash command to set PST_VERSION
    bash -c "PST_VERSION=$(pip show pydata-sphinx-theme | grep Version | awk -F': ' '{print $2}') && \
    pybabel extract . -F babel.cfg -o src/pydata_sphinx_theme/locale/sphinx.pot --keywords='_ __ l_ lazy_gettext' \
    --project=pydata-sphinx-theme --copyright-holder='PyData developers' --version=$PST_VERSION"
    pybabel update -i src/pydata_sphinx_theme/locale/sphinx.pot -d src/pydata_sphinx_theme/locale -D sphinx {posargs}

# add a new locale for translations based on the catalog template
# the locale needs to be given in the format of the language code
# for example: `tox -e i18n-new-locale -- ss`
[testenv:i18n-new-locale]
description = "Create a new locale based on our catalog template"
extras = {[testenv:i18n-extract]extras}
package = editable
commands =
    pybabel init -i src/pydata_sphinx_theme/locale/sphinx.pot -d src/pydata_sphinx_theme/locale -l {posargs}

# compile translation catalogs to binary MO files
# tox run -e i18n-compile
[testenv:i18n-compile]
description = "Compile translation catalogs to binary MO files"
extras = {[testenv:i18n-extract]extras}
package = editable
commands =
    pybabel compile -d src/pydata_sphinx_theme/locale -D sphinx
