# Tox (https://tox.readthedocs.io/) 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.

[tox]
requires =
    sphinx-scrapy[tox] @ git+https://github.com/scrapy/sphinx-scrapy.git@0.8.3
envlist = pre-commit,pylint,typing,py,docs
minversion = 1.7.0

[test-requirements]
deps =
    attrs
    coverage >= 7.10.6
    httpx
    pexpect >= 4.8.0
    pyftpdlib >= 2.0.1
    pygments
    pytest
    pytest-cov >= 7.0.0
    pytest-xdist
    sybil >= 1.3.0  # https://github.com/cjw296/sybil/issues/20#issuecomment-605433422
    testfixtures
    pytest-twisted >= 1.14.3

[testenv]
deps =
    {[test-requirements]deps}
    pytest >= 8.4.1  # https://github.com/pytest-dev/pytest/pull/13502
passenv =
    PYTEST_ADDOPTS
    S3_TEST_FILE_URI
    AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY
    AWS_SESSION_TOKEN
    GCS_TEST_FILE_URI
    GCS_PROJECT_ID
#allow tox virtualenv to upgrade pip/wheel/setuptools
download = true
commands =
    pytest {posargs:--cov-config=pyproject.toml --cov=scrapy --cov-report= --cov-report=term-missing --cov-report=xml --junitxml=testenv.junit.xml -o junit_family=legacy --durations=10 scrapy tests --doctest-modules}

[testenv:typing]
basepython = python3.10
deps =
    mypy==1.19.1
    typing-extensions==4.15.0
    Pillow==12.1.1
    Protego==0.6.0
    attrs==25.4.0
    boto3-stubs[s3]==1.42.59
    botocore-stubs==1.42.41
    h2==4.3.0
    httpx==0.28.1
    itemadapter==0.13.1
    ptpython==3.0.32
    ipython
    pyOpenSSL==25.3.0
    pytest==9.0.2
    types-Pygments==2.19.0.20251121
    types-defusedxml==0.7.0.20250822
    types-lxml==2026.2.16
    types-pexpect==4.9.0.20260127
    uvloop==0.22.1
    w3lib==2.4.0
    zstandard==0.25.0
commands =
    mypy {posargs:scrapy tests}

[testenv:typing-tests]
basepython = python3.10
deps =
    {[test-requirements]deps}
    {[testenv:typing]deps}
    pytest-mypy-testing==0.2.0
commands =
    pytest {posargs:tests_typing}

[testenv:pre-commit]
basepython = python3
deps =
    pre-commit
commands =
    pre-commit run {posargs:--all-files}

[testenv:pylint]
basepython = python3
deps =
    {[testenv:extra-deps]deps}
    pylint==4.0.2
commands =
    pylint conftest.py docs extras scrapy tests

[testenv:twinecheck]
basepython = python3
deps =
    twine==6.2.0
    build==1.3.0
commands =
    python -m build --sdist
    twine check dist/*

[pinned]
basepython = python3.10
deps =
    # pytest 8.4.1 adds support for Twisted 25.5.0 but drops support for Twisted < 24.10.0
    pytest==8.4.0
    Protego==0.1.15
    Twisted==21.7.0
    cryptography==37.0.0
    cssselect==0.9.1
    httpx==0.26.0
    itemadapter==0.1.0
    lxml==4.6.4
    parsel==1.5.0
    pyOpenSSL==22.0.0
    queuelib==1.4.2
    service_identity==18.1.0
    w3lib==1.17.0
    zope.interface==5.1.0
    {[test-requirements]deps}
setenv =
    _SCRAPY_PINNED=true
commands =
    pytest {posargs:--cov-config=pyproject.toml --cov=scrapy --cov-report=xml --cov-report= --junitxml=pinned.junit.xml -o junit_family=legacy --durations=10 scrapy tests}

[testenv:pinned]
basepython = {[pinned]basepython}
deps =
    {[pinned]deps}
    PyDispatcher==2.0.5
setenv =
    {[pinned]setenv}
commands = {[pinned]commands}

[testenv:extra-deps]
basepython = python3
deps =
    {[testenv]deps}
    Pillow
    Twisted[http2]
    boto3
    bpython  # optional for shell wrapper tests
    brotli >= 1.2.0; implementation_name != "pypy"  # optional for HTTP compress downloader middleware tests
    brotlicffi >= 1.2.0.0; implementation_name == "pypy"  # optional for HTTP compress downloader middleware tests
    google-cloud-storage
    httpx
    ipython
    robotexclusionrulesparser
    uvloop; platform_system != "Windows" and implementation_name != "pypy"
    zstandard; implementation_name != "pypy"  # optional for HTTP compress downloader middleware tests

[testenv:extra-deps-pinned]
basepython = {[pinned]basepython}
deps =
    {[pinned]deps}
    Pillow==8.3.2
    boto3==1.20.0
    bpython==0.7.1
    brotli==1.2.0; implementation_name != "pypy"
    brotlicffi==1.2.0.0; implementation_name == "pypy"
    google-cloud-storage==1.29.0
    httpx==0.26.0
    ipython==7.1.0
    robotexclusionrulesparser==1.6.2
    uvloop==0.16.0; platform_system != "Windows" and implementation_name != "pypy"
    zstandard==0.16.0; implementation_name != "pypy"
setenv =
    {[pinned]setenv}
commands = {[pinned]commands}

[testenv:default-reactor]
commands =
    {[testenv]commands} --reactor=default

[testenv:default-reactor-pinned]
basepython = {[pinned]basepython}
deps = {[testenv:pinned]deps}
commands = {[pinned]commands} --reactor=default
setenv =
    {[pinned]setenv}

[testenv:no-reactor]
deps =
    {[testenv]deps}
    pytest-asyncio
commands =
    {[testenv]commands} -p no:twisted --reactor=none

[testenv:no-reactor-extra-deps]
deps =
    {[testenv:extra-deps]deps}
    pytest-asyncio
commands =
    {[testenv]commands} -p no:twisted --reactor=none

[testenv:no-reactor-pinned]
basepython = {[pinned]basepython}
deps =
    {[testenv:pinned]deps}
    pytest-asyncio
commands = {[pinned]commands} -p no:twisted --reactor=none
setenv =
    {[pinned]setenv}

[testenv:pypy3]
basepython = pypy3
commands =
    ; not enabling coverage as it significantly increases the run time
    pytest {posargs:--durations=10 scrapy tests}

[testenv:pypy3-extra-deps]
basepython = pypy3
deps =
    {[testenv:extra-deps]deps}
commands = {[testenv:pypy3]commands}

[testenv:pypy3-pinned]
basepython = pypy3.11
deps =
    PyPyDispatcher==2.1.0
    {[test-requirements]deps}
    pytest==8.4.0
    Protego==0.1.15
    Twisted==21.7.0
    cryptography==44.0.2
    cssselect==0.9.1
    itemadapter==0.1.0
    lxml==5.3.2
    parsel==1.5.0
    pyOpenSSL==24.3.0
    queuelib==1.4.2
    service_identity==18.1.0
    w3lib==1.20.0
    zope.interface==5.1.0
commands =
    ; disabling coverage
    pytest {posargs:--durations=10 scrapy tests}
setenv =
    {[pinned]setenv}

[testenv:docs-tests]
changedir = docs
deps =
    {[test-requirements]deps}
    -rdocs/requirements.txt
commands =
    pytest

[testenv:docs-coverage]
changedir = docs
deps =
    -rdocs/requirements.txt
commands =
    sphinx-build -b coverage . {envtmpdir}/coverage

[testenv:docs-links]
changedir = docs
deps =
    -rdocs/requirements.txt
commands =
    sphinx-build -W -b linkcheck . {envtmpdir}/linkcheck


# Run S3 tests with botocore installed but without boto3.

[testenv:botocore]
deps =
    {[testenv]deps}
    botocore>=1.13.45
commands =
    pytest {posargs:--cov-config=pyproject.toml --cov=scrapy --cov-report=xml --cov-report= tests --junitxml=botocore.junit.xml -o junit_family=legacy} -m requires_botocore

[testenv:botocore-pinned]
basepython = {[pinned]basepython}
deps =
    {[pinned]deps}
    botocore==1.13.45
    # botocore 1.13.45 requires urllib3>=1.20,<1.26; requests 2.33.0 requires urllib3>=1.26,<3
    requests<2.33.0
setenv =
    {[pinned]setenv}
commands =
    pytest {posargs:--cov-config=pyproject.toml --cov=scrapy --cov-report=xml --cov-report= tests --junitxml=botocore-pinned.junit.xml -o junit_family=legacy} -m requires_botocore


# Run proxy tests that use mitmproxy in a separate env to avoid installing
# numerous mitmproxy deps in other envs (even in extra-deps), as they can
# conflict with other deps we want, or don't want, to have installed there.

[testenv:mitmproxy]
deps =
    {[testenv]deps}
    # mitmproxy does not support PyPy
    mitmproxy; implementation_name != "pypy"
commands =
    pytest {posargs:--cov-config=pyproject.toml --cov=scrapy --cov-report=xml --cov-report= tests --junitxml=botocore.junit.xml -o junit_family=legacy} -m requires_mitmproxy
