Skip to content

Commit

Permalink
show config now shows all config, filter-able, contains host tox python
Browse files Browse the repository at this point in the history
and package versions
  • Loading branch information
gaborbernat committed May 15, 2019
1 parent bfd22c6 commit d011311
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 55 deletions.
9 changes: 9 additions & 0 deletions docs/changelog/1298.feature.rst
@@ -0,0 +1,9 @@
``--showconfig`` overhaul:

- now fully generated via the config parser, so anyone can load it by using the built-in python config parser
- the ``tox`` section contains all configuration data from config
- the ``tox`` section contains a ``host_python`` key detailing the path of the host python
- the ``tox:version`` section contains the versions of all packages tox depends on with their version
- passing ``-l`` now allows only listing default target envs
- allows showing config for a given set of tox environments only via the ``-e`` cli flag or the ``TOXENV`` environment
variable, in this case the ``tox`` and ``tox:version`` section is only shown if at least one verbosity flag is passed
21 changes: 14 additions & 7 deletions src/tox/config/__init__.py
Expand Up @@ -1077,7 +1077,8 @@ def line_of_default_to_zero(section, name=None):
self.handle_provision(config, reader)

self.parse_build_isolation(config, reader)
config.envlist, all_envs, config.envlist_default = self._getenvdata(reader, config)
res = self._getenvdata(reader, config)
config.envlist, all_envs, config.envlist_default, config.envlist_explicit = res

# factors used in config or predefined
known_factors = self._list_section_factors("testenv")
Expand Down Expand Up @@ -1268,18 +1269,19 @@ def _getenvdata(self, reader, config):
from_config = reader.getstring("envlist", replace=False)

env_list = []
envlist_explicit = False
if (from_option and "ALL" in from_option) or (
not from_option and from_environ and "ALL" in from_environ.split(",")
):
all_envs = self._getallenvs(reader)
else:
candidates = (
os.environ.get(PARALLEL_ENV_VAR_KEY),
from_option,
from_environ,
from_config,
(os.environ.get(PARALLEL_ENV_VAR_KEY), True),
(from_option, True),
(from_environ, True),
(from_config, False),
)
env_str = next((i for i in candidates if i), [])
env_str, envlist_explicit = next(((i, e) for i, e in candidates if i), ([], False))
env_list = _split_env(env_str)
all_envs = self._getallenvs(reader, env_list)

Expand All @@ -1293,7 +1295,7 @@ def _getenvdata(self, reader, config):
if config.isolated_build is True and package_env in env_list:
msg = "isolated_build_env {} cannot be part of envlist".format(package_env)
raise tox.exception.ConfigError(msg)
return env_list, all_envs, _split_env(from_config)
return env_list, all_envs, _split_env(from_config), envlist_explicit


def _split_env(env):
Expand Down Expand Up @@ -1368,6 +1370,11 @@ def __init__(self, name, url=None):
self.name = name
self.url = url

def __str__(self):
return "IndexServerConfig(name={}, url={})".format(self.name, self.url)

__repr__ = __str__


is_section_substitution = re.compile(r"{\[[^{}\s]+\]\S+?}").match
"""Check value matches substitution form of referencing value from other section.
Expand Down
95 changes: 70 additions & 25 deletions src/tox/session/commands/show_config.py
@@ -1,31 +1,76 @@
import subprocess
import sys
from collections import OrderedDict

from tox import reporter as report
from tox.version import __version__
from six import StringIO

from tox import reporter

try:
import ConfigParser
except ImportError:
# noinspection PyPep8Naming
import configparser as ConfigParser

DO_NOT_SHOW_CONFIG_ATTRIBUTES = (
"interpreters",
"envconfigs",
"envlist",
"pluginmanager",
"envlist_explicit",
)


def show_config(config):
info_versions()
report.keyvalue("config-file:", config.option.configfile)
report.keyvalue("toxinipath: ", config.toxinipath)
report.keyvalue("toxinidir: ", config.toxinidir)
report.keyvalue("toxworkdir: ", config.toxworkdir)
report.keyvalue("setupdir: ", config.setupdir)
report.keyvalue("distshare: ", config.distshare)
report.keyvalue("skipsdist: ", config.skipsdist)
report.line("")
for envconfig in config.envconfigs.values():
report.line("[testenv:{}]".format(envconfig.envname), bold=True)
for attr in config._parser._testenv_attr:
report.line(" {:<15} = {}".format(attr.name, getattr(envconfig, attr.name)))


def info_versions():
versions = ["tox-{}".format(__version__)]
proc = subprocess.Popen(
(sys.executable, "-m", "virtualenv", "--version"), stdout=subprocess.PIPE
parser = ConfigParser.ConfigParser()

if not config.envlist_explicit or reporter.verbosity() >= reporter.Verbosity.INFO:
tox_info(config, parser)
version_info(parser)
tox_envs_info(config, parser)

content = StringIO()
parser.write(content)
value = content.getvalue().rstrip()
reporter.verbosity0(value)


def tox_envs_info(config, parser):
if config.envlist_explicit:
env_list = config.envlist
elif config.option.listenvs:
env_list = config.envlist_default
else:
env_list = list(config.envconfigs.keys())
for name in env_list:
env_config = config.envconfigs[name]
values = OrderedDict(
(attr.name, str(getattr(env_config, attr.name)))
for attr in config._parser._testenv_attr
)
parser["testenv:{}".format(name)] = values


def tox_info(config, parser):
info = OrderedDict(
(i, str(getattr(config, i)))
for i in sorted(dir(config))
if not i.startswith("_") and i not in DO_NOT_SHOW_CONFIG_ATTRIBUTES
)
out, _ = proc.communicate()
versions.append("virtualenv-{}".format(out.decode("UTF-8").strip()))
report.keyvalue("tool-versions:", " ".join(versions))
info["host_python"] = sys.executable
parser["tox"] = info


def version_info(parser):
import pkg_resources

versions = OrderedDict()
visited = set()
to_visit = {"tox"}
while to_visit:
current = to_visit.pop()
visited.add(current)
current_dist = pkg_resources.get_distribution(current)
to_visit.update(i.name for i in current_dist.requires() if i.name not in visited)
versions[current] = current_dist.version

parser["tox:versions"] = versions
22 changes: 0 additions & 22 deletions tests/unit/config/test_config.py
Expand Up @@ -2757,28 +2757,6 @@ def test_override_workdir(self, cmd, initproj):
assert py.path.local(gooddir).check()
assert not py.path.local(baddir).check()

def test_showconfig_with_force_dep_version(self, cmd, initproj):
initproj(
"force_dep_version",
filedefs={
"tox.ini": """
[tox]
[testenv]
deps=
dep1==2.3
dep2
"""
},
)
result = cmd("--showconfig")
result.assert_success(is_run_test_env=False)
assert any(re.match(r".*deps.*dep1==2.3, dep2.*", l) for l in result.outlines)
# override dep1 specific version, and force version for dep2
result = cmd("--showconfig", "--force-dep=dep1", "--force-dep=dep2==5.0")
result.assert_success(is_run_test_env=False)
assert any(re.match(r".*deps.*dep1, dep2==5.0.*", l) for l in result.outlines)


@pytest.mark.parametrize(
"cli_args,run_envlist",
Expand Down
90 changes: 90 additions & 0 deletions tests/unit/session/test_show_config.py
@@ -0,0 +1,90 @@
import re

import pytest

try:
import ConfigParser
except ImportError:
# noinspection PyPep8Naming
import configparser as ConfigParser


def test_showconfig_with_force_dep_version(cmd, initproj):
initproj(
"force_dep_version",
filedefs={
"tox.ini": """
[tox]
[testenv]
deps=
dep1==2.3
dep2
"""
},
)
result = cmd("--showconfig")
result.assert_success(is_run_test_env=False)
assert any(re.match(r".*deps.*dep1==2.3, dep2.*", l) for l in result.outlines)
# override dep1 specific version, and force version for dep2
result = cmd("--showconfig", "--force-dep=dep1", "--force-dep=dep2==5.0")
result.assert_success(is_run_test_env=False)
assert any(re.match(r".*deps.*dep1, dep2==5.0.*", l) for l in result.outlines)


@pytest.fixture()
def setup_mixed_conf(initproj):
initproj(
"force_dep_version",
filedefs={
"tox.ini": """
[tox]
envlist = py37,py27,pypi,docs
[testenv:notincluded]
changedir = whatever
[testenv:docs]
changedir = docs
"""
},
)


@pytest.mark.parametrize(
"args, expected",
[
(
["--showconfig"],
[
"tox",
"tox:versions",
"testenv:py37",
"testenv:py27",
"testenv:pypi",
"testenv:docs",
"testenv:notincluded",
],
),
(
["--showconfig", "-l"],
[
"tox",
"tox:versions",
"testenv:py37",
"testenv:py27",
"testenv:pypi",
"testenv:docs",
],
),
(["--showconfig", "-e", "py37,py36"], ["testenv:py37", "testenv:py36"]),
],
ids=["all", "default_only", "-e"],
)
def test_showconfig(cmd, setup_mixed_conf, args, expected):
result = cmd(*args)
result.assert_success(is_run_test_env=False)
parser = ConfigParser.ConfigParser()
parser.read_string(result.out)
found_sections = parser.sections()
assert found_sections == expected
2 changes: 1 addition & 1 deletion tox.ini
Expand Up @@ -20,7 +20,7 @@ setenv = PIP_DISABLE_VERSION_CHECK = 1
COVERAGE_FILE = {env:COVERAGE_FILE:{toxworkdir}/.coverage.{envname}}
VIRTUALENV_NO_DOWNLOAD = 1
passenv = http_proxy https_proxy no_proxy SSL_CERT_FILE PYTEST_*
deps = pip == 19.0.3
deps = pip == 19.1.1
extras = testing
commands = pytest \
--cov "{envsitepackagesdir}/tox" \
Expand Down

0 comments on commit d011311

Please sign in to comment.