# the tox file specifies a way of running our test suite
# against different combinations of libraries and python
# versions.

[tox]
# Our various test environments. The py*-all tasks will run the core
# library tests and all contrib tests with the latest library versions.
# The others will test specific versions of libraries.
#
# FIXME[gabin]:
# If the env name is longer than 128 characters (linux kernel limit specified
# in "master/include/linux/binfmts.h"), we'll get a "bad interpreter: No such file or directory" error.
#
#See linux kernel limitation:
# - https://github.com/torvalds/linux/blob/master/include/linux/binfmts.h#L12
#
#See related github topic:
# - https://github.com/pypa/virtualenv/issues/596
envlist =
    flake8
    black
    wait
    {py34,py35,py36,py37}-tracer
    {py34,py35,py36,py37}-internal
    {py34,py35,py36,py37}-integration
    {py34,py35,py36,py37}-ddtracerun
    {py34,py35,py36,py37}-test_utils
    {py34,py35,py36,py37}-test_logging
# Integrations environments
    aiobotocore_contrib-py34-aiobotocore{02,03,04}
    aiobotocore_contrib-{py35,py36}-aiobotocore{02,03,04,05,07,08,09,010}
    # aiobotocore 0.2 and 0.4 do not work because they use async as a reserved keyword
    aiobotocore_contrib-py37-aiobotocore{03,05,07,08,09,010}
    # Python 3.7 needs at least aiohttp 2.3
    aiohttp_contrib-{py34,py35,py36}-aiohttp{12,13,20,21,22}-aiohttp_jinja{012,013}-yarl
    aiohttp_contrib-{py34,py35,py36,py37}-aiohttp23-aiohttp_jinja{015}-yarl10
    aiohttp_contrib-{py35,py36,py37}-aiohttp{30,31,32,33,34,35}-aiohttp_jinja{015}-yarl10
    aiopg_contrib-{py34,py35,py36}-aiopg{012,015}
    aiopg_contrib-py37-aiopg015
    algoliasearch_contrib-{py34,py35,py36,py37}-algoliasearch{1,2}
    asyncio_contrib-{py34,py35,py36,py37}
# boto needs moto<1 and moto<1 does not support Python >= 3.7
    boto_contrib-{py34,py35,py36}-boto
    botocore_contrib-{py34,py35,py36,py37}-botocore
    bottle_contrib{,_autopatch}-{py34,py35,py36,py37}-bottle{11,12}-webtest
    cassandra_contrib-{py34,py35,py36,py37}-cassandra{35,36,37,38,315}
# Non-4.x celery should be able to use the older redis lib, since it locks to an older kombu
    celery_contrib-{py34,py35,py36}-celery{31}-redis{210}
# 4.x celery bumps kombu to 4.4+, which requires redis 3.2 or later, this tests against
# older redis with an older kombu, and newer kombu/newer redis.
# https://github.com/celery/kombu/blob/3e60e6503a77b9b1a987cf7954659929abac9bac/Changelog#L35
    celery_contrib-{py34,py35,py36}-celery{40,41}-{redis210-kombu43,redis320-kombu44}
# Celery 4.2 is now limited to Kombu 4.3
# https://github.com/celery/celery/commit/1571d414461f01ae55be63a03e2adaa94dbcb15d
    celery_contrib-{py34,py35,py36}-celery42-redis210-kombu43
# Celery 4.3 wants Kombu >= 4.4 and Redis >= 3.2
# Python 3.7 needs Celery 4.3
    celery_contrib-{py34,py35,py36,py37}-celery43-redis320-kombu44
    consul_contrib-py{34,35,36,37}-consul{07,10,11}
    dbapi_contrib-{py34,py35,py36}
    django_contrib{,_autopatch}-{py34,py35,py36}-django{18,111}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached
    django_contrib{,_autopatch}-{py34,py35,py36}-django{200}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached
    django_drf_contrib-{py34,py35,py36}-django{111}-djangorestframework{34,37,38}
    django_drf_contrib-{py34,py35,py36}-django{200}-djangorestframework{37,38}
    dogpile_contrib-{py35,py36,py37}-dogpilecache{06,07,08,latest}
    elasticsearch_contrib-{py34,py35,py36}-elasticsearch{16,17,18,23,24,51,52,53,54,63,64}
    elasticsearch_contrib-{py34,py35,py36}-elasticsearch1{100}
    elasticsearch_contrib-{py34,py35,py36}-elasticsearch2{50}
    elasticsearch_contrib-{py34,py35,py36}-elasticsearch5{50}
    elasticsearch_contrib-{py34,py35,py36}-elasticsearch6{40}
    falcon_contrib{,_autopatch}-{py34,py35,py36}-falcon{10,11,12,13,14}
    flask_contrib{,_autopatch}-{py34,py35,py36}-flask{010,011,012,10}-blinker
    flask_cache_contrib{,_autopatch}-{py34,py35,py36,py37}-flask{010,011,012}-flaskcache{013}-memcached-redis{210}-blinker
    futures_contrib-{py34,py35,py36,py37}
    gevent_contrib-{py34,py35,py36}-gevent{11,12,13}
    gevent_contrib-py37-gevent{13,14}
    grpc_contrib-{py34,py35,py36,py37}-grpc{112,113,114,115,116,117,118,119,120,121,122}
    httplib_contrib-{py34,py35,py36,py37}
    jinja2_contrib-{py34,py35,py36,py37}-jinja{27,28,29,210}
    mako_contrib-{py34,py35,py36,py37}-mako{010,100}
    molten_contrib-py{36,37}-molten{070,072}
    mongoengine_contrib-{py34,py35,py36,py37}-mongoengine{015,016,017,018,latest}-pymongo{latest}
    mysql_contrib-{py34,py35,py36,py37}-mysqlconnector
    mysqldb_contrib-{py27}-mysqldb{12}
    mysqldb_contrib-{py34,py35,py36,py37}-mysqlclient{13}
    psycopg_contrib-{py34,py35,py36}-psycopg2{24,25,26,27,28}
    psycopg_contrib-py37-psycopg2{27,28}
    pylibmc_contrib-{py34,py35,py36,py37}-pylibmc{140,150}
    pymemcache_contrib{,_autopatch}-{py34,py35,py36,py37}-pymemcache{130,140}
    pymongo_contrib-{py34,py35,py36,py37}-pymongo{30,31,32,33,34,35,36,37,38,39,latest}-mongoengine{latest}
    pymysql_contrib-{py34,py35,py36,py37}-pymysql{07,08,09}
    pyramid_contrib{,_autopatch}-{py34,py35,py36,py37}-pyramid{17,18,19}-webtest
    redis_contrib-{py34,py35,py36,py37}-redis{26,27,28,29,210,300}
    rediscluster_contrib-{py34,py35,py36,py37}-rediscluster{135,136}-redis210
    requests_contrib{,_autopatch}-{py34,py35,py36,py37}-requests{208,209,210,211,212,213,219}
    kombu_contrib-{py34,py35,py36}-kombu{40,41,42}
    # Python 3.7 needs Kombu >= 4.2
    kombu_contrib-py37-kombu42
# python 3.6 requests + gevent regression test
# DEV: This is a known issue for gevent 1.1, suggestion is to upgrade to gevent > 1.2
#      https://github.com/gevent/gevent/issues/903
    requests_gevent_contrib-{py36}-requests{208,209,210,211,212,213,219}-gevent{12,13}
    requests_gevent_contrib-py37-requests{208,209,210,211,212,213,219}-gevent13
    sqlalchemy_contrib-{py34,py35,py36,py37}-sqlalchemy{10,11,12}-psycopg228-mysqlconnector
    sqlite3_contrib-{py34,py35,py36,py37}-sqlite3
    tornado_contrib-{py34,py35,py36,py37}-tornado{40,41,42,43,44,45}
    tornado_contrib-{py37}-tornado{50,51,60}
    vertica_contrib-{py34,py35,py36,py37}-vertica{060,070}
# Opentracer
    {py34,py35,py36,py37}-opentracer
    {py34,py35,py36,py37}-opentracer_asyncio
    {py34,py35,py36,py37}-opentracer_tornado-tornado{40,41,42,43,44}
    {py34,py35,py36}-opentracer_gevent-gevent{11,12}
    py37-opentracer_gevent-gevent{13,14}
# Unit tests: pytest based test suite that do not require any additional dependency
    unit_tests-{py34,py35,py36,py37}
    benchmarks-{py34,py35,py36,py37}

[testenv]
# Always re-run `setup.py develop` to ensure the proper C-extension .so files are created
# DEV: If we don't do this sometimes CircleCI gets messed up and only has the py27 .so
#      meaning running on py3.x will fail
#      https://stackoverflow.com/questions/57459123/why-do-i-need-to-run-tox-twice-to-test-a-python-package-with-c-extension
commands_pre={envpython} {toxinidir}/setup.py develop
usedevelop = True
basepython =
    py34: python3.4
    py35: python3.5
    py36: python3.6
    py37: python3.7

deps =
    pdbpp
    pytest>=3
    pytest-benchmark
    pytest-cov
    pytest-django
    pytest-mock
    opentracing
# test dependencies installed in all envs
    mock
# force the downgrade as a workaround
# https://github.com/aio-libs/aiohttp/issues/2662
    yarl: yarl==0.18.0
    yarl10: yarl>=1.0,<1.1
# integrations
    aiobotocore010: aiobotocore>=0.10,<0.11
    aiobotocore09: aiobotocore>=0.9,<0.10
    aiobotocore08: aiobotocore>=0.8,<0.9
    aiobotocore07: aiobotocore>=0.7,<0.8
    # aiobotocore06 does not work
    aiobotocore05: aiobotocore>=0.5,<0.6
    aiobotocore04: aiobotocore>=0.4,<0.5
    aiobotocore03: aiobotocore>=0.3,<0.4
    aiobotocore02: aiobotocore>=0.2,<0.3
    aiobotocore02: multidict==4.5.2
    aiobotocore{02,03,04}-{py34}: typing
    aiopg012: aiopg>=0.12,<0.13
    aiopg015: aiopg>=0.15,<0.16
    aiopg: sqlalchemy
    aiohttp12: aiohttp>=1.2,<1.3
    aiohttp13: aiohttp>=1.3,<1.4
    aiohttp20: aiohttp>=2.0,<2.1
    aiohttp21: aiohttp>=2.1,<2.2
    aiohttp22: aiohttp>=2.2,<2.3
    aiohttp23: aiohttp>=2.3,<2.4
    aiohttp30: aiohttp>=3.0,<3.1
    aiohttp31: aiohttp>=3.1,<3.2
    aiohttp32: aiohttp>=3.2,<3.3
    aiohttp33: aiohttp>=3.3,<3.4
    aiohttp34: aiohttp>=3.4,<3.5
    aiohttp35: aiohttp>=3.5,<3.6
    aiohttp_jinja012: aiohttp_jinja2>=0.12,<0.13
    aiohttp_jinja013: aiohttp_jinja2>=0.13,<0.14
    aiohttp_jinja015: aiohttp_jinja2>=0.15,<0.16
    algoliasearch1: algoliasearch>=1.2,<2
    algoliasearch2: algoliasearch>=2,<3
    blinker: blinker
    boto: boto
    boto: moto<1.0
    botocore: botocore
    py34-botocore: PyYAML<5.3
    py34-botocore: jsonpatch<1.25
    botocore: moto>=1.0,<2
    bottle11: bottle>=0.11,<0.12
    bottle12: bottle>=0.12,<0.13
    cassandra35: cassandra-driver>=3.5,<3.6
    cassandra36: cassandra-driver>=3.6,<3.7
    cassandra37: cassandra-driver>=3.7,<3.8
    cassandra38: cassandra-driver>=3.8,<3.9
    cassandra315: cassandra-driver>=3.15,<3.16
    celery31: celery>=3.1,<3.2
    celery40: celery>=4.0,<4.1
    celery41: celery>=4.1,<4.2
    celery42: celery>=4.2,<4.3
    celery43: celery>=4.3,<4.4
    consul07: python-consul>=0.7,<1.0
    consul10: python-consul>=1.0,<1.1
    consul11: python-consul>=1.1,<1.2
    ddtracerun: redis
    django18: django>=1.8,<1.9
    django111: django>=1.11,<1.12
    django200: django>=2.0,<2.1
    djangopylibmc06: django-pylibmc>=0.6,<0.7
    djangoredis45: django-redis>=4.5,<4.6
    djangorestframework34: djangorestframework>=3.4,<3.5
    djangorestframework37: djangorestframework>=3.7,<3.8
    djangorestframework38: djangorestframework>=3.8,<3.9
    dogpilecache06: dogpile.cache==0.6.*
    dogpilecache07: dogpile.cache==0.7.*
    dogpilecache08: dogpile.cache==0.8.*
    dogpilecachelatest: dogpile.cache
    elasticsearch16: elasticsearch>=1.6,<1.7
    elasticsearch17: elasticsearch>=1.7,<1.8
    elasticsearch18: elasticsearch>=1.8,<1.9
    elasticsearch23: elasticsearch>=2.3,<2.4
    elasticsearch24: elasticsearch>=2.4,<2.5
    elasticsearch51: elasticsearch>=5.1,<5.2
    elasticsearch52: elasticsearch>=5.2,<5.3
    elasticsearch53: elasticsearch>=5.3,<5.4
    elasticsearch54: elasticsearch>=5.4,<5.5
    elasticsearch63: elasticsearch>=6.3,<6.4
    elasticsearch64: elasticsearch>=6.4,<6.5
    # elasticsearch1 package
    elasticsearch1100: elasticsearch1>=1.10.0,<1.11.0
    # elasticsearch2 package
    elasticsearch250: elasticsearch2>=2.5.0,<2.6.0
    # elasticsearch5 package
    elasticsearch550: elasticsearch5>=5.5.0,<5.6.0
    # elasticsearch6 package
    elasticsearch640: elasticsearch6>=6.4.0,<6.5.0
    falcon10: falcon>=1.0,<1.1
    falcon11: falcon>=1.1,<1.2
    falcon12: falcon>=1.2,<1.3
    falcon13: falcon>=1.3,<1.4
    falcon14: falcon>=1.4,<1.5
    flask010: flask>=0.10,<0.11
    flask011: flask>=0.11,<0.12
    flask012: flask>=0.12,<0.13
    flask10: flask>=1.0,<1.1
    flaskcache012: flask_cache>=0.12,<0.13
    flaskcache013: flask_cache>=0.13,<0.14
    futures: futures
    futures30: futures>=3.0,<3.1
    futures31: futures>=3.1,<3.2
    futures32: futures>=3.2,<3.3
    gevent11: gevent>=1.1,<1.2
    gevent12: gevent>=1.2,<1.3
    gevent13: gevent>=1.3,<1.4
    gevent14: gevent>=1.4,<1.5
    grpc112: grpcio>=1.12.0,<1.13.0
    grpc113: grpcio>=1.13.0,<1.14.0
    grpc114: grpcio>=1.14.0,<1.15.0
    grpc115: grpcio>=1.15.0,<1.16.0
    grpc116: grpcio>=1.16.0,<1.17.0
    grpc117: grpcio>=1.17.0,<1.18.0
    grpc118: grpcio>=1.18.0,<1.19.0
    grpc119: grpcio>=1.19.0,<1.20.0
    grpc120: grpcio>=1.20.0,<1.21.0
    grpc121: grpcio>=1.21.0,<1.22.0
    grpc122: grpcio>=1.22.0,<1.23.0
    grpc112: googleapis-common-protos
    grpc113: googleapis-common-protos
    grpc114: googleapis-common-protos
    grpc115: googleapis-common-protos
    grpc116: googleapis-common-protos
    grpc117: googleapis-common-protos
    grpc118: googleapis-common-protos
    grpc119: googleapis-common-protos
    grpc120: googleapis-common-protos
    grpc121: googleapis-common-protos
    grpc122: googleapis-common-protos
    jinja27: jinja2>=2.7,<2.8
    jinja28: jinja2>=2.8,<2.9
    jinja29: jinja2>=2.9,<2.10
    jinja210: jinja2>=2.10,<2.11
    mako100: mako>=1.0.0,<1.1.0
    mako010: mako>=0.1.0,<1.0.0
    memcached: python-memcached
    molten070: molten>=0.7.0,<0.7.2
    molten072: molten>=0.7.2,<0.8.0
    mongoengine015: mongoengine>=0.15<0.16
    mongoengine016: mongoengine>=0.16<0.17
    mongoengine017: mongoengine>=0.17<0.18
    mongoengine018: mongoengine>=0.18<0.19
    mongoenginelatest: mongoengine>=0.18
    mysqlconnector: mysql-connector-python!=8.0.18
    mysqldb12: mysql-python>=1.2,<1.3
    mysqlclient13: mysqlclient>=1.3,<1.4
    pylibmc: pylibmc
    pylibmc140: pylibmc>=1.4.0,<1.5.0
    pylibmc150: pylibmc>=1.5.0,<1.6.0
    pymemcache130: pymemcache>=1.3.0,<1.4.0
    pymemcache140: pymemcache>=1.4.0,<1.5.0
    pymongo30: pymongo>=3.0,<3.1
    pymongo31: pymongo>=3.1,<3.2
    pymongo32: pymongo>=3.2,<3.3
    pymongo33: pymongo>=3.3,<3.4
    pymongo34: pymongo>=3.4,<3.5
    pymongo36: pymongo>=3.6,<3.7
    pymongo37: pymongo>=3.7,<3.8
    pymongo38: pymongo>=3.8,<3.9
    pymongo39: pymongo>=3.9,<3.10
    pymongolatest: pymongo>=3.9
    pymysql07: pymysql>=0.7,<0.8
    pymysql08: pymysql>=0.8,<0.9
    pymysql09: pymysql>=0.9,<0.10
    pyramid17: pyramid>=1.7,<1.8
    pyramid18: pyramid>=1.8,<1.9
    pyramid19: pyramid>=1.9,<1.10
    psycopg224: psycopg2>=2.4,<2.5
    psycopg225: psycopg2>=2.5,<2.6
    psycopg226: psycopg2>=2.6,<2.7
    psycopg227: psycopg2>=2.7,<2.8
    psycopg228: psycopg2>=2.8,<2.9
    redis26: redis>=2.6,<2.7
    redis27: redis>=2.7,<2.8
    redis28: redis>=2.8,<2.9
    redis29: redis>=2.9,<2.10
    redis210: redis>=2.10,<2.11
    redis300: redis>=3.0.0,<3.1.0
    redis320: redis>=3.2.0,<3.3.0
    rediscluster135: redis-py-cluster>=1.3.5,<1.3.6
    rediscluster136: redis-py-cluster>=1.3.6,<1.3.7
    kombu44:  kombu>=4.4,<4.5
    kombu43:  kombu>=4.3,<4.4
    kombu42:  kombu>=4.2,<4.3
    kombu41:  kombu>=4.1,<4.2
    kombu40:  kombu>=4.0,<4.1
    requests_contrib: requests-mock>=1.4
    requests200: requests>=2.0,<2.1
    requests208: requests>=2.8,<2.9
    requests209: requests>=2.9,<2.10
    requests210: requests>=2.10,<2.11
    requests211: requests>=2.11,<2.12
    requests212: requests>=2.12,<2.13
    requests213: requests>=2.13,<2.14
    requests218: requests>=2.18,<2.19
    requests219: requests>=2.19,<2.20
    sqlalchemy10: sqlalchemy>=1.0,<1.1
    sqlalchemy11: sqlalchemy>=1.1,<1.2
    sqlalchemy12: sqlalchemy>=1.2,<1.3
    tornado40: tornado>=4.0,<4.1
    tornado41: tornado>=4.1,<4.2
    tornado42: tornado>=4.2,<4.3
    tornado43: tornado>=4.3,<4.4
    tornado44: tornado>=4.4,<4.5
    tornado45: tornado>=4.5,<4.6
    tornado50: tornado>=5.0,<5.1
    tornado51: tornado>=5.1,<5.2
    tornado60: tornado>=6.0,<6.1
    vertica060: vertica-python>=0.6.0,<0.7.0
    vertica070: vertica-python>=0.7.0,<0.8.0
    webtest: WebTest

# pass along test env variables
passenv=TEST_*

commands =
# run only essential tests related to the tracing client
    tracer: pytest {posargs} --ignore="tests/contrib" --ignore="tests/test_integration.py" --ignore="tests/commands" --ignore="tests/opentracer" --ignore="tests/unit" --ignore="tests/internal" tests
# run only the `ddtrace.internal` tests
    internal: pytest {posargs} tests/internal
# run only the opentrace tests
    opentracer: pytest {posargs} tests/opentracer/test_tracer.py tests/opentracer/test_span.py tests/opentracer/test_span_context.py tests/opentracer/test_dd_compatibility.py tests/opentracer/test_utils.py
    opentracer_asyncio: pytest {posargs} tests/opentracer/test_tracer_asyncio.py
    opentracer_tornado-tornado{40,41,42,43,44}: pytest {posargs} tests/opentracer/test_tracer_tornado.py
    opentracer_gevent: pytest {posargs} tests/opentracer/test_tracer_gevent.py
# integration tests
    integration: pytest {posargs} tests/test_integration.py
# Contribs
    aiobotocore_contrib-{py34,py35,py36,py37}: pytest {posargs} tests/contrib/aiobotocore
    aiopg_contrib-{py34,py35,py36,py37}: pytest {posargs} tests/contrib/aiopg
    aiohttp_contrib: pytest {posargs} tests/contrib/aiohttp
    algoliasearch_contrib: pytest {posargs} tests/contrib/algoliasearch
    asyncio_contrib: pytest {posargs} tests/contrib/asyncio
    boto_contrib: pytest {posargs} tests/contrib/boto
    botocore_contrib: pytest {posargs} tests/contrib/botocore
    bottle_contrib: pytest {posargs} --ignore="tests/contrib/bottle/test_autopatch.py" tests/contrib/bottle/
    bottle_contrib_autopatch: python tests/ddtrace_run.py pytest {posargs} tests/contrib/bottle/test_autopatch.py
    cassandra_contrib: pytest {posargs} tests/contrib/cassandra
    celery_contrib: pytest {posargs} tests/contrib/celery
    consul_contrib: pytest {posargs} tests/contrib/consul
    dbapi_contrib: pytest {posargs} tests/contrib/dbapi
    django_contrib: pytest {posargs} tests/contrib/django
    django_contrib_autopatch: python tests/ddtrace_run.py pytest {posargs} tests/contrib/django
    django_drf_contrib: pytest {posargs} tests/contrib/djangorestframework
    dogpile_contrib: pytest {posargs} tests/contrib/dogpile_cache
    elasticsearch_contrib: pytest {posargs} tests/contrib/elasticsearch
    falcon_contrib: pytest {posargs} tests/contrib/falcon/test_middleware.py tests/contrib/falcon/test_distributed_tracing.py
    falcon_contrib_autopatch: python tests/ddtrace_run.py pytest {posargs} tests/contrib/falcon/test_autopatch.py
    flask_contrib: pytest {posargs} tests/contrib/flask
    flask_contrib_autopatch: python tests/ddtrace_run.py pytest {posargs} tests/contrib/flask_autopatch
    flask_cache_contrib: pytest {posargs} tests/contrib/flask_cache
    futures_contrib: pytest {posargs} tests/contrib/futures
    gevent_contrib: pytest {posargs} tests/contrib/gevent
    grpc_contrib: pytest {posargs} tests/contrib/grpc
    httplib_contrib: pytest {posargs} tests/contrib/httplib
    jinja2_contrib: pytest {posargs} tests/contrib/jinja2
    mako_contrib: pytest {posargs} tests/contrib/mako
    molten_contrib: pytest {posargs} tests/contrib/molten
    mongoengine_contrib: pytest {posargs} tests/contrib/mongoengine
    mysql_contrib: pytest {posargs} tests/contrib/mysql
    mysqldb_contrib: pytest {posargs} tests/contrib/mysqldb
    psycopg_contrib: pytest {posargs} tests/contrib/psycopg
    pylibmc_contrib: pytest {posargs} tests/contrib/pylibmc
    pymemcache_contrib: pytest {posargs} --ignore="tests/contrib/pymemcache/autopatch" tests/contrib/pymemcache/
    pymemcache_contrib_autopatch: python tests/ddtrace_run.py pytest {posargs} tests/contrib/pymemcache/autopatch/
    pymongo_contrib: pytest {posargs} tests/contrib/pymongo
    pymysql_contrib: pytest {posargs} tests/contrib/pymysql
    pyramid_contrib: pytest {posargs} tests/contrib/pyramid/test_pyramid.py
    pyramid_contrib_autopatch: python tests/ddtrace_run.py pytest {posargs} tests/contrib/pyramid/test_pyramid_autopatch.py
    redis_contrib: pytest {posargs} tests/contrib/redis
    rediscluster_contrib: pytest {posargs} tests/contrib/rediscluster
    requests_contrib: pytest {posargs} tests/contrib/requests
    requests_gevent_contrib: pytest {posargs} tests/contrib/requests_gevent
    kombu_contrib: pytest {posargs} tests/contrib/kombu
    sqlalchemy_contrib: pytest {posargs} tests/contrib/sqlalchemy
    sqlite3_contrib: pytest {posargs} tests/contrib/sqlite3
    tornado_contrib: pytest {posargs} tests/contrib/tornado
    vertica_contrib: pytest {posargs} tests/contrib/vertica/
# run subsets of the tests for particular library versions
    ddtracerun: pytest {posargs} tests/commands/test_runner.py
    test_utils: pytest {posargs} tests/contrib/test_utils.py
    test_logging: pytest {posargs} tests/contrib/logging/
# Unit tests: pytest based test suite that do not require any additional dependency.
    unit_tests: pytest {posargs} tests/unit
    benchmarks: pytest --benchmark-only {posargs} tests/benchmark.py

[testenv:wait]
commands=python tests/wait-for-services.py {posargs}
basepython=python
deps=
    cassandra-driver
    psycopg2
    mysql-connector-python!=8.0.18
    redis-py-cluster>=1.3.6,<1.4.0
    vertica-python>=0.6.0,<0.7.0
    kombu>=4.2.0,<4.3.0


# this is somewhat flaky (can fail and still be up) so try the tests anyway
ignore_outcome=true

[testenv:black]
deps=black
commands=black --check .
basepython=python3.7

[testenv:flake8]
deps=
  flake8>=3.7,<=3.8
  flake8-blind-except
  flake8-builtins
  flake8-docstrings
  flake8-logging-format
  flake8-rst-docstrings
  # needed for some features from flake8-rst-docstrings
  pygments
commands=flake8 .
basepython=python3.7

# do not use develop mode with celery as running multiple python versions within
# same job will cause problem for tests that use ddtrace-run
[celery_contrib]
usedevelop = False
[testenv:celery_contrib-py34-celery31-redis210]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py35-celery31-redis210]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py36-celery31-redis210]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py34-celery40-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py34-celery40-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py34-celery41-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py34-celery41-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py35-celery40-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py35-celery40-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py35-celery41-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py35-celery41-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py36-celery40-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py36-celery40-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py36-celery41-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py36-celery41-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py34-celery42-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py35-celery42-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py36-celery42-redis210-kombu43]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py34-celery43-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py35-celery43-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py36-celery43-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}
[testenv:celery_contrib-py37-celery43-redis320-kombu44]
usedevelop = {[celery_contrib]usedevelop}

[falcon_autopatch]
setenv =
    DATADOG_SERVICE_NAME=my-falcon
[testenv:falcon_contrib_autopatch-py34-falcon10]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py34-falcon11]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py34-falcon12]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py34-falcon13]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py34-falcon14]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py35-falcon10]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py35-falcon11]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py35-falcon12]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py35-falcon13]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py35-falcon14]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py36-falcon10]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py36-falcon11]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py36-falcon12]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py36-falcon13]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py36-falcon14]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py37-falcon10]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py37-falcon11]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py37-falcon12]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py37-falcon13]
setenv =
    {[falcon_autopatch]setenv}
[testenv:falcon_contrib_autopatch-py37-falcon14]
setenv =
    {[falcon_autopatch]setenv}


[pyramid_autopatch]
setenv =
    DATADOG_SERVICE_NAME = foobar
    DATADOG_PYRAMID_DISTRIBUTED_TRACING = True
[testenv:pyramid_contrib_autopatch-py34-pyramid17-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py34-pyramid18-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py34-pyramid19-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py35-pyramid17-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py35-pyramid18-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py35-pyramid19-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py36-pyramid17-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py36-pyramid18-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py36-pyramid19-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py37-pyramid17-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py37-pyramid18-webtest]
setenv =
    {[pyramid_autopatch]setenv}
[testenv:pyramid_contrib_autopatch-py37-pyramid19-webtest]
setenv =
    {[pyramid_autopatch]setenv}


[flask_autopatch]
setenv =
    DATADOG_SERVICE_NAME = test.flask.service
    DATADOG_PATCH_MODULES = jinja2:false
[testenv:flask_contrib_autopatch-py34-flask010-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py34-flask011-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py34-flask012-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py34-flask10-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py35-flask010-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py35-flask011-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py35-flask012-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py35-flask10-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py36-flask010-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py36-flask011-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py36-flask012-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py36-flask10-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py37-flask010-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py37-flask011-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py37-flask012-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py37-flask10-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py34-flask010-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py34-flask011-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py34-flask012-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py35-flask010-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py35-flask011-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py35-flask012-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py36-flask010-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py36-flask011-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py36-flask012-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py37-flask010-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py37-flask011-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}
[testenv:flask_contrib_autopatch-py37-flask012-flaskcache013-memcached-redis210-blinker]
setenv =
    {[flask_autopatch]setenv}

[bottle_autopatch]
setenv =
    DATADOG_SERVICE_NAME = bottle-app
[testenv:bottle_contrib_autopatch-py34-bottle11-webtest]
setenv =
    {[bottle_autopatch]setenv}
[testenv:bottle_contrib_autopatch-py35-bottle11-webtest]
setenv =
    {[bottle_autopatch]setenv}
[testenv:bottle_contrib_autopatch-py36-bottle11-webtest]
setenv =
    {[bottle_autopatch]setenv}
[testenv:bottle_contrib_autopatch-py37-bottle11-webtest]
setenv =
    {[bottle_autopatch]setenv}
[testenv:bottle_contrib_autopatch-py34-bottle12-webtest]
setenv =
    {[bottle_autopatch]setenv}
[testenv:bottle_contrib_autopatch-py35-bottle12-webtest]
setenv =
    {[bottle_autopatch]setenv}
[testenv:bottle_contrib_autopatch-py36-bottle12-webtest]
setenv =
    {[bottle_autopatch]setenv}
[testenv:bottle_contrib_autopatch-py37-bottle12-webtest]
setenv =
    {[bottle_autopatch]setenv}


# DEV: We use `conftest.py` as a local pytest plugin to configure hooks for collection
[pytest]
# Common directories to ignore
addopts = --ignore "tests/utils" --ignore "tests/base"
# DEV: The default is `test_*\.py` which will miss `test.py` files
python_files = test*\.py

[flake8]
max-line-length=120
exclude=
  .ddtox,.tox,
  .git,__pycache__,
  .eggs,*.egg,
  build,
  # We shouldn't lint our vendored dependencies
  ddtrace/vendor/
# Ignore:
# A003: XXX is a python builtin, consider renaming the class attribute
# G201 Logging: .exception(...) should be used instead of .error(..., exc_info=True)
# E231,W503: not respected by black
# We ignore most of the D errors because there are too many; the goal is to fix them eventually
ignore = W503,E231,A003,G201,D100,D101,D102,D103,D104,D105,D106,D107,D200,D202,D204,D205,D208,D210,D300,D400,D401,D403,D413
enable-extensions=G
rst-roles = class,meth,obj,ref
rst-directives = py:data
