tox is a generic virtualenv management and test command line tool
Virtual environment creation, management, and lifecycle control for tox. The environment system supports different environment types including Python virtual environments, external environments, and custom environment implementations through a flexible hierarchy and plugin system.
The foundational environment abstraction that defines the interface for all tox environments.
class ToxEnv:
"""Base tox environment class."""
def __init__(self, create_args: ToxEnvCreateArgs) -> None:
"""
Initialize the tox environment.
Args:
create_args: Environment creation arguments
"""
def setup(self) -> None:
"""
Setup the environment for use.
This installs dependencies, configures the environment,
and prepares it for command execution.
"""
def teardown(self) -> None:
"""
Clean up the environment.
This removes temporary files and releases resources
used by the environment.
"""
def execute(self, cmd: Sequence[Path | str], stdin: StdinSource,
show: bool | None = None, cwd: Path | None = None,
run_id: str = "", executor: Execute | None = None) -> Outcome:
"""
Execute commands in the environment.
Args:
cmd: Command and arguments to execute
stdin: Standard input source
show: Whether to show output
cwd: Working directory for execution
run_id: Unique identifier for this execution
executor: Custom executor to use
Returns:
Outcome: Execution result with exit code and output
"""
@property
def name(self) -> str:
"""Environment name (e.g., 'py311', 'docs')."""
@property
def conf(self) -> EnvConfigSet:
"""Environment configuration."""
@property
def core(self) -> CoreConfigSet:
"""Core tox configuration."""
@property
def env_dir(self) -> Path:
"""The tox environment directory."""
@property
def cache(self) -> Info:
"""Environment cache/info management."""
def register_config(self) -> None:
"""Register configuration options for this environment."""
@staticmethod
@abstractmethod
def id() -> str:
"""Return the type ID of this environment."""
@property
@abstractmethod
def executor(self) -> Execute:
"""Return the executor for this environment."""
@property
@abstractmethod
def installer(self) -> Installer[Any]:
"""Return the installer for this environment."""
@property
@abstractmethod
def runs_on_platform(self) -> str:
"""Return platform regex this environment runs on."""Specialized environment classes for Python-based testing and execution.
class PythonToxEnv(ToxEnv):
"""Python-specific tox environment."""
def python_executable(self) -> Path:
"""
Get path to Python executable for this environment.
Returns:
Path: Path to Python interpreter
"""
def install_deps(self) -> None:
"""Install environment dependencies."""
def install_package(self, package_path: Path) -> None:
"""
Install package in environment.
Args:
package_path: Path to package to install
"""
@property
def base_python(self) -> str:
"""Base Python version specification."""
class VirtualEnvToxEnv(PythonToxEnv):
"""Virtual environment implementation for Python."""
def create_virtual_env(self) -> None:
"""Create the virtual environment."""
@property
def virtual_env_path(self) -> Path:
"""Path to virtual environment directory."""
class VirtualEnvRunner:
"""Runner for virtual environment operations."""
def create(self, base_python: str, path: Path) -> None:
"""
Create virtual environment.
Args:
base_python: Base Python interpreter
path: Target path for virtual environment
"""Different categories of environments supported by tox.
class RunToxEnv(ToxEnv):
"""Environment for running commands."""
def run_commands(self, commands: list[str]) -> ExecuteStatus:
"""
Run sequence of commands.
Args:
commands: Commands to execute
Returns:
ExecuteStatus: Combined execution status
"""
class PackageToxEnv(ToxEnv):
"""Environment for packaging operations."""
def build_package(self) -> Path:
"""
Build package in this environment.
Returns:
Path: Path to built package
"""System for registering and discovering environment types.
class ToxEnvInfo:
"""Information about an environment type."""
def __init__(self, name: str, description: str, factory: type) -> None:
"""
Initialize environment info.
Args:
name: Environment type name
description: Human-readable description
factory: Environment class factory
"""
@property
def name(self) -> str:
"""Environment type name."""
@property
def description(self) -> str:
"""Environment description."""
# Global environment registry
REGISTER: dict[str, ToxEnvInfo]System for managing package installation and dependencies within environments.
class PipInstall:
"""Pip installation handler for Python environments."""
def __init__(self, env: PythonToxEnv) -> None:
"""
Initialize pip installer.
Args:
env: Python environment
"""
def install(self, packages: list[str]) -> ExecuteStatus:
"""
Install packages via pip.
Args:
packages: Package specifications to install
Returns:
ExecuteStatus: Installation result
"""
def install_requirements(self, req_file: Path) -> ExecuteStatus:
"""
Install from requirements file.
Args:
req_file: Path to requirements file
Returns:
ExecuteStatus: Installation result
"""
class RequirementsFile:
"""Handler for requirements files."""
def __init__(self, path: Path) -> None:
"""
Initialize requirements file handler.
Args:
path: Path to requirements file
"""
def read(self) -> list[str]:
"""
Read requirements from file.
Returns:
list[str]: List of requirement specifications
"""Key configuration options that control environment behavior:
# Example environment configuration
[testenv:py311]
basepython = python3.11
deps =
pytest>=6.0
pytest-cov>=2.0
requests
commands =
pytest {posargs}
coverage report
changedir = {toxinidir}/tests
passenv =
HOME
USER
CI
setenv =
PYTHONPATH = {toxinidir}/src
COVERAGE_FILE = {envtmpdir}/.coverageControl environment behavior through variables:
basepython: Python interpreter to usedeps: Dependencies to installcommands: Commands to executecommands_pre: Pre-execution commandscommands_post: Post-execution commandschangedir: Working directorypassenv: Environment variables to inheritsetenv: Environment variables to setinstall_command: Custom install commandallowlist_externals: Allowed external commandsControl points in the environment lifecycle:
# Pre/post command hooks
[testenv]
commands_pre =
python --version
pip list
commands = pytest {posargs}
commands_post =
coverage html
echo "Tests completed"Create custom environment types by extending the base classes:
from tox.tox_env.api import ToxEnv
from tox.plugin import impl
class CustomToxEnv(ToxEnv):
"""Custom environment implementation."""
def create(self) -> None:
"""Custom environment creation."""
print(f"Creating custom environment: {self.name}")
def setup(self) -> None:
"""Custom environment setup."""
print(f"Setting up custom environment: {self.name}")
def execute(self, request):
"""Custom command execution."""
print(f"Executing in {self.name}: {request.cmd}")
# Custom execution logic
return ExecuteStatus(0, "", "")
@impl
def tox_register_tox_env(register):
"""Register custom environment type."""
register.add_env_type(
name="custom",
factory=CustomToxEnv,
description="Custom environment type"
)Environments can be selected through various mechanisms:
# Run specific environments
tox -e py311,py312
# Run all environments
tox
# Run environments matching pattern
tox -e py3{11,12}[tox]
envlist = py311,py312,docs,lint
# Conditional environments
[testenv:docs]
deps = sphinx
commands = sphinx-build docs docs/_build
[testenv:lint]
deps = flake8
commands = flake8 src/from tox.session.state import State
# Select specific environments
state = setup_state(['-e', 'py311,docs'])
# Get selected environments
selected = state.envs.all()
for name, env in selected.items():
print(f"Selected: {name}")Environment system includes specific error handling:
class ToxEnvError(Exception):
"""Base environment error."""
class SkipEnvironment(Exception):
"""Skip this environment."""
class FailEnvironment(Exception):
"""Mark environment as failed."""Usage in custom environments:
def setup(self) -> None:
if not self.python_executable().exists():
raise SkipEnvironment(f"Python not found: {self.base_python}")
try:
self.install_deps()
except Exception as e:
raise FailEnvironment(f"Dependency installation failed: {e}")Tox provides strong isolation between environments:
This isolation ensures that environments don't interfere with each other and provides reproducible testing conditions.
Install with Tessl CLI
npx tessl i tessl/pypi-tox