summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernát Gábor <bgabor8@bloomberg.net>2020-10-19 09:29:51 +0100
committerBernát Gábor <bgabor8@bloomberg.net>2020-10-19 09:29:51 +0100
commit61869b12edd970998e235c86fcf72b189445c6eb (patch)
tree2b9bc817bfc28fa6d11ec2bba82dedd065e4aeed
parent860983a992f5b6a613c111b5e1cbfd2a7213bea8 (diff)
downloadtox-git-61869b12edd970998e235c86fcf72b189445c6eb.tar.gz
Improve documentation
Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
-rw-r--r--.pre-commit-config.yaml135
-rw-r--r--pyproject.toml35
-rw-r--r--setup.cfg5
-rw-r--r--setup.py10
-rw-r--r--src/tox/__init__.py6
-rw-r--r--src/tox/config/cli/env_var.py6
-rw-r--r--src/tox/config/cli/for_docs.py7
-rw-r--r--src/tox/config/cli/ini.py18
-rw-r--r--src/tox/config/cli/parse.py23
-rw-r--r--src/tox/config/cli/parser.py53
-rw-r--r--src/tox/config/core.py1
-rw-r--r--src/tox/config/sets.py22
-rw-r--r--src/tox/config/source/api.py14
-rw-r--r--src/tox/config/source/ini/__init__.py23
-rw-r--r--src/tox/config/source/ini/convert.py1
-rw-r--r--src/tox/config/source/ini/factor.py10
-rw-r--r--src/tox/config/source/ini/replace.py10
-rw-r--r--src/tox/config/source/toml.py0
-rw-r--r--src/tox/execute/__init__.py10
-rw-r--r--src/tox/execute/api.py104
-rw-r--r--src/tox/execute/local_sub_process/__init__.py11
-rw-r--r--src/tox/execute/request.py5
-rw-r--r--src/tox/execute/stream.py14
-rw-r--r--src/tox/helper/__init__.py3
-rw-r--r--src/tox/helper/build_isolated.py6
-rw-r--r--src/tox/helper/build_requires.py8
-rw-r--r--src/tox/helper/wheel_meta.py7
-rw-r--r--src/tox/log/__init__.py8
-rw-r--r--src/tox/log/command.py3
-rw-r--r--src/tox/log/env.py2
-rw-r--r--src/tox/log/result.py2
-rw-r--r--src/tox/plugin/__init__.py5
-rw-r--r--src/tox/plugin/impl.py2
-rw-r--r--src/tox/plugin/manager.py6
-rw-r--r--src/tox/plugin/spec.py11
-rw-r--r--src/tox/plugin/util.py1
-rw-r--r--src/tox/provision/__init__.py8
-rw-r--r--src/tox/pytest.py18
-rw-r--r--src/tox/report.py1
-rw-r--r--src/tox/run.py39
-rw-r--r--src/tox/session/__init__.py3
-rw-r--r--src/tox/session/cmd/list_env.py3
-rw-r--r--src/tox/session/cmd/run/__init__.py3
-rw-r--r--src/tox/session/cmd/run/common.py1
-rw-r--r--src/tox/session/cmd/run/parallel.py8
-rw-r--r--src/tox/session/cmd/run/sequential.py8
-rw-r--r--src/tox/session/cmd/run/single.py3
-rw-r--r--src/tox/session/cmd/show_config.py3
-rw-r--r--src/tox/session/cmd/version_flag.py3
-rw-r--r--src/tox/session/common.py3
-rw-r--r--src/tox/session/state.py4
-rw-r--r--src/tox/tox_env/__init__.py3
-rw-r--r--src/tox/tox_env/api.py19
-rw-r--r--src/tox/tox_env/builder.py13
-rw-r--r--src/tox/tox_env/errors.py9
-rw-r--r--src/tox/tox_env/info.py (renamed from src/tox/tox_env/cache.py)8
-rw-r--r--src/tox/tox_env/package.py3
-rw-r--r--src/tox/tox_env/python/api.py6
-rw-r--r--src/tox/tox_env/python/package.py3
-rw-r--r--src/tox/tox_env/python/runner.py3
-rw-r--r--src/tox/tox_env/python/virtual_env/api.py6
-rw-r--r--src/tox/tox_env/python/virtual_env/package/api.py14
-rw-r--r--src/tox/tox_env/python/virtual_env/package/artifact/api.py2
-rw-r--r--src/tox/tox_env/python/virtual_env/runner.py7
-rw-r--r--src/tox/tox_env/register.py8
-rw-r--r--src/tox/tox_env/runner.py2
-rw-r--r--src/tox/util/__init__.py16
-rw-r--r--src/tox/util/cpu.py1
-rw-r--r--src/tox/util/graph.py1
-rw-r--r--src/tox/util/lock.py38
-rw-r--r--src/tox/util/path.py9
-rw-r--r--tests/unit/tox_env/python/virtual_env/setuptools/package/test_wheel_build.py4
-rw-r--r--tox.ini121
73 files changed, 541 insertions, 450 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7c2d1053..2b11f69e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,77 +1,60 @@
-default_language_version:
- python: python3
repos:
-- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v3.2.0
- hooks:
- - id: check-ast
- - id: check-builtin-literals
- - id: check-docstring-first
- - id: check-merge-conflict
- - id: check-yaml
- - id: check-toml
- - id: debug-statements
- - id: end-of-file-fixer
- - id: trailing-whitespace
-- repo: https://github.com/asottile/add-trailing-comma
- rev: v2.0.1
- hooks:
- - id: add-trailing-comma
-- repo: https://github.com/asottile/pyupgrade
- rev: v2.7.2
- hooks:
- - id: pyupgrade
-- repo: https://github.com/asottile/seed-isort-config
- rev: v2.2.0
- hooks:
- - id: seed-isort-config
- args:
- - --application-directories
- - .:src
-- repo: https://github.com/pre-commit/mirrors-isort
- rev: v5.6.4
- hooks:
- - id: isort
-- repo: https://github.com/ambv/black
- rev: 20.8b1
- hooks:
- - id: black
- args:
- - --safe
- language_version: python3.8
-- repo: https://github.com/asottile/blacken-docs
- rev: v1.8.0
- hooks:
- - id: blacken-docs
- additional_dependencies:
- - black==19.10b0
- language_version: python3.8
-- repo: https://github.com/pre-commit/pygrep-hooks
- rev: v1.6.0
- hooks:
- - id: rst-backticks
-- repo: https://github.com/asottile/setup-cfg-fmt
- rev: v1.15.0
- hooks:
- - id: setup-cfg-fmt
- args:
- - --min-py3-version
- - '3.4'
-- repo: https://gitlab.com/pycqa/flake8
- rev: 3.8.4
- hooks:
- - id: flake8
- additional_dependencies:
- - flake8-bugbear == 20.1.2
- language_version: python3.8
-- repo: local
- hooks:
- - id: changelogs-rst
- name: changelog filenames
- language: fail
- entry: >-
- changelog files must be named
- ####.(bugfix|feature|deprecation|breaking|doc|misc).rst
- exclude: >-
- ^docs/changelog/(\d+\.(bugfix|feature|deprecation|breaking|doc|misc).rst|README.rst|template.jinja2)
- files: ^docs/changelog/
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v3.2.0
+ hooks:
+ - id: check-ast
+ - id: check-builtin-literals
+ - id: check-docstring-first
+ - id: check-merge-conflict
+ - id: check-yaml
+ - id: check-toml
+ - id: debug-statements
+ - id: end-of-file-fixer
+ - id: trailing-whitespace
+ - repo: https://github.com/asottile/pyupgrade
+ rev: v2.7.2
+ hooks:
+ - id: pyupgrade
+ - repo: https://github.com/PyCQA/isort
+ rev: 5.6.4
+ hooks:
+ - id: isort
+ - repo: https://github.com/psf/black
+ rev: 20.8b1
+ hooks:
+ - id: black
+ args:
+ - --safe
+ - repo: https://github.com/PyCQA/flake8
+ rev: 3.8.4
+ hooks:
+ - id: flake8
+ additional_dependencies:
+ - flake8-bugbear == 20.1.2
+ language_version: python3.9
+ - repo: https://github.com/asottile/setup-cfg-fmt
+ rev: v1.15.0
+ hooks:
+ - id: setup-cfg-fmt
+ args: [ '--min-py3-version', '3.6' ]
+ - repo: https://github.com/asottile/blacken-docs
+ rev: v1.8.0
+ hooks:
+ - id: blacken-docs
+ additional_dependencies:
+ - black==19.10b0
+ - repo: https://github.com/pre-commit/pygrep-hooks
+ rev: v1.6.0
+ hooks:
+ - id: rst-backticks
+ - repo: local
+ hooks:
+ - id: changelogs-rst
+ name: changelog filenames
+ language: fail
+ entry: >-
+ changelog files must be named
+ ####.(bugfix|feature|deprecation|breaking|doc|misc).rst
+ exclude: >-
+ ^docs/changelog/(\d+\.(bugfix|feature|deprecation|breaking|doc|misc).rst|README.rst|template.jinja2)
+ files: ^docs/changelog/
diff --git a/pyproject.toml b/pyproject.toml
index 566f0bc7..7d394bed 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,20 +1,27 @@
[build-system]
-requires = [
- "setuptools >= 45.0.0",
- "wheel >= 0.30.0",
- "setuptools_scm >= 3, <4",
-]
-build-backend = 'setuptools.build_meta'
+requires = ["setuptools >= 44", "wheel >= 0.30", "setuptools_scm[toml]>=3.4"]
+build-backend = "setuptools.build_meta"
[tool.black]
line-length = 120
+[tool.isort]
+profile = "black"
+known_first_party = ["tox_ini_fmt"]
+
+[tool.setuptools_scm]
+write_to = "src/tox/version.py"
+write_to_template = """
+\"\"\" Version information \"\"\"
+__version__ = "{version}"
+"""
+
[tool.towncrier]
- package = "tox"
- package_dir = "" # we purposfully do not set this as src, forcing import from site-package that has version.py
- filename = "docs/changelog.rst"
- directory = "docs/changelog"
- title_format = false
- issue_format = "`#{issue} <https://github.com/tox-dev/tox/issues/{issue}>`_"
- template = "docs/changelog/template.jinja2"
- # possible types, all default: feature, bugfix, doc, removal, misc
+package = "tox"
+package_dir = "" # we purposfully do not set this as src, forcing import from site-package that has version.py
+filename = "docs/changelog.rst"
+directory = "docs/changelog"
+title_format = false
+issue_format = "`#{issue} <https://github.com/tox-dev/tox/issues/{issue}>`_"
+template = "docs/changelog/template.jinja2"
+# possible types, all default: feature, bugfix, doc, removal, misc
diff --git a/setup.cfg b/setup.cfg
index 94be8a62..277e0490 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -75,3 +75,8 @@ where = src
[bdist_wheel]
universal = 1
+
+[tool:pytest]
+testpaths = tests
+junit_family = xunit2
+addopts = --tb=auto -ra --showlocals
diff --git a/setup.py b/setup.py
index bf2e3b44..60684932 100644
--- a/setup.py
+++ b/setup.py
@@ -1,9 +1,3 @@
-from setuptools import __version__, setup
+from setuptools import setup
-if int(__version__.split(".")[0]) < 41:
- raise RuntimeError("setuptools >= 41 required to build")
-
-setup(
- use_scm_version={"write_to": "src/tox/version.py", "write_to_template": '__version__ = "{version}"'},
- setup_requires=["setuptools_scm >= 2"],
-)
+setup()
diff --git a/src/tox/__init__.py b/src/tox/__init__.py
index dc2782c3..56a4babe 100644
--- a/src/tox/__init__.py
+++ b/src/tox/__init__.py
@@ -1,3 +1,7 @@
+from .run import main
from .version import __version__
-__all__ = ("__version__",)
+__all__ = (
+ "__version__",
+ "main",
+)
diff --git a/src/tox/config/cli/env_var.py b/src/tox/config/cli/env_var.py
index 6e46c6b4..6e5de1be 100644
--- a/src/tox/config/cli/env_var.py
+++ b/src/tox/config/cli/env_var.py
@@ -1,3 +1,6 @@
+"""
+Provides configuration values from the the environment variables.
+"""
import logging
import os
@@ -18,12 +21,11 @@ def get_env_var(key, of_type):
environ_key = fmt.format(key_upper)
if environ_key in os.environ:
value = os.environ[environ_key]
- # noinspection PyBroadException
try:
source = f"env var {environ_key}"
of_type = CONVERT.to(raw=value, of_type=of_type)
return of_type, source
- except Exception as exception:
+ except Exception as exception: # noqa
logging.warning(
"env var %s=%r cannot be transformed to %r because %r",
environ_key,
diff --git a/src/tox/config/cli/for_docs.py b/src/tox/config/cli/for_docs.py
index 95f6393f..d830034a 100644
--- a/src/tox/config/cli/for_docs.py
+++ b/src/tox/config/cli/for_docs.py
@@ -1,3 +1,6 @@
-from .parse import _get_core_parser
+"""
+This module exports the parser for the Sphinx doc generator.
+"""
+from .parse import _get_parser
-parser = _get_core_parser()
+parser = _get_parser()
diff --git a/src/tox/config/cli/ini.py b/src/tox/config/cli/ini.py
index 1a92c5f4..dc407c00 100644
--- a/src/tox/config/cli/ini.py
+++ b/src/tox/config/cli/ini.py
@@ -1,3 +1,6 @@
+"""
+Provides configuration values from tox.ini files.
+"""
import logging
import os
from pathlib import Path
@@ -27,14 +30,12 @@ class IniConfig:
self.config_file = self.config_file.absolute()
try:
self.ini = Ini(self.config_file)
- # noinspection PyProtectedMember
- self.has_tox_section = cast(IniLoader, self.ini.core)._section is not None
+ self.has_tox_section = cast(IniLoader, self.ini.core)._section is not None # noqa
except Exception as exception:
logging.error("failed to read config file %s because %r", config_file, exception)
self.has_config_file = None
def get(self, key, of_type):
- # noinspection PyBroadException
cache_key = key, of_type
if cache_key in self._cache:
result = self._cache[cache_key]
@@ -45,14 +46,8 @@ class IniConfig:
result = value, source
except KeyError: # just not found
result = None
- except Exception as exception:
- logging.warning(
- "%s key %s as type %r failed with %r",
- self.config_file,
- key,
- of_type,
- exception,
- )
+ except Exception as exception: # noqa
+ logging.warning("%s key %s as type %r failed with %r", self.config_file, key, of_type, exception)
result = None
self._cache[cache_key] = result
return result
@@ -62,6 +57,7 @@ class IniConfig:
@property
def epilog(self):
+ # text to show within the parsers epilog
return (
f"{os.linesep}config file {str(self.config_file)!r} {self.STATE[self.has_config_file]} "
f"(change{'d' if self.is_env_var else ''} via env var {self.TOX_CONFIG_FILE_ENV_VAR})"
diff --git a/src/tox/config/cli/parse.py b/src/tox/config/cli/parse.py
index 5ba8c5f1..a03f3a50 100644
--- a/src/tox/config/cli/parse.py
+++ b/src/tox/config/cli/parse.py
@@ -1,3 +1,7 @@
+"""
+This module pulls together this package: create and parse CLI arguments for tox.
+"""
+
from typing import Dict, List, Tuple
from tox.report import setup_report
@@ -7,13 +11,14 @@ from .parser import Handler, Parsed, ToxParser
def get_options(*args) -> Tuple[Parsed, List[str], Dict[str, Handler]]:
guess_verbosity = _get_base(args)
- handlers, parsed, unknown = _get_core(args)
+ handlers, parsed, unknown = _get_all(args)
if guess_verbosity != parsed.verbosity:
setup_report(parsed.verbosity, parsed.is_colored) # pragma: no cover
return parsed, unknown, handlers
def _get_base(args):
+ """First just load the base options (verbosity+color) to setup the logging framework."""
tox_parser = ToxParser.base()
parsed, unknown = tox_parser.parse(args)
guess_verbosity = parsed.verbosity
@@ -21,18 +26,22 @@ def _get_base(args):
return guess_verbosity
-def _get_core(args):
- tox_parser = _get_core_parser()
+def _get_all(args):
+ """Parse all the options."""
+ tox_parser = _get_parser()
parsed, unknown = tox_parser.parse(args)
handlers = {k: p for k, (_, p) in tox_parser.handlers.items()}
return handlers, parsed, unknown
-def _get_core_parser():
- tox_parser = ToxParser.core()
- # noinspection PyUnresolvedReferences
- from tox.plugin.manager import MANAGER
+def _get_parser():
+ tox_parser = ToxParser.core() # load the core options
+ # plus options setup by plugins
+ from tox.plugin.manager import MANAGER # noqa
MANAGER.tox_add_option(tox_parser)
tox_parser.fix_defaults()
return tox_parser
+
+
+__all__ = ("get_options",)
diff --git a/src/tox/config/cli/parser.py b/src/tox/config/cli/parser.py
index 6339149d..23a08785 100644
--- a/src/tox/config/cli/parser.py
+++ b/src/tox/config/cli/parser.py
@@ -1,22 +1,37 @@
+"""
+Customize argparse logic for tox (also contains the base options).
+"""
+
import argparse
import logging
import os
import sys
-from argparse import SUPPRESS, Action, ArgumentDefaultsHelpFormatter, ArgumentParser, Namespace
+from argparse import (
+ SUPPRESS,
+ Action,
+ ArgumentDefaultsHelpFormatter,
+ ArgumentParser,
+ Namespace,
+)
from itertools import chain
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, TypeVar
from tox.config.source.ini import StrConvert
-from tox.plugin.util import NAME
+from tox.plugin import NAME
from tox.session.state import State
from .env_var import get_env_var
from .ini import IniConfig
+if sys.version_info >= (3, 8):
+ from typing import Literal
+else:
+ from typing_extensions import Literal # noqa
+
class ArgumentParserWithEnvAndConfig(ArgumentParser):
"""
- Custom option parser which updates its defaults by checking the configuration files and environmental variables
+ Argument parser which updates its defaults by checking the configuration files and environmental variables.
"""
def __init__(self, *args: Any, **kwargs: Any) -> None:
@@ -47,10 +62,6 @@ class ArgumentParserWithEnvAndConfig(ArgumentParser):
if of_type is None:
if isinstance(action, argparse._StoreAction) and action.choices: # noqa
loc = locals()
- if sys.version_info >= (3, 8):
- from typing import Literal # noqa
- else:
- from typing_extensions import Literal # noqa
loc["Literal"] = Literal
as_literal = f"Literal[{', '.join(repr(i) for i in action.choices)}]"
of_type = eval(as_literal, globals(), loc)
@@ -64,12 +75,16 @@ class ArgumentParserWithEnvAndConfig(ArgumentParser):
class HelpFormatter(ArgumentDefaultsHelpFormatter):
+ """
+ A help formatter that provides the default value and the source it comes from.
+ """
+
def __init__(self, prog: str) -> None:
super().__init__(prog, max_help_position=42, width=240)
def _get_help_string(self, action: Action) -> str:
- # noinspection PyProtectedMember
- text = super()._get_help_string(action)
+
+ text = super()._get_help_string(action) # noqa
if hasattr(action, "default_source"):
default = " (default: %(default)s)"
if text.endswith(default):
@@ -77,6 +92,12 @@ class HelpFormatter(ArgumentDefaultsHelpFormatter):
return text
+Handler = Callable[[State], Optional[int]]
+
+
+ToxParserT = TypeVar("ToxParserT", bound="ToxParser")
+
+
class Parsed(Namespace):
@property
def verbosity(self) -> int:
@@ -87,18 +108,14 @@ class Parsed(Namespace):
return self.colored == "yes"
-Handler = Callable[[State], Optional[int]]
-
-
-ToxParserT = TypeVar("ToxParserT", bound="ToxParser")
-
-
class ToxParser(ArgumentParserWithEnvAndConfig):
+ """Argument parser for tox."""
+
def __init__(self, *args: Any, root: bool = False, add_cmd: bool = False, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
if root is True:
self._add_base_options()
- self.handlers = {} # type:Dict[str, Tuple[Any, Handler]]
+ self.handlers: Dict[str, Tuple[Any, Handler]] = {}
if add_cmd is True:
self._cmd = self.add_subparsers(title="command", help="tox command to execute", dest="command")
self._cmd.required = False
@@ -130,6 +147,7 @@ class ToxParser(ArgumentParserWithEnvAndConfig):
return cls(prog=NAME, formatter_class=HelpFormatter, add_cmd=True, root=True)
def _add_base_options(self) -> None:
+ """Argument options that always make sense."""
from tox.report import LEVELS
level_map = "|".join("{} - {}".format(c, logging.getLevelName(l)) for c, l in sorted(list(LEVELS.items())))
@@ -163,7 +181,8 @@ class ToxParser(ArgumentParserWithEnvAndConfig):
return result, unknown
def _inject_default_cmd(self, args):
- # we need to inject the command if not present and reorganize args left of the command
+ # if the users specifies no command we imply he wants run, however for this to work we need to inject it onto
+ # the argument parsers left side
if self._cmd is None: # no commands yet so must be all global, nothing to fix
return args
_global = {
diff --git a/src/tox/config/core.py b/src/tox/config/core.py
index 236deaa4..d74d1157 100644
--- a/src/tox/config/core.py
+++ b/src/tox/config/core.py
@@ -1,3 +1,4 @@
+"""Define configuration options that are part of the core tox configurations"""
from pathlib import Path
from tox.config.sets import ConfigSet
diff --git a/src/tox/config/sets.py b/src/tox/config/sets.py
index 6d8bc82b..7db0632a 100644
--- a/src/tox/config/sets.py
+++ b/src/tox/config/sets.py
@@ -1,3 +1,6 @@
+"""
+Group together configuration values that belong together (such as base tox configuration, tox environment configs)
+"""
from abc import ABC, abstractmethod
from collections import OrderedDict
from copy import deepcopy
@@ -21,6 +24,8 @@ if TYPE_CHECKING:
class ConfigDefinition(ABC):
+ """Abstract base class for configuration definitions"""
+
def __init__(self, keys: Iterable[str], desc: str) -> None:
self.keys = keys
self.desc = desc
@@ -31,6 +36,8 @@ class ConfigDefinition(ABC):
class ConfigConstantDefinition(ConfigDefinition):
+ """A configuration definition whose value is defined upfront (such as the tox environment name)"""
+
def __init__(self, keys: Iterable[str], desc: str, value: Any) -> None:
super().__init__(keys, desc)
self.value = value
@@ -47,6 +54,8 @@ _PLACE_HOLDER = object()
class ConfigDynamicDefinition(ConfigDefinition):
+ """A configuration definition that comes from a source (such as in memory, an ini file, a toml file, etc.)"""
+
def __init__(
self,
keys: Iterable[str],
@@ -97,9 +106,11 @@ class ConfigDynamicDefinition(ConfigDefinition):
class ConfigSet:
+ """A set of configuration that belong together (such as a tox environment settings, core tox settings)"""
+
def __init__(self, raw: Loader, conf: "Config"):
self._raw = raw
- self._defined = {} # type:Dict[str, ConfigDefinition]
+ self._defined: Dict[str, ConfigDefinition] = {}
self._conf = conf
self._keys = OrderedDict()
self._raw.setup_with_conf(self)
@@ -115,14 +126,6 @@ class ConfigSet:
):
"""
Add configuration value.
-
- :param keys:
- :param of_type:
- :param default:
- :param desc:
- :param post_process:
- :param overwrite:
- :return:
"""
keys_ = self._make_keys(keys)
for key in keys_:
@@ -163,4 +166,5 @@ class ConfigSet:
return iter(self._keys.keys())
def unused(self) -> Set[str]:
+ """Return a list of keys present in the config source but not used"""
return self._raw.found_keys() - set(self._defined.keys())
diff --git a/src/tox/config/source/api.py b/src/tox/config/source/api.py
index 7d8405a8..53f6b295 100644
--- a/src/tox/config/source/api.py
+++ b/src/tox/config/source/api.py
@@ -9,14 +9,14 @@ from tox.execute.request import shell_cmd
if sys.version_info >= (3, 8):
from typing import Literal
else:
- from typing_extensions import Literal
+ from typing_extensions import Literal # noqa
_NO_MAPPING = object()
class Command:
def __init__(self, args):
- self.args = args # type:List[str]
+ self.args: List[str] = args
def __repr__(self):
return f"{type(self).__name__}(args={self.args!r})"
@@ -44,6 +44,8 @@ class EnvList:
class Convert(ABC):
+ """Base abstract class that defines transformation of a value to a tox configuration"""
+
def to(self, raw, of_type):
from_module = getattr(of_type, "__module__", None)
if from_module in ("typing", "typing_extensions"):
@@ -63,7 +65,7 @@ class Convert(ABC):
def _to_typing(self, raw, of_type):
origin = getattr(of_type, "__origin__", getattr(of_type, "__class__", None))
if origin is not None:
- result = _NO_MAPPING # type: Any
+ result: Any = _NO_MAPPING
if origin in (list, List):
result = [self.to(i, of_type.__args__[0]) for i in self.to_list(raw)]
elif origin in (set, Set):
@@ -159,9 +161,11 @@ class Loader(Convert, ABC):
class Source(ABC):
+ """An abstract configuration source. Has a core and per tox environment configuration loader."""
+
def __init__(self, core: Loader) -> None:
- self.core = core # type: Loader
- self._envs = {} # type: Dict[str, Loader]
+ self.core: Loader = core
+ self._envs: Dict[str, Loader] = {}
@abstractmethod
def envs(self, core_conf):
diff --git a/src/tox/config/source/ini/__init__.py b/src/tox/config/source/ini/__init__.py
index da5678b7..a71d3418 100644
--- a/src/tox/config/source/ini/__init__.py
+++ b/src/tox/config/source/ini/__init__.py
@@ -1,3 +1,4 @@
+"""Load """
from configparser import ConfigParser, SectionProxy
from copy import deepcopy
from itertools import chain
@@ -15,6 +16,8 @@ TEST_ENV_PREFIX = f"{BASE_TEST_ENV}:"
class Ini(Source):
+ """Configuration sourced from a ini file (such as tox.ini)"""
+
CORE_PREFIX = "tox"
def __init__(self, path: Path) -> None:
@@ -30,7 +33,7 @@ class Ini(Source):
section_loader=self._get_section,
)
super().__init__(core)
- self._envs = {} # type: Dict[str, IniLoader]
+ self._envs: Dict[str, IniLoader] = {}
def __deepcopy__(self, memo):
# python < 3.7 cannot copy config parser
@@ -101,7 +104,7 @@ class Ini(Source):
class IniLoader(StrConvert, Loader):
- """Load from ini section"""
+ """Load configuration from an ini section (ini file is a string to string dictionary)"""
def __init__(
self,
@@ -112,10 +115,10 @@ class IniLoader(StrConvert, Loader):
section_loader,
) -> None:
super().__init__(name)
- self._section = section # type:Optional[SectionProxy]
- self._src = src # type: Ini
- self._default_base = default_base # type:EnvList
- self._base = [] # type:List[IniLoader]
+ self._section: Optional[SectionProxy] = section
+ self._src: Ini = src
+ self._default_base: EnvList = default_base
+ self._base: List[IniLoader] = []
self._section_loader = section_loader
def __deepcopy__(self, memo):
@@ -131,15 +134,15 @@ class IniLoader(StrConvert, Loader):
return result
def setup_with_conf(self, conf: ConfigSet):
- # noinspection PyUnusedLocal
- def load_bases(values, conf_):
- result = [] # type: List[IniLoader]
+ def load_bases(values, conf_): # noqa
+ result: List[IniLoader] = []
for value in values:
name = value.lstrip(TEST_ENV_PREFIX)
- ini_loader = self._src.get_section(value, name) # type: IniLoader
+ ini_loader: IniLoader = self._src.get_section(value, name)
result.append(ini_loader)
return result
+ # allow environment inheritance
conf.add_config(
keys="base",
of_type=EnvList,
diff --git a/src/tox/config/source/ini/convert.py b/src/tox/config/source/ini/convert.py
index 155365a9..a283a35a 100644
--- a/src/tox/config/source/ini/convert.py
+++ b/src/tox/config/source/ini/convert.py
@@ -1,3 +1,4 @@
+"""Convert string configuration values to tox python configuration objects."""
import shlex
from itertools import chain
from pathlib import Path
diff --git a/src/tox/config/source/ini/factor.py b/src/tox/config/source/ini/factor.py
index 77c52636..4c9d9662 100644
--- a/src/tox/config/source/ini/factor.py
+++ b/src/tox/config/source/ini/factor.py
@@ -1,3 +1,6 @@
+"""
+Expand tox factor expressions to tox environment list.
+"""
import itertools
import re
@@ -83,4 +86,9 @@ def expand_env_with_negation(value):
yield variant_str
-__all__ = ("filter_for_env", "find_envs", "expand_factors", "extend_factors")
+__all__ = (
+ "filter_for_env",
+ "find_envs",
+ "expand_factors",
+ "extend_factors",
+)
diff --git a/src/tox/config/source/ini/replace.py b/src/tox/config/source/ini/replace.py
index 09f8f2a0..10f72b21 100644
--- a/src/tox/config/source/ini/replace.py
+++ b/src/tox/config/source/ini/replace.py
@@ -1,3 +1,6 @@
+"""
+Apply value substitution (replacement) on tox strings.
+"""
import os
import re
import sys
@@ -20,8 +23,7 @@ BASE_TEST_ENV = "testenv"
def substitute_once(val, conf, name, section_loader):
- # noinspection PyTypeChecker
- return RE_ITEM_REF.sub(partial(_replace_match, conf, name, section_loader), val)
+ return RE_ITEM_REF.sub(partial(_replace_match, conf, name, section_loader), val) # noqa
def replace(value, conf, name, section_loader):
@@ -54,7 +56,6 @@ def _replace_match(conf: Config, name, section_loader, match):
else:
value = groups["key"]
section = groups["section"] or name
- # noinspection PyBroadException
if section not in conf:
env_conf = section_loader(section)
else:
@@ -62,7 +63,6 @@ def _replace_match(conf: Config, name, section_loader, match):
try:
replace_value = env_conf[value]
except Exception: # noqa
- # noinspection PyBroadException
try:
try:
if groups["section"] is None:
@@ -73,7 +73,7 @@ def _replace_match(conf: Config, name, section_loader, match):
if key_missing_value is None:
raise
replace_value = key_missing_value
- except Exception:
+ except Exception: # noqa
start, end = match.span()
replace_value = match.string[start:end]
if replace_value is None:
diff --git a/src/tox/config/source/toml.py b/src/tox/config/source/toml.py
deleted file mode 100644
index e69de29b..00000000
--- a/src/tox/config/source/toml.py
+++ /dev/null
diff --git a/src/tox/execute/__init__.py b/src/tox/execute/__init__.py
index e69de29b..58dc0cdf 100644
--- a/src/tox/execute/__init__.py
+++ b/src/tox/execute/__init__.py
@@ -0,0 +1,10 @@
+"""
+Package that handles execution of commands within tox environments.
+"""
+from .api import Outcome
+from .request import ExecuteRequest
+
+__all__ = (
+ "ExecuteRequest",
+ "Outcome",
+)
diff --git a/src/tox/execute/api.py b/src/tox/execute/api.py
index a882e73f..93078688 100644
--- a/src/tox/execute/api.py
+++ b/src/tox/execute/api.py
@@ -1,3 +1,6 @@
+"""
+Abstract base API for executing commands within tox environments.
+"""
import logging
import signal
import sys
@@ -17,13 +20,58 @@ Executor = Callable[[ExecuteRequest, ContentHandler, ContentHandler], int]
SIGINT = signal.CTRL_C_EVENT if sys.platform == "win32" else signal.SIGINT
+class Execute(ABC):
+ """Abstract API for execution of a tox environment"""
+
+ def __call__(self, request: ExecuteRequest, show_on_standard: bool, colored: bool) -> "Outcome":
+ start = timer()
+ executor = self.executor()
+ interrupt = None
+ try:
+ with CollectWrite(sys.stdout if show_on_standard else None) as out:
+ with CollectWrite(sys.stderr if show_on_standard else None, Fore.RED if colored else None) as err:
+ instance: ExecuteInstance = executor(request, out.collect, err.collect)
+ try:
+ exit_code = instance.run()
+ except KeyboardInterrupt as exception:
+ interrupt = exception
+ while True:
+ try:
+ is_main = threading.current_thread() == threading.main_thread()
+ if is_main:
+ # disable further interrupts until we finish this, main thread only
+ if sys.platform != "win32":
+ signal.signal(SIGINT, signal.SIG_IGN)
+ except KeyboardInterrupt: # pragma: no cover
+ continue # pragma: no cover
+ else:
+ try:
+ exit_code = instance.interrupt()
+ break
+ finally:
+ if is_main and sys.platform != "win32": # restore signal handler on main thread
+ signal.signal(SIGINT, signal.default_int_handler)
+ finally:
+ end = timer()
+ result = Outcome(request, show_on_standard, exit_code, out.text, err.text, start, end, instance.cmd)
+ if interrupt is not None:
+ raise ToxKeyboardInterrupt(result, interrupt)
+ return result
+
+ @staticmethod
+ @abstractmethod
+ def executor() -> Type["ExecuteInstance"]:
+ raise NotImplementedError
+
+
class ExecuteInstance:
+ """An instance of a command execution"""
+
def __init__(self, request: ExecuteRequest, out_handler: ContentHandler, err_handler: ContentHandler) -> None:
def _safe_handler(handler, data):
- # noinspection PyBroadException
try:
handler(data)
- except Exception: # pragma: no cover
+ except Exception: # noqa # pragma: no cover
pass # pragma: no cover
self.request = request
@@ -45,6 +93,8 @@ class ExecuteInstance:
class Outcome:
+ """Result of a command execution"""
+
OK = 0
def __init__(
@@ -82,13 +132,7 @@ class Outcome:
print(Fore.RED, file=sys.stderr, end="")
print(self.err, file=sys.stderr, end="")
print(Fore.RESET, file=sys.stderr)
- logger.critical(
- "exit code %d for %s: %s in %s",
- self.exit_code,
- self.request.cwd,
- self.shell_cmd,
- self.elapsed,
- )
+ logger.critical("exit code %d for %s: %s in %s", self.exit_code, self.request.cwd, self.shell_cmd, self.elapsed)
raise SystemExit(self.exit_code)
@property
@@ -104,45 +148,3 @@ class ToxKeyboardInterrupt(KeyboardInterrupt):
def __init__(self, outcome: Outcome, exc: KeyboardInterrupt):
self.outcome = outcome
self.exc = exc
-
-
-class Execute(ABC):
- def __call__(self, request: ExecuteRequest, show_on_standard: bool, colored: bool) -> Outcome:
- start = timer()
- executor = self.executor()
- interrupt = None
- try:
- with CollectWrite(sys.stdout if show_on_standard else None) as out:
- with CollectWrite(sys.stderr if show_on_standard else None, Fore.RED if colored else None) as err:
- instance = executor(request, out.collect, err.collect) # type: ExecuteInstance
- try:
- exit_code = instance.run()
- except KeyboardInterrupt as exception:
- interrupt = exception
- while True:
- try:
- is_main = threading.current_thread() == threading.main_thread()
- if is_main:
- # disable further interrupts until we finish this, main thread only
- if sys.platform != "win32":
- signal.signal(SIGINT, signal.SIG_IGN)
- except KeyboardInterrupt: # pragma: no cover
- continue # pragma: no cover
- else:
- try:
- exit_code = instance.interrupt()
- break
- finally:
- if is_main and sys.platform != "win32": # restore signal handler on main thread
- signal.signal(SIGINT, signal.default_int_handler)
- finally:
- end = timer()
- result = Outcome(request, show_on_standard, exit_code, out.text, err.text, start, end, instance.cmd)
- if interrupt is not None:
- raise ToxKeyboardInterrupt(result, interrupt)
- return result
-
- @staticmethod
- @abstractmethod
- def executor() -> Type[ExecuteInstance]:
- raise NotImplementedError
diff --git a/src/tox/execute/local_sub_process/__init__.py b/src/tox/execute/local_sub_process/__init__.py
index 4f6de97f..e08625d9 100644
--- a/src/tox/execute/local_sub_process/__init__.py
+++ b/src/tox/execute/local_sub_process/__init__.py
@@ -6,7 +6,14 @@ import sys
from subprocess import PIPE, TimeoutExpired
from typing import List, Optional, Sequence, Tuple, Type
-from ..api import SIGINT, ContentHandler, Execute, ExecuteInstance, ExecuteRequest, Outcome
+from ..api import (
+ SIGINT,
+ ContentHandler,
+ Execute,
+ ExecuteInstance,
+ ExecuteRequest,
+ Outcome,
+)
from .read_via_thread import WAIT_GENERAL
if sys.platform == "win32":
@@ -40,7 +47,7 @@ class LocalSubProcessExecuteInstance(ExecuteInstance):
def __init__(self, request: ExecuteRequest, out_handler: ContentHandler, err_handler: ContentHandler) -> None:
super().__init__(request, out_handler, err_handler)
self.process = None
- self._cmd = [] # type: Optional[List[str]]
+ self._cmd: Optional[List[str]] = []
@property
def cmd(self) -> Sequence[str]:
diff --git a/src/tox/execute/request.py b/src/tox/execute/request.py
index 9f4fe415..328499b2 100644
--- a/src/tox/execute/request.py
+++ b/src/tox/execute/request.py
@@ -1,13 +1,16 @@
+"""Module declaring a command execution request."""
import sys
from pathlib import Path
from typing import Dict, List, Sequence, Union
class ExecuteRequest:
+ """Defines a commands execution request"""
+
def __init__(self, cmd: Sequence[Union[str, Path]], cwd: Path, env: Dict[str, str], allow_stdin: bool):
if len(cmd) == 0:
raise ValueError("cannot execute an empty command")
- self.cmd = [str(i) for i in cmd] # type: List[str]
+ self.cmd: List[str] = [str(i) for i in cmd]
self.cwd = cwd
self.env = env
self.allow_stdin = allow_stdin
diff --git a/src/tox/execute/stream.py b/src/tox/execute/stream.py
index 465b2751..178fdb66 100644
--- a/src/tox/execute/stream.py
+++ b/src/tox/execute/stream.py
@@ -12,13 +12,13 @@ class CollectWrite:
def __init__(self, target: Optional[IO[bytes]], color: Optional[str] = None) -> None:
self._content = bytearray()
- self._print_to = None if target is None else target.buffer # type:Optional[IO[bytes]]
- self._do_print = target is not None # type: bool
- self._keep_printing = Event() # type: Event
- self._content_lock = Lock() # type: Lock
- self._print_lock = Lock() # type: Lock
- self._at = 0 # type: int
- self._color = color # type: Optional[str]
+ self._print_to: Optional[IO[bytes]] = None if target is None else target.buffer
+ self._do_print: bool = target is not None
+ self._keep_printing: Event = Event()
+ self._content_lock: Lock = Lock()
+ self._print_lock: Lock = Lock()
+ self._at: int = 0
+ self._color: Optional[str] = color
def __enter__(self):
if self._do_print:
diff --git a/src/tox/helper/__init__.py b/src/tox/helper/__init__.py
index 482e21b3..7267899c 100644
--- a/src/tox/helper/__init__.py
+++ b/src/tox/helper/__init__.py
@@ -1,3 +1,6 @@
+"""
+Contains helper scripts.
+"""
from pathlib import Path
HERE = Path(__file__).absolute().parent
diff --git a/src/tox/helper/build_isolated.py b/src/tox/helper/build_isolated.py
index 5de28a96..b6d615a1 100644
--- a/src/tox/helper/build_isolated.py
+++ b/src/tox/helper/build_isolated.py
@@ -1,3 +1,6 @@
+"""
+Build a package per PEP-517.
+"""
import json
import sys
@@ -8,8 +11,7 @@ extra = json.loads(sys.argv[4])
backend_spec = sys.argv[5]
backend_obj = sys.argv[6] if len(sys.argv) >= 7 else None
-# noinspection PyTypeChecker
-backend = __import__(backend_spec, fromlist=[None])
+backend = __import__(backend_spec, fromlist=[None]) # noqa
if backend_obj:
backend = getattr(backend, backend_obj)
diff --git a/src/tox/helper/build_requires.py b/src/tox/helper/build_requires.py
index 6f47c90b..a76f7e60 100644
--- a/src/tox/helper/build_requires.py
+++ b/src/tox/helper/build_requires.py
@@ -1,3 +1,7 @@
+"""
+Get environment requires per PEP-517.
+"""
+
import json
import sys
@@ -5,8 +9,8 @@ into = sys.argv[1]
backend_spec = sys.argv[2]
backend_obj = sys.argv[3] if len(sys.argv) >= 4 else None
-# noinspection PyTypeChecker
-backend = __import__(backend_spec, fromlist=[None])
+
+backend = __import__(backend_spec, fromlist=[None]) # noqa
if backend_obj:
backend = getattr(backend, backend_obj)
diff --git a/src/tox/helper/wheel_meta.py b/src/tox/helper/wheel_meta.py
index 9f512253..d63cf3e1 100644
--- a/src/tox/helper/wheel_meta.py
+++ b/src/tox/helper/wheel_meta.py
@@ -1,3 +1,6 @@
+"""
+Get projects metadata per PEP-517.
+"""
import json
import sys
@@ -6,8 +9,8 @@ extra = json.loads(sys.argv[2])
backend_spec = sys.argv[3]
backend_obj = sys.argv[4] if len(sys.argv) >= 5 else None
-# noinspection PyTypeChecker
-backend = __import__(backend_spec, fromlist=[None])
+
+backend = __import__(backend_spec, fromlist=[None]) # noqa
if backend_obj:
backend = getattr(backend, backend_obj)
diff --git a/src/tox/log/__init__.py b/src/tox/log/__init__.py
index ed549068..bfa2defc 100644
--- a/src/tox/log/__init__.py
+++ b/src/tox/log/__init__.py
@@ -1,4 +1,10 @@
"""This module handles collecting and persisting in json format a tox session"""
+from .command import CommandLog
+from .env import EnvLog
from .result import ResultLog
-__all__ = ("ResultLog",)
+__all__ = (
+ "ResultLog",
+ "EnvLog",
+ "CommandLog",
+)
diff --git a/src/tox/log/command.py b/src/tox/log/command.py
index 6a3d34bf..db9e3ee9 100644
--- a/src/tox/log/command.py
+++ b/src/tox/log/command.py
@@ -1,3 +1,6 @@
+"""Record commands executed by tox"""
+
+
class CommandLog:
"""Report commands interacting with third party tools"""
diff --git a/src/tox/log/env.py b/src/tox/log/env.py
index e7b9f9e7..e9a2b562 100644
--- a/src/tox/log/env.py
+++ b/src/tox/log/env.py
@@ -1,3 +1,5 @@
+"""Record information about tox environments"""
+
from copy import copy
from .command import CommandLog
diff --git a/src/tox/log/result.py b/src/tox/log/result.py
index 785bebbc..051bf7ad 100644
--- a/src/tox/log/result.py
+++ b/src/tox/log/result.py
@@ -1,4 +1,4 @@
-"""Generate json report of a run"""
+"""Generate json report of a tox run"""
import json
import socket
import sys
diff --git a/src/tox/plugin/__init__.py b/src/tox/plugin/__init__.py
index e69de29b..01dc773d 100644
--- a/src/tox/plugin/__init__.py
+++ b/src/tox/plugin/__init__.py
@@ -0,0 +1,5 @@
+"""
+API for the plugin system used.
+"""
+
+NAME = "tox"
diff --git a/src/tox/plugin/impl.py b/src/tox/plugin/impl.py
index 858b13ca..bc2f71ab 100644
--- a/src/tox/plugin/impl.py
+++ b/src/tox/plugin/impl.py
@@ -1,5 +1,5 @@
import pluggy
-from .util import NAME
+from . import NAME
impl = pluggy.HookimplMarker(NAME)
diff --git a/src/tox/plugin/manager.py b/src/tox/plugin/manager.py
index 8d5eb84e..83ec38d4 100644
--- a/src/tox/plugin/manager.py
+++ b/src/tox/plugin/manager.py
@@ -1,3 +1,4 @@
+"""Contains the plugin manager object"""
from typing import List, Type
import pluggy
@@ -15,13 +16,12 @@ from tox.tox_env.python.virtual_env.package import dev
from tox.tox_env.python.virtual_env.package.artifact import sdist, wheel
from tox.tox_env.register import REGISTER, ToxEnvRegister
-from . import spec
-from .util import NAME
+from . import NAME, spec
class Plugin:
def __init__(self) -> None:
- self.manager = pluggy.PluginManager(NAME) # type:pluggy.PluginManager
+ self.manager: pluggy.PluginManager = pluggy.PluginManager(NAME)
self.manager.add_hookspecs(spec)
internal_plugins = (
diff --git a/src/tox/plugin/spec.py b/src/tox/plugin/spec.py
index 7042f7ac..fdaf3438 100644
--- a/src/tox/plugin/spec.py
+++ b/src/tox/plugin/spec.py
@@ -8,24 +8,21 @@ from tox.config.sets import ConfigSet
from tox.tox_env.api import ToxEnv
from tox.tox_env.register import ToxEnvRegister
-from .util import NAME
+from . import NAME
hook_spec = pluggy.HookspecMarker(NAME)
-# noinspection PyUnusedLocal
@hook_spec
-def tox_add_option(parser: ArgumentParser) -> None:
+def tox_add_option(parser: ArgumentParser) -> None: # noqa
"""add cli flags"""
-# noinspection PyUnusedLocal
@hook_spec
-def tox_add_core_config(core: ConfigSet) -> None:
+def tox_add_core_config(core: ConfigSet) -> None: # noqa
"""add options to the core section of the tox"""
-# noinspection PyUnusedLocal
@hook_spec
-def tox_register_tox_env(register: ToxEnvRegister) -> Type[ToxEnv]:
+def tox_register_tox_env(register: ToxEnvRegister) -> Type[ToxEnv]: # noqa
"""register new tox environment types that can have their own argument"""
diff --git a/src/tox/plugin/util.py b/src/tox/plugin/util.py
deleted file mode 100644
index 30f0740a..00000000
--- a/src/tox/plugin/util.py
+++ /dev/null
@@ -1 +0,0 @@
-NAME = "tox"
diff --git a/src/tox/provision/__init__.py b/src/tox/provision/__init__.py
index a21dc161..315b3e62 100644
--- a/src/tox/provision/__init__.py
+++ b/src/tox/provision/__init__.py
@@ -1,3 +1,6 @@
+"""
+This package handles provisioning an appropriate tox version per requirements.
+"""
import sys
from typing import List
@@ -65,13 +68,12 @@ def tox_add_core_config(core: ConfigSet):
post_process=add_tox_requires_min_version,
)
core.add_config(
- keys=["no_package", "app", "skip_sdist"],
+ keys=["no_package", "skipsdist"],
of_type=bool,
default=False,
desc="Is there any packaging involved in this project.",
)
-# noinspection PyUnusedLocal
-def run_provision(deps: List[Requirement], tox_env: ToxEnv):
+def run_provision(deps: List[Requirement], tox_env: ToxEnv): # noqa
""""""
diff --git a/src/tox/pytest.py b/src/tox/pytest.py
index d6f201b9..5b5b7ca5 100644
--- a/src/tox/pytest.py
+++ b/src/tox/pytest.py
@@ -1,3 +1,7 @@
+"""
+A pytest plugin useful to test tox itself (and its plugins).
+"""
+
import os
import sys
import textwrap
@@ -83,7 +87,7 @@ def empty_project(tox_project, monkeypatch):
class ToxProject:
def __init__(self, files: Dict[str, Any], path: Path, capsys, monkeypatch):
- self.path = path # type: Path
+ self.path: Path = path
self._capsys = capsys
self.monkeypatch = monkeypatch
self._setup_files(self.path, files)
@@ -155,12 +159,12 @@ class ToxRunOutcome:
def __init__(self, cmd: Sequence[str], cwd: Path, code: int, out: str, err: str, state: Optional[State]) -> None:
extended_cmd = [sys.executable, "-m", "tox"]
extended_cmd.extend(cmd)
- self.cmd = extended_cmd # type: List[str]
- self.cwd = cwd # type: Path
- self.code = code # type:int
- self.out = out # type:str
- self.err = err # type: str
- self.state = state # type:Optional[State]
+ self.cmd: List[str] = extended_cmd
+ self.cwd: Path = cwd
+ self.code: int = code
+ self.out: str = out
+ self.err: str = err
+ self.state: Optional[State] = state
@property
def success(self) -> bool:
diff --git a/src/tox/report.py b/src/tox/report.py
index 8ca144e2..bdc02b08 100644
--- a/src/tox/report.py
+++ b/src/tox/report.py
@@ -1,3 +1,4 @@
+"""Handle reporting from within tox"""
import logging
import sys
diff --git a/src/tox/run.py b/src/tox/run.py
index 51d6a1ea..7762de12 100644
--- a/src/tox/run.py
+++ b/src/tox/run.py
@@ -1,3 +1,4 @@
+"""Main entry point for tox."""
import sys
from pathlib import Path
from typing import Optional, Sequence
@@ -11,27 +12,35 @@ from tox.tox_env.builder import build_tox_envs
def run(args: Optional[Sequence[str]] = None) -> None:
try:
- state = setup_state(args)
- command = state.options.command
- handler = state.handlers[command]
- result = handler(state)
- if result is None:
- result = 0
- raise SystemExit(result)
+ result = main(sys.argv[1:] if args is None else args)
except KeyboardInterrupt:
- raise SystemExit(-2)
+ result = -2
+ raise SystemExit(result)
-def make_config(path: Path) -> Config:
- tox_ini = path / "tox.ini"
- ini_loader = Ini(tox_ini)
- return Config(ini_loader)
+def main(args: Sequence[str]) -> int:
+ state = setup_state(args)
+ command = state.options.command
+ handler = state.handlers[command]
+ result = handler(state)
+ if result is None:
+ result = 0
+ return result
-def setup_state(args: Optional[Sequence[str]]) -> State:
- if args is None:
- args = sys.argv[1:]
+def setup_state(args: Sequence[str]) -> State:
+ """Setup the state object of this run."""
+ # parse CLI arguments
options = get_options(*args)
+ # parse configuration file
config = make_config(Path().absolute())
+ # build tox environment config objects
state = build_tox_envs(config, options, args)
return state
+
+
+def make_config(path: Path) -> Config:
+ """Make a tox configuration object."""
+ # for now only tox.ini supported
+ ini_loader = Ini(path / "tox.ini")
+ return Config(ini_loader)
diff --git a/src/tox/session/__init__.py b/src/tox/session/__init__.py
index e69de29b..e818d7ac 100644
--- a/src/tox/session/__init__.py
+++ b/src/tox/session/__init__.py
@@ -0,0 +1,3 @@
+"""
+Package that handles execution of various commands within tox.
+"""
diff --git a/src/tox/session/cmd/list_env.py b/src/tox/session/cmd/list_env.py
index 82ca38ae..6207e3cb 100644
--- a/src/tox/session/cmd/list_env.py
+++ b/src/tox/session/cmd/list_env.py
@@ -1,3 +1,6 @@
+"""
+Print available tox environments.
+"""
from tox.config.cli.parser import ToxParser
from tox.plugin.impl import impl
from tox.session.state import State
diff --git a/src/tox/session/cmd/run/__init__.py b/src/tox/session/cmd/run/__init__.py
index e69de29b..791f5094 100644
--- a/src/tox/session/cmd/run/__init__.py
+++ b/src/tox/session/cmd/run/__init__.py
@@ -0,0 +1,3 @@
+"""
+Defines how we execute a tox environment.
+"""
diff --git a/src/tox/session/cmd/run/common.py b/src/tox/session/cmd/run/common.py
index d84d55ec..118f2ed0 100644
--- a/src/tox/session/cmd/run/common.py
+++ b/src/tox/session/cmd/run/common.py
@@ -1,3 +1,4 @@
+"""Common functionality shared across multiple type of runs"""
from tox.config.cli.parser import ToxParser
diff --git a/src/tox/session/cmd/run/parallel.py b/src/tox/session/cmd/run/parallel.py
index 0511f2ae..affe239d 100644
--- a/src/tox/session/cmd/run/parallel.py
+++ b/src/tox/session/cmd/run/parallel.py
@@ -1,3 +1,6 @@
+"""
+Run tox environments in parallel.
+"""
import inspect
import logging
import os
@@ -22,7 +25,7 @@ logger = logging.getLogger(__name__)
ENV_VAR_KEY = "TOX_PARALLEL_ENV"
OFF_VALUE = 0
DEFAULT_PARALLEL = OFF_VALUE
-MAIN_FILE = Path(inspect.getsourcefile(tox)) / "__main__.py"
+MAIN_FILE = Path(inspect.getsourcefile(tox)).parent / "__main__.py"
@impl
@@ -169,8 +172,7 @@ def _stop_child_processes(processes, main_threads):
"""A three level stop mechanism for children - INT (250ms) -> TERM (100ms) -> KILL"""
# first stop children
- # noinspection PyUnusedLocal
- def shutdown(tox_env, action, process):
+ def shutdown(tox_env, action, process): # noqa
action.handle_interrupt(process)
threads = [Thread(target=shutdown, args=(n, a, p)) for n, (a, p) in processes.items()]
diff --git a/src/tox/session/cmd/run/sequential.py b/src/tox/session/cmd/run/sequential.py
index bdf76074..688377c1 100644
--- a/src/tox/session/cmd/run/sequential.py
+++ b/src/tox/session/cmd/run/sequential.py
@@ -1,3 +1,6 @@
+"""
+Run tox environments in sequential order.
+"""
from typing import Dict
from tox.config.cli.parser import ToxParser
@@ -19,15 +22,14 @@ def tox_add_option(parser: ToxParser) -> None:
def run_sequential(state: State) -> int:
- status_codes = {} # type:Dict[str, int]
+ status_codes: Dict[str, int] = {}
for name in state.env_list:
tox_env = state.tox_envs[name]
status_codes[name] = run_one(tox_env, state.options.recreate, state.options.no_test)
return report(status_codes, state.tox_envs)
-# noinspection PyUnusedLocal
-def report(status_dict: Dict[str, int], tox_envs: Dict[str, ToxEnv]) -> int:
+def report(status_dict: Dict[str, int], tox_envs: Dict[str, ToxEnv]) -> int: # noqa
for name, status in status_dict.items():
if status == Outcome.OK:
msg = "OK "
diff --git a/src/tox/session/cmd/run/single.py b/src/tox/session/cmd/run/single.py
index 8e96c134..1c29c429 100644
--- a/src/tox/session/cmd/run/single.py
+++ b/src/tox/session/cmd/run/single.py
@@ -1,3 +1,6 @@
+"""
+Defines how to run a single tox environment.
+"""
from typing import List, cast
from tox.config.source.api import Command
diff --git a/src/tox/session/cmd/show_config.py b/src/tox/session/cmd/show_config.py
index eb61b283..fe277242 100644
--- a/src/tox/session/cmd/show_config.py
+++ b/src/tox/session/cmd/show_config.py
@@ -1,3 +1,6 @@
+"""
+Show materialized configuration of tox environments.
+"""
from typing import Any, List, Union
from tox.config.cli.parser import ToxParser
diff --git a/src/tox/session/cmd/version_flag.py b/src/tox/session/cmd/version_flag.py
index ed84379f..83c3916c 100644
--- a/src/tox/session/cmd/version_flag.py
+++ b/src/tox/session/cmd/version_flag.py
@@ -1,3 +1,6 @@
+"""
+Display the version information about tox.
+"""
from pathlib import Path
from tox.config.cli.parser import ToxParser
diff --git a/src/tox/session/common.py b/src/tox/session/common.py
index ee505266..141194c1 100644
--- a/src/tox/session/common.py
+++ b/src/tox/session/common.py
@@ -7,8 +7,7 @@ from tox.config.source.ini import StrConvert
def env_list_flag(parser: ToxParser):
class ToxEnvList(argparse.Action):
- # noinspection PyShadowingNames
- def __call__(self, parser, args, values, option_string=None):
+ def __call__(self, parser, args, values, option_string=None): # noqa
list_envs = StrConvert().to(values, of_type=List[str])
setattr(args, self.dest, list_envs)
diff --git a/src/tox/session/state.py b/src/tox/session/state.py
index d6068f6b..e66b9f3b 100644
--- a/src/tox/session/state.py
+++ b/src/tox/session/state.py
@@ -6,8 +6,8 @@ from tox.tox_env.runner import RunToxEnv
class State:
def __init__(self, conf, tox_envs, opt_parse, args):
- self.conf = conf # type:Config
- self.tox_envs = tox_envs # type:Dict[str, RunToxEnv]
+ self.conf: Config = conf
+ self.tox_envs: Dict[str, RunToxEnv] = tox_envs
options, unknown, handlers = opt_parse
self.options = options
self.unknown_options = unknown
diff --git a/src/tox/tox_env/__init__.py b/src/tox/tox_env/__init__.py
index e69de29b..b9feade9 100644
--- a/src/tox/tox_env/__init__.py
+++ b/src/tox/tox_env/__init__.py
@@ -0,0 +1,3 @@
+"""
+Package handling the creation and management of tox environments.
+"""
diff --git a/src/tox/tox_env/api.py b/src/tox/tox_env/api.py
index 3cc5b225..da0f1257 100644
--- a/src/tox/tox_env/api.py
+++ b/src/tox/tox_env/api.py
@@ -1,3 +1,6 @@
+"""
+Defines the abstract base traits of a tox environment.
+"""
import itertools
import logging
import os
@@ -11,7 +14,7 @@ from tox.config.sets import ConfigSet
from tox.execute.api import Execute
from tox.execute.request import ExecuteRequest
-from .cache import Cache
+from .info import Info
if sys.platform == "win32":
PASS_ENV_ALWAYS = [
@@ -33,13 +36,13 @@ else:
class ToxEnv(ABC):
def __init__(self, conf: ConfigSet, core: ConfigSet, options, executor: Execute):
- self.conf = conf # type: ConfigSet
- self.core = core # type:ConfigSet
+ self.conf: ConfigSet = conf
+ self.core: ConfigSet = core
self.options = options
self._executor = executor
self.register_config()
- self._cache = Cache(self.conf["env_dir"] / ".tox-cache")
- self._paths = [] # type:List[Path]
+ self._cache = Info(self.conf["env_dir"])
+ self._paths: List[Path] = []
self.logger = logging.getLogger(self.conf["env_name"])
def register_config(self):
@@ -101,11 +104,11 @@ class ToxEnv(ABC):
@property
def environment_variables(self) -> Dict[str, str]:
- result = {} # type:Dict[str, str]
- pass_env = self.conf["pass_env"] # type: List[str]
+ result: Dict[str, str] = {}
+ pass_env: List[str] = self.conf["pass_env"]
pass_env.extend(PASS_ENV_ALWAYS)
- set_env = self.conf["set_env"] # type: Dict[str, str]
+ set_env: Dict[str, str] = self.conf["set_env"]
for key, value in os.environ.items():
if key in pass_env:
result[key] = value
diff --git a/src/tox/tox_env/builder.py b/src/tox/tox_env/builder.py
index 13ea024e..c7576ea1 100644
--- a/src/tox/tox_env/builder.py
+++ b/src/tox/tox_env/builder.py
@@ -1,3 +1,6 @@
+"""
+Build the state of a tox run (creates tox run and build environments).
+"""
import copy
from typing import Dict, cast
@@ -18,9 +21,9 @@ def build_tox_envs(config: Config, options, args):
class Builder:
def __init__(self, options: str, config: Config):
- self.tox_env_to_runner = {} # type:Dict[str, RunToxEnv]
- self._tox_env_to_runner_type = {} # type:Dict[str, str]
- self._pkg_envs = {} # type:Dict[str, PackageToxEnv]
+ self.tox_env_to_runner: Dict[str, RunToxEnv] = {}
+ self._tox_env_to_runner_type: Dict[str, str] = {}
+ self._pkg_envs: Dict[str, PackageToxEnv] = {}
self.options = options
self._config = config
self._run()
@@ -49,7 +52,7 @@ class Builder:
runner = cast(str, env_conf["runner"])
from .register import REGISTER
- env = REGISTER.runner(runner)(env_conf, self._config.core, self.options) # type: RunToxEnv
+ env: RunToxEnv = REGISTER.runner(runner)(env_conf, self._config.core, self.options)
self._tox_env_to_runner_type[env_name] = runner
self._build_package_env(env)
return env
@@ -69,7 +72,7 @@ class Builder:
def _get_package_env(self, packager, pkg_name):
if pkg_name in self._pkg_envs:
- package_tox_env = self._pkg_envs[pkg_name] # type:PackageToxEnv
+ package_tox_env: PackageToxEnv = self._pkg_envs[pkg_name]
else:
if pkg_name in self.tox_env_to_runner: # if already detected as runner remove
del self.tox_env_to_runner[pkg_name]
diff --git a/src/tox/tox_env/errors.py b/src/tox/tox_env/errors.py
index 9a561d15..fd3d6217 100644
--- a/src/tox/tox_env/errors.py
+++ b/src/tox/tox_env/errors.py
@@ -1,10 +1,13 @@
-class Recreate(Exception):
+"""Defines tox error types"""
+
+
+class Recreate(RuntimeError):
"""Recreate the tox environment"""
-class Skip(Exception):
+class Skip(RuntimeError):
"""Skip this tox environment"""
-class Fail(Exception):
+class Fail(RuntimeError):
"""Failed creating env"""
diff --git a/src/tox/tox_env/cache.py b/src/tox/tox_env/info.py
index 5730256d..419f5174 100644
--- a/src/tox/tox_env/cache.py
+++ b/src/tox/tox_env/info.py
@@ -1,11 +1,15 @@
+"""
+Declare and handle the tox env info file (a file at the root of every tox environment that contains information about
+the status of the tox environment - python version of the environment, installed packages, etc.).
+"""
import json
from contextlib import contextmanager
from pathlib import Path
-class Cache:
+class Info:
def __init__(self, path: Path) -> None:
- self._path = path
+ self._path = path / ".tox-info.json"
try:
value = json.loads(self._path.read_text())
except (ValueError, OSError):
diff --git a/src/tox/tox_env/package.py b/src/tox/tox_env/package.py
index 3906e867..1c6c409d 100644
--- a/src/tox/tox_env/package.py
+++ b/src/tox/tox_env/package.py
@@ -1,3 +1,6 @@
+"""
+A tox environment that can build packages.
+"""
from abc import ABC, abstractmethod
from typing import Any, List
diff --git a/src/tox/tox_env/python/api.py b/src/tox/tox_env/python/api.py
index ebb03462..b315610f 100644
--- a/src/tox/tox_env/python/api.py
+++ b/src/tox/tox_env/python/api.py
@@ -1,3 +1,6 @@
+"""
+Declare the abstract base class for tox environments that handle the Python language.
+"""
import sys
from abc import ABC, abstractmethod
from pathlib import Path
@@ -82,8 +85,7 @@ class Python(ToxEnv, ABC):
raise NoInterpreter(base_pythons)
return self._python
- # noinspection PyMethodMayBeStatic
- def get_python(self, base):
+ def get_python(self, base): # noqa
return get_interpreter(base)
def cached_install(self, deps, section, of_type):
diff --git a/src/tox/tox_env/python/package.py b/src/tox/tox_env/python/package.py
index c826d9b9..bd44e01b 100644
--- a/src/tox/tox_env/python/package.py
+++ b/src/tox/tox_env/python/package.py
@@ -1,3 +1,6 @@
+"""
+A tox build environment that handles Python packages.
+"""
import sys
from abc import ABC, abstractmethod
from typing import List
diff --git a/src/tox/tox_env/python/runner.py b/src/tox/tox_env/python/runner.py
index a5994eb1..e1215003 100644
--- a/src/tox/tox_env/python/runner.py
+++ b/src/tox/tox_env/python/runner.py
@@ -1,3 +1,6 @@
+"""
+A tox run environment that handles the Python language.
+"""
from abc import ABC
from typing import List, Set
diff --git a/src/tox/tox_env/python/virtual_env/api.py b/src/tox/tox_env/python/virtual_env/api.py
index c2cc6743..1e4d5189 100644
--- a/src/tox/tox_env/python/virtual_env/api.py
+++ b/src/tox/tox_env/python/virtual_env/api.py
@@ -1,3 +1,6 @@
+"""
+Declare the abstract base class for tox environments that handle the Python language via the virtualenv project.
+"""
import sys
from abc import ABC
from pathlib import Path
@@ -58,8 +61,7 @@ class VirtualEnv(Python, ABC):
def perform_install(self, install_command: Sequence[str]) -> Outcome:
return self.execute(cmd=install_command, allow_stdin=False)
- # noinspection PyMethodMayBeStatic
- def install_command(self, develop, force_reinstall, no_deps, packages):
+ def install_command(self, develop, force_reinstall, no_deps, packages): # noqa
install_command = ["python", "-m", "pip", "--disable-pip-version-check", "install"]
if develop is True:
install_command.append("-e")
diff --git a/src/tox/tox_env/python/virtual_env/package/api.py b/src/tox/tox_env/python/virtual_env/package/api.py
index 31ff65a3..5d49fe9f 100644
--- a/src/tox/tox_env/python/virtual_env/package/api.py
+++ b/src/tox/tox_env/python/virtual_env/package/api.py
@@ -39,12 +39,12 @@ class Pep517VirtualEnvPackage(VirtualEnv, PythonPackage, ABC):
def __init__(self, conf: ConfigSet, core: ConfigSet, options) -> None:
super().__init__(conf, core, options)
backend_module, backend_object, requires = self.load_builder_and_requires()
- self._requires = requires # type: List[Requirement]
- self.build_backend_module = backend_module # type:str
- self.build_backend_obj = backend_object # type: Optional[str]
- self._distribution_meta = None # type:Optional[imp_meta.PathDistribution]
- self._build_requires = None # type:Optional[List[Requirement]]
- self._package = None # type:Optional[Requirement]
+ self._requires: List[Requirement] = requires
+ self.build_backend_module: str = backend_module
+ self.build_backend_obj: Optional[str] = backend_object
+ self._distribution_meta: Optional[imp_meta.PathDistribution] = None
+ self._build_requires: Optional[List[Requirement]] = None
+ self._package: Optional[Requirement] = None
def load_builder_and_requires(self) -> Tuple[str, Optional[str], List[Requirement]]:
py_project_toml = cast(Path, self.core["tox_root"]) / "pyproject.toml"
@@ -113,12 +113,10 @@ class Pep517VirtualEnvPackage(VirtualEnv, PythonPackage, ABC):
extra, _at = None, None
if extra is None or extra in extras:
if _at is not None:
- # noinspection PyProtectedMember
del markers[_at]
_at -= 1
if _at > 0 and markers[_at] in ("and", "or"):
del markers[_at]
- # noinspection PyProtectedMember
if len(markers) == 0:
req.marker = None
result.append(req)
diff --git a/src/tox/tox_env/python/virtual_env/package/artifact/api.py b/src/tox/tox_env/python/virtual_env/package/artifact/api.py
index 41316eac..dbaceac4 100644
--- a/src/tox/tox_env/python/virtual_env/package/artifact/api.py
+++ b/src/tox/tox_env/python/virtual_env/package/artifact/api.py
@@ -42,7 +42,7 @@ class Pep517VirtualEnvPackageArtifact(Pep517VirtualEnvPackage, ABC):
result = self.execute(cmd=cmd, allow_stdin=False, cwd=self.core["tox_root"])
result.assert_success(self.logger)
with open(str(out_file)) as file_handler:
- base_name = json.load(file_handler) # type:str
+ base_name: str = json.load(file_handler)
return [dest / base_name]
def perform_packaging(self) -> List[Path]:
diff --git a/src/tox/tox_env/python/virtual_env/runner.py b/src/tox/tox_env/python/virtual_env/runner.py
index 86fc2254..15f1fa7a 100644
--- a/src/tox/tox_env/python/virtual_env/runner.py
+++ b/src/tox/tox_env/python/virtual_env/runner.py
@@ -1,7 +1,12 @@
+"""
+A tox python environment runner that uses the virtualenv project.
+"""
from configparser import ConfigParser, NoSectionError
from tox.plugin.impl import impl
-from tox.tox_env.python.virtual_env.package.artifact.wheel import Pep517VirtualEnvPackageWheel
+from tox.tox_env.python.virtual_env.package.artifact.wheel import (
+ Pep517VirtualEnvPackageWheel,
+)
from tox.tox_env.register import ToxEnvRegister
from ..runner import PythonRun
diff --git a/src/tox/tox_env/register.py b/src/tox/tox_env/register.py
index f8fed5d4..4732b752 100644
--- a/src/tox/tox_env/register.py
+++ b/src/tox/tox_env/register.py
@@ -6,13 +6,13 @@ from .runner import RunToxEnv
class ToxEnvRegister:
def __init__(self):
- self._run_envs = {} # type:Dict[str, Type[RunToxEnv]]
- self._package_envs = {} # type:Dict[str, Type[PackageToxEnv]]
- self._default_run_env = "" # type:str
+ self._run_envs: Dict[str, Type[RunToxEnv]] = {}
+ self._package_envs: Dict[str, Type[PackageToxEnv]] = {}
+ self._default_run_env: str = ""
def populate(self, manager):
manager.tox_register_tox_env(register=self)
- self._default_run_env = next(iter(self._run_envs.keys())) # type:str
+ self._default_run_env: str = next(iter(self._run_envs.keys()))
def add_run_env(self, of_type: Type[RunToxEnv]):
self._run_envs[of_type.id()] = of_type
diff --git a/src/tox/tox_env/runner.py b/src/tox/tox_env/runner.py
index 552b0420..fdeacd24 100644
--- a/src/tox/tox_env/runner.py
+++ b/src/tox/tox_env/runner.py
@@ -13,7 +13,7 @@ from .package import PackageToxEnv
class RunToxEnv(ToxEnv, ABC):
def __init__(self, conf: ConfigSet, core: ConfigSet, options, execute: Execute):
super().__init__(conf, core, options, execute)
- self.package_env = None # type: Optional[PackageToxEnv]
+ self.package_env: Optional[PackageToxEnv] = None
def register_config(self):
super().register_config()
diff --git a/src/tox/util/__init__.py b/src/tox/util/__init__.py
index 731b7ecb..e69de29b 100644
--- a/src/tox/util/__init__.py
+++ b/src/tox/util/__init__.py
@@ -1,16 +0,0 @@
-import os
-from contextlib import contextmanager
-
-
-@contextmanager
-def set_os_env_var(env_var_name, value):
- """Set an environment variable with unrolling once the context exists"""
- prev_value = os.environ.get(env_var_name)
- try:
- os.environ[env_var_name] = str(value)
- yield
- finally:
- if prev_value is None:
- del os.environ[env_var_name]
- else:
- os.environ[env_var_name] = prev_value
diff --git a/src/tox/util/cpu.py b/src/tox/util/cpu.py
index a29a220e..ac7e5af7 100644
--- a/src/tox/util/cpu.py
+++ b/src/tox/util/cpu.py
@@ -1,3 +1,4 @@
+"""Helper methods related to the CPU"""
import os
diff --git a/src/tox/util/graph.py b/src/tox/util/graph.py
index 1442f76a..8450f909 100644
--- a/src/tox/util/graph.py
+++ b/src/tox/util/graph.py
@@ -1,3 +1,4 @@
+"""Helper methods related to graph theory."""
from collections import OrderedDict, defaultdict
diff --git a/src/tox/util/lock.py b/src/tox/util/lock.py
deleted file mode 100644
index 7908f424..00000000
--- a/src/tox/util/lock.py
+++ /dev/null
@@ -1,38 +0,0 @@
-"""holds locking functionality that works across processes"""
-
-import logging
-from contextlib import contextmanager
-
-import py
-from filelock import FileLock, Timeout
-
-
-@contextmanager
-def hold_lock(lock_file):
- py.path.local(lock_file.dirname).ensure(dir=1)
- lock = FileLock(str(lock_file))
- try:
- try:
- lock.acquire(0.0001)
- except Timeout:
- logging.warning(f"lock file {lock_file} present, will block until released")
- lock.acquire()
- yield
- finally:
- lock.release(force=True)
-
-
-def get_unique_file(path, prefix, suffix):
- """get a unique file in a folder having a given prefix and suffix, with unique number in between"""
- lock_file = path.join(".lock")
- prefix = f"{prefix}-"
- with hold_lock(lock_file):
- max_value = -1
- for candidate in path.listdir(f"{prefix}*{suffix}"):
- try:
- max_value = max(max_value, int(candidate.basename[len(prefix) : -len(suffix)]))
- except ValueError:
- continue
- winner = path.join(f"{prefix}{max_value + 1}{suffix}")
- winner.ensure(dir=0)
- return winner
diff --git a/src/tox/util/path.py b/src/tox/util/path.py
deleted file mode 100644
index 66573744..00000000
--- a/src/tox/util/path.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import logging
-import shutil
-
-
-def ensure_empty_dir(path):
- if path.check():
- logging.warning(f" removing {path}")
- shutil.rmtree(str(path), ignore_errors=True)
- path.ensure(dir=1)
diff --git a/tests/unit/tox_env/python/virtual_env/setuptools/package/test_wheel_build.py b/tests/unit/tox_env/python/virtual_env/setuptools/package/test_wheel_build.py
index d59bf481..d73a3344 100644
--- a/tests/unit/tox_env/python/virtual_env/setuptools/package/test_wheel_build.py
+++ b/tests/unit/tox_env/python/virtual_env/setuptools/package/test_wheel_build.py
@@ -10,7 +10,9 @@ from tox.execute.api import Outcome
from tox.execute.request import ExecuteRequest
from tox.pytest import ToxProjectCreator
from tox.tox_env.python.virtual_env.api import VirtualEnv
-from tox.tox_env.python.virtual_env.package.artifact.wheel import Pep517VirtualEnvPackageWheel
+from tox.tox_env.python.virtual_env.package.artifact.wheel import (
+ Pep517VirtualEnvPackageWheel,
+)
@pytest.fixture()
diff --git a/tox.ini b/tox.ini
index 9bdb3e9f..c0cf8195 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,48 +1,64 @@
[tox]
envlist =
+ fix
+ py39
py38
py37
py36
pypy3
cov
- fix_lint
- pkg_meta
docs
-minversion = 3.14.0
+ pkg_meta
+isolated_build = true
skip_missing_interpreters = true
-isolated_build = True
+minversion = 3.14.0
[testenv]
description = run the tests with pytest
+passenv =
+ PYTEST_*
+ SSL_CERT_FILE
setenv =
COVERAGE_FILE = {env:COVERAGE_FILE:{toxworkdir}/.coverage.{envname}}
COVERAGE_PROCESS_START = {toxinidir}/.coveragerc
_COVERAGE_SRC = {envsitepackagesdir}/tox
-passenv =
- SSL_CERT_FILE
- PYTEST_*
-extras = testing
+extras =
+ testing
commands =
coverage erase
coverage run -m pytest \
- --junitxml {toxworkdir}/junit.{envname}.xml \
- tests {posargs:--timeout 30 --durations 5}
-
+ --junitxml {toxworkdir}/junit.{envname}.xml \
+ tests {posargs:--timeout 30 --durations 5}
coverage combine
coverage report --skip-covered --show-missing
coverage xml -o {toxworkdir}/coverage.{envname}.xml
coverage html -d {envtmpdir}/htmlcov
+[testenv:fix]
+description = format the code base to adhere to our styles, and complain about what we cannot do automatically
+passenv =
+ {[testenv]passenv}
+ PROGRAMDATA
+basepython = python3.8
+skip_install = true
+deps =
+ pre-commit>=2.2
+commands =
+ pre-commit run --all-files --show-diff-on-failure {posargs}
+ python -c 'import pathlib; print("hint: run {} install to add checks as pre-commit hook".format(pathlib.Path(r"{envdir}") / "bin" / "pre-commit"))'
+
[testenv:cov]
description = merge existing coverage reports and report coverage diff against DIFF_MASTER env-var (default origin/master)
-deps =
- coverage>=5
- diff_cover>=3
-skip_install = true
passenv =
{[testenv]passenv}
DIFF_AGAINST
-setenv = COVERAGE_FILE={toxworkdir}/.coverage
+setenv =
+ COVERAGE_FILE = {toxworkdir}/.coverage
+skip_install = true
+deps =
+ coverage>=5
+ diff_cover>=3
+parallel_show_output = true
commands =
coverage combine
coverage report -m
@@ -50,35 +66,44 @@ commands =
coverage html -d {toxworkdir}/htmlcov
diff-cover --compare-branch {env:DIFF_AGAINST:origin/rewrite} {toxworkdir}/coverage.xml
depends =
+ py39
py38
py37
py36
pypy3
-parallel_show_output = True
+
+[testenv:docs]
+description = build documentation
+basepython = python3.8
+extras =
+ docs
+commands =
+ python -c 'import glob; import subprocess; subprocess.call(["proselint"] + glob.glob("docs/*.rst") + glob.glob("docs/**/*.rst"))'
+ sphinx-build -d "{envtmpdir}/doctree" docs "{toxworkdir}/docs_out" --color -b html {posargs}
+ python -c 'import pathlib; print("documentation available under file://\{0\}".format(pathlib.Path(r"{toxworkdir}") / "docs_out" / "index.html"))'
[testenv:pkg_meta]
description = check that the long description is valid
basepython = python3.8
-deps =
- twine >= 3
- pep517 >= 0.8.1
skip_install = true
+deps =
+ build>=0.0.4
+ twine>=3
commands =
- python -m pep517.build -o {envtmpdir} -s -b .
+ python -m build -o {envtmpdir} -s -w .
twine check {envtmpdir}/*
-[testenv:fix_lint]
-description = format the code base to adhere to our styles, and complain about what we cannot do automatically
-basepython = python3.8
-passenv =
- {[testenv]passenv}
- PROGRAMDATA
+[testenv:dev]
+description = dev environment with all deps at {envdir}
+usedevelop = true
deps =
- pre-commit>=2.2.0
-skip_install = true
+ setuptools_scm>=3
+extras =
+ docs
+ testing
commands =
- pre-commit run --all-files --show-diff-on-failure {posargs}
- python -c 'import pathlib; print("hint: run {} install to add checks as pre-commit hook".format(pathlib.Path(r"{envdir}") / "bin" / "pre-commit"))'
+ python -m pip list --format=columns
+ python -c "print(r'{envpython}')"
[flake8]
max-complexity = 22
@@ -87,37 +112,3 @@ ignore = E203, W503, C901, E402, B011
[pep8]
max-line-length = 120
-
-[pytest]
-testpaths = tests
-junit_family = xunit2
-addopts = --tb=auto -ra --showlocals
-
-[isort]
-multi_line_output = 3
-include_trailing_comma = True
-force_grid_wrap = 0
-line_length = 99
-known_first_party = tox,tests
-known_third_party = _overlapped,_pytest,appdirs,colorama,filelock,packaging,pluggy,psutil,py,pytest,setuptools,sphinx_rtd_theme,toml,virtualenv,wheel
-
-[testenv:dev]
-description = dev environment with all deps at {envdir}
-deps =
- setuptools_scm >= 3
-extras =
- testing
- docs
-usedevelop = True
-commands =
- python -m pip list --format=columns
- python -c "print(r'{envpython}')"
-
-[testenv:docs]
-basepython = python3.8
-description = build documentation
-extras = docs
-commands =
- python -c 'import glob; import subprocess; subprocess.call(["proselint"] + glob.glob("docs/*.rst") + glob.glob("docs/**/*.rst"))'
- sphinx-build -d "{envtmpdir}/doctree" docs "{toxworkdir}/docs_out" --color -b html {posargs}
- python -c 'import pathlib; print("documentation available under file://\{0\}".format(pathlib.Path(r"{toxworkdir}") / "docs_out" / "index.html"))'