[tox]
envlist = py3, xenial-dev, flake8, pylint, black, isort
recreate = True

[testenv]
commands = {envpython} -m pytest {posargs:tests/unittests}
setenv =
    LC_ALL = en_US.utf-8
passenv=
    PYTEST_ADDOPTS

[testenv:flake8]
basepython = python3
deps =
    flake8==3.9.2
commands = {envpython} -m flake8 {posargs:cloudinit/ tests/ tools/ setup.py}

# https://github.com/gabrielfalcao/HTTPretty/issues/223
setenv =
    LC_ALL = en_US.utf-8

[testenv:pylint]
basepython = python3
deps =
    # requirements
    pylint==2.11.1
    # test-requirements because unit tests are now present in cloudinit tree
    -r{toxinidir}/test-requirements.txt
    -r{toxinidir}/integration-requirements.txt
commands = {envpython} -m pylint {posargs:cloudinit tests tools}

[testenv:black]
basepython = python3
deps =
    # requirements
    black==21.12b0
commands = {envpython} -m black . --check

[testenv:isort]
basepython = python3
deps =
    isort==5.10.1
commands = {envpython} -m isort . --check-only

[testenv:format]
basepython = python3
deps =
    black==21.12b0
    isort==5.10.1
commands =
    {envpython} -m isort .
    {envpython} -m black .

[testenv:py3]
basepython = python3
deps =
    -r{toxinidir}/test-requirements.txt
commands = {envpython} -m pytest \
            --durations 10 \
            {posargs:--cov=cloudinit --cov-branch \
            tests/unittests}

[testenv:py27]
basepython = python2.7
deps = -r{toxinidir}/test-requirements.txt

[flake8]
# E203: whitespace before ':', doesn't adhere to pep8 or black formatting
# W503: line break before binary operator
ignore=E203,W503
exclude = .venv,.tox,dist,doc,*egg,.git,build,tools
per-file-ignores =
    cloudinit/cmd/main.py:E402

[testenv:doc]
basepython = python3
deps =
    -r{toxinidir}/doc-requirements.txt
commands =
    {envpython} -m sphinx {posargs:doc/rtd doc/rtd_html}
    doc8 doc/rtd

[xenial-shared-deps]
# The version of pytest in xenial doesn't work with Python 3.8, so we define
# two xenial environments: [testenv:xenial] runs the tests with exactly the
# version of pytest present in xenial, and is used in CI.  [testenv:xenial-dev]
# runs the tests with the lowest version of pytest that works with Python 3.8,
# 3.0.7, but keeps the other dependencies at xenial's level.
#
# (This section is not a testenv, it is used to maintain a single definition of
# the dependencies shared between the two xenial testenvs.)
deps =
    # requirements
    jinja2==2.8
    pyyaml==3.11
    oauthlib==1.0.3
    pyserial==3.0.1
    configobj==5.0.6
    requests==2.9.1
    jsonschema
    # test-requirements
    pytest-catchlog==1.2.1

[testenv:xenial]
# When updating this commands definition, also update the definition in
# [testenv:xenial-dev].  See the comment there for details.
commands =
  python ./tools/pipremove jsonschema
  python -m pytest {posargs:tests/unittests}
basepython = python3
deps =
    # Refer to the comment in [xenial-shared-deps] for details
    {[xenial-shared-deps]deps}
    httpretty==0.8.6
    jsonpatch==1.10
    pytest==2.8.7

[testenv:xenial-dev]
# This should be:
#   commands = {[testenv:xenial]commands}
# but the version of pytest in xenial has a bug
# (https://github.com/tox-dev/tox/issues/208) which means that the {posargs}
# substitution variable is misparsed and causes a traceback.  Ensure that any
# changes here are reflected in [testenv:xenial].
commands =
  python ./tools/pipremove jsonschema
  python -m pytest {posargs:tests/unittests}
basepython = {[testenv:xenial]basepython}
deps =
    # Refer to the comment in [xenial-shared-deps] for details
    {[xenial-shared-deps]deps}
    # httpretty in xenial is 0.8.6, not 0.9.5.  The oldest version to work with
    # Python 3.7+ is 0.9.5, because it is the first to include this commit:
    # https://github.com/gabrielfalcao/HTTPretty/commit/5776d97da3992b9071db5e21faf175f6e8729060
    httpretty==0.9.5
    # jsonpatch in xenial is 1.10, not 1.19 (#839779). The oldest version
    # to work with python3.6 is 1.16 as found in Artful.  To keep default
    # invocation of 'tox' happy, accept the difference in version here.
    jsonpatch==1.16
    pytest==3.0.7

[testenv:tip-flake8]
commands = {envpython} -m flake8 {posargs:cloudinit/ tests/ tools/ setup.py}
deps = flake8

[testenv:tip-pylint]
commands = {envpython} -m pylint {posargs:cloudinit tests tools}
deps =
    # requirements
    pylint
    # test-requirements
    -r{toxinidir}/test-requirements.txt
    -r{toxinidir}/integration-requirements.txt

# Until Xenial tox support is dropped or bumps to tox:2.3.2, reflect changes to
# deps into testenv:integration-tests-ci: commands, passenv and deps.
# This is due to (https://github.com/tox-dev/tox/issues/208) which means that
# the {posargs} handling and substitutions won't do what we want until tox 2.3.2
# Once Xenial is dropped, integration-tests-ci can use proper substitution
# commands = {[testenv:integration-tests]commands}
[testenv:integration-tests]
basepython = python3
commands = {envpython} -m pytest --log-cli-level=INFO {posargs:tests/integration_tests}
passenv = CLOUD_INIT_* SSH_AUTH_SOCK OS_*
deps =
    -r{toxinidir}/integration-requirements.txt

[testenv:integration-tests-ci]
commands = {envpython} -m pytest --log-cli-level=INFO {posargs:tests/integration_tests}
passenv = CLOUD_INIT_* SSH_AUTH_SOCK OS_* TRAVIS
deps =
    -r{toxinidir}/integration-requirements.txt
setenv =
    PYTEST_ADDOPTS="-m ci and not adhoc"

[testenv:integration-tests-jenkins]
commands = {envpython} -m pytest --log-cli-level=INFO {posargs:tests/integration_tests}
passenv = *_proxy CLOUD_INIT_* SSH_AUTH_SOCK OS_* GOOGLE_* GCP_*
deps =
    -r{toxinidir}/integration-requirements.txt
setenv =
    PYTEST_ADDOPTS="-m not adhoc"

[pytest]
# TODO: s/--strict/--strict-markers/ once xenial support is dropped
testpaths = tests/unittests
addopts = --strict
log_format = %(asctime)s %(levelname)-9s %(name)s:%(filename)s:%(lineno)d %(message)s
log_date_format = %Y-%m-%d %H:%M:%S
markers =
    allow_subp_for: allow subp usage for the given commands (disable_subp_usage)
    allow_all_subp: allow all subp usage (disable_subp_usage)
    ci: run this integration test as part of CI test runs
    ds_sys_cfg: a sys_cfg dict to be used by datasource fixtures
    ec2: test will only run on EC2 platform
    gce: test will only run on GCE platform
    azure: test will only run on Azure platform
    oci: test will only run on OCI platform
    openstack: test will only run on openstack platform
    lxd_config_dict: set the config_dict passed on LXD instance creation
    lxd_container: test will only run in LXD container
    lxd_setup: specify callable to be called between init and start
    lxd_use_exec: `execute` will use `lxc exec` instead of SSH
    lxd_vm: test will only run in LXD VM
    not_xenial: test cannot run on the xenial release
    not_bionic: test cannot run on the bionic release
    no_container: test cannot run in a container
    user_data: the user data to be passed to the test instance
    instance_name: the name to be used for the test instance
    sru_2020_11: test is part of the 2020/11 SRU verification
    sru_2021_01: test is part of the 2021/01 SRU verification
    sru_next: test is part of the next SRU verification
    ubuntu: this test should run on Ubuntu
    unstable: skip this test because it is flakey
    adhoc: only run on adhoc basis, not in any CI environment (travis or jenkins)