[tox] envlist = flake8, black, mypy test-py{26,27,34,35,36,37,38,39,py2,py3} coverage_report docs packaging skip_missing_interpreters = {tty:True:False} [default] basepython = python3.9 deps = idna==2.9 # rq.filter: <3 setenv = PY_MODULE=hyperlink PYTHONPYCACHEPREFIX={envtmpdir}/pycache ## # Default environment: unit tests ## [testenv] description = run tests basepython = py: python py26: python2.6 py27: python2.7 py34: python3.4 py35: python3.5 py36: python3.6 py37: python3.7 py38: python3.8 py39: python3.9 py310: python3.10 pypy2: pypy pypy3: pypy3 deps = {[default]deps} # In Python 2, we need to pull in typing, mock py{26,27,py2}: typing==3.7.4.3 py{26,27,py2}: mock==3.0.5 # rq.filter: <4 # For pytest py{26,27,34,py2}: pytest==4.6.11 # rq.filter: <5 py{35,36,37,38,39,py3}: pytest==5.2.4 # For code coverage {[testenv:coverage_report]deps} py{26,27,34,py2}: pytest-cov==2.8.1 # rq.filter: <2.9 py{35,36,37,38,39,py3}: pytest-cov==2.10.1 # For hypothesis. Note Python 3.4 isn't supported by hypothesis. py{26,27,py2}: hypothesis==4.43.9 # rq.filter: <4.44 py{35,36,37,38,39,py3}: hypothesis==5.8.6 setenv = {[default]setenv} COVERAGE_FILE={toxworkdir}/coverage.{envname} HYPOTHESIS_STORAGE_DIRECTORY={toxworkdir}/hypothesis passenv = CI commands = pytest --cov={env:PY_MODULE} --cov-report=term-missing:skip-covered --doctest-modules {posargs:src/{env:PY_MODULE}} coverage_xml: coverage xml ## # Black code formatting ## [testenv:black] description = run Black (linter) basepython = {[default]basepython} skip_install = True deps = black==20.8b1 setenv = BLACK_LINT_ARGS=--check commands = black {env:BLACK_LINT_ARGS:} {posargs:setup.py src} [testenv:black-reformat] description = {[testenv:black]description} and reformat basepython = {[testenv:black]basepython} skip_install = {[testenv:black]skip_install} deps = {[testenv:black]deps} commands = {[testenv:black]commands} ## # Flake8 linting ## [testenv:flake8] description = run Flake8 (linter) basepython = {[default]basepython} skip_install = True deps = flake8-bugbear==20.11.1 flake8==3.8.4 mccabe==0.6.1 pep8-naming==0.11.1 pycodestyle==2.6.0 pydocstyle==5.1.1 pyflakes==2.2.0 commands = flake8 {posargs:setup.py src/{env:PY_MODULE}} [flake8] # !!! BRING THE PAIN !!! select = A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z show-source = True doctests = True max-line-length = 80 # Codes: http://flake8.pycqa.org/en/latest/user/error-codes.html ignore = # syntax error in type comment F723, # function name should be lowercase N802, # argument name should be lowercase N803, # variable in function should be lowercase N806, # variable in class scope should not be mixedCase N815, # variable in global scope should not be mixedCase N816, # line break before binary operator W503, # End of list (allows last item to end with trailing ',') EOL # flake8-import-order: local module name space application-import-names = deploy ## # Mypy static type checking ## [testenv:mypy] description = run Mypy (static type checker) basepython = {[default]basepython} deps = mypy==0.790 {[default]deps} commands = mypy \ --config-file="{toxinidir}/tox.ini" \ --cache-dir="{toxworkdir}/mypy_cache" \ {tty:--pretty:} \ {posargs:src} [mypy] # Global settings check_untyped_defs = True disallow_any_generics = True disallow_incomplete_defs = True disallow_untyped_defs = True no_implicit_optional = True show_column_numbers = True show_error_codes = True strict_optional = True warn_no_return = True warn_redundant_casts = True warn_return_any = True warn_unreachable = True warn_unused_ignores = True # DrawCallable is generic [mypy-hyperlink.hypothesis] disallow_any_generics = False [mypy-hyperlink.test.test_hypothesis] disallow_any_generics = False # Don't complain about dependencies known to lack type hints [mypy-hypothesis] ignore_missing_imports = True [mypy-hypothesis.*] ignore_missing_imports = True [mypy-idna] ignore_missing_imports = True ## # Coverage report ## [testenv:coverage_report] description = generate coverage report depends = test-py{26,27,34,35,36,37,38,39,py2,py3} basepython = {[default]basepython} skip_install = True deps = # coverage 5.0 drops Python 3.4 support coverage==4.5.4 # rq.filter: <5 setenv = {[default]setenv} COVERAGE_FILE={toxworkdir}/coverage commands = coverage combine - coverage report - coverage html ## # Codecov ## [testenv:codecov] description = upload coverage to Codecov depends = {[coverage_report]depends} basepython = python skip_install = True deps = {[testenv:coverage_report]deps} codecov==2.1.11 passenv = # See https://github.com/codecov/codecov-python/blob/master/README.md#using-tox # And CI-specific docs: # https://help.github.com/en/articles/virtual-environments-for-github-actions#default-environment-variables # https://docs.travis-ci.com/user/environment-variables#default-environment-variables # https://www.appveyor.com/docs/environment-variables/ TOXENV CODECOV_* CI GITHUB_* TRAVIS TRAVIS_* APPVEYOR APPVEYOR_* setenv = {[testenv:coverage_report]setenv} COVERAGE_XML={envlogdir}/coverage.xml commands = # Note documentation for CI variables in passenv above coverage combine coverage xml -o "{env:COVERAGE_XML}" codecov --file="{env:COVERAGE_XML}" --env \ GITHUB_REF GITHUB_COMMIT GITHUB_USER GITHUB_WORKFLOW \ TRAVIS_BRANCH TRAVIS_BUILD_WEB_URL \ TRAVIS_COMMIT TRAVIS_COMMIT_MESSAGE \ APPVEYOR_REPO_BRANCH APPVEYOR_REPO_COMMIT \ APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL \ APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED ## # Documentation ## [testenv:docs] description = build documentation basepython = {[default]basepython} deps = Sphinx==3.4.3 sphinx-rtd-theme==0.5.1 commands = sphinx-build \ -b html -d "{envtmpdir}/doctrees" \ "{toxinidir}/docs" \ "{toxinidir}/htmldocs" [testenv:docs-auto] description = build documentation and rebuild automatically basepython = {[default]basepython} deps = {[testenv:docs]deps} sphinx-autobuild==2020.9.1 commands = sphinx-autobuild \ -b html -d "{envtmpdir}/doctrees" \ --host=localhost \ "{toxinidir}/docs" \ "{toxinidir}/htmldocs" ## # Packaging ## [testenv:packaging] description = check for potential packaging problems basepython = {[default]basepython} skip_install = True deps = check-manifest==0.46 readme-renderer==28.0 twine==3.3.0 commands = check-manifest pip wheel --wheel-dir "{envtmpdir}/dist" --no-deps {toxinidir} twine check "{envtmpdir}/dist/"* ## # Print dependencies ## [testenv:dependencies] description = print dependencies basepython = {[default]basepython} recreate = true deps = commands = pip freeze --exclude={env:PY_MODULE}