CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-tox

tox is a generic virtualenv management and test command line tool

Overview
Eval results
Files

plugin-system.mddocs/

Plugin System

Hook-based extensibility system using pluggy that allows plugins to extend CLI options, configuration, environment types, and execution hooks. Tox's plugin system supports both entry-point plugins and toxfile.py plugins for maximum flexibility.

Capabilities

Plugin Hook Decorator

The core decorator for marking plugin hook implementations.

impl: Callable[[_F], _F]
"""
Decorator to mark tox plugin hooks.

Usage:
    @impl
    def hook_function(...): ...
"""

NAME: str = "tox"
"""The name of the tox hook system."""

Usage example:

from tox.plugin import impl

@impl
def tox_add_option(parser):
    parser.add_argument("--my-option", help="Custom option")

Hook Specifications

The complete set of hooks available for plugin development.

class ToxHookSpecs:
    """Hook specification definitions for tox plugins."""
    
    def tox_add_option(self, parser: ToxParser) -> None:
        """
        Add command line options.
        
        Args:
            parser: Command line parser to extend
        """
    
    def tox_add_core_config(self, core_conf: CoreConfigSet) -> None:
        """
        Add core configuration options.
        
        Args:
            core_conf: Core configuration set to extend
        """
    
    def tox_add_env_config(self, env_conf: EnvConfigSet) -> None:
        """
        Add environment-specific configuration options.
        
        Args:
            env_conf: Environment configuration set to extend
        """
    
    def tox_register_tox_env(self, register) -> None:
        """
        Register new environment types.
        
        Args:
            register: Environment registry to extend
        """
    
    def tox_extend_envs(self) -> list[str]:
        """
        Extend the list of available environments.
        
        Returns:
            list[str]: Additional environment names
        """
    
    def tox_before_run_commands(self, tox_env: ToxEnv, run_conf, opts) -> None:
        """
        Hook called before running commands in environment.
        
        Args:
            tox_env: Environment where commands will run
            run_conf: Run configuration
            opts: Additional options
        """
    
    def tox_after_run_commands(self, tox_env: ToxEnv, run_conf, opts, outcome: Outcome) -> None:
        """
        Hook called after running commands in environment.
        
        Args:
            tox_env: Environment where commands ran
            run_conf: Run configuration
            opts: Additional options
            outcome: Execution outcome
        """

Plugin Manager

The plugin manager coordinates plugin discovery and hook execution.

MANAGER: PluginManager
"""Global plugin manager instance."""

Plugin Development

Basic Plugin Structure

Create a plugin by implementing hook functions:

# my_tox_plugin.py
from tox.plugin import impl
from tox.config.cli.parser import ToxParser

@impl
def tox_add_option(parser: ToxParser) -> None:
    """Add custom CLI option."""
    parser.add_argument(
        "--coverage-report", 
        action="store_true",
        help="Generate coverage report after tests"
    )

@impl
def tox_add_core_config(core_conf) -> None:
    """Add core configuration option."""
    core_conf.add_config(
        keys="coverage_threshold",
        desc="Minimum coverage threshold",
        of_type=float,
        default=80.0
    )

@impl
def tox_after_run_commands(tox_env, run_conf, opts, outcome) -> None:
    """Generate coverage report if requested."""
    if getattr(opts, 'coverage_report', False):
        print(f"Generating coverage report for {tox_env.name}")
        # Coverage report generation logic

Environment Type Plugins

Register custom environment types:

from tox.plugin import impl
from tox.tox_env.api import ToxEnv

class DockerToxEnv(ToxEnv):
    """Docker-based tox environment."""
    
    def create(self) -> None:
        """Create Docker container."""
        print(f"Creating Docker container for {self.name}")
        
    def execute(self, request):
        """Execute command in Docker container."""
        # Docker execution logic
        return ExecuteStatus(0, "success", "")

@impl
def tox_register_tox_env(register) -> None:
    """Register Docker environment type."""
    register.add_env_type(
        name="docker",
        factory=DockerToxEnv,
        description="Docker container environment"
    )

Configuration Extension

Extend tox configuration with plugin-specific options:

@impl
def tox_add_env_config(env_conf) -> None:
    """Add environment configuration options."""
    env_conf.add_config(
        keys="docker_image",
        desc="Docker image to use",
        of_type=str,
        default="python:3.11"
    )
    
    env_conf.add_config(
        keys="docker_volumes",
        desc="Docker volumes to mount",
        of_type=list,
        default=[]
    )

Plugin Discovery

Entry Point Plugins

Register plugins via setuptools entry points:

# setup.py or pyproject.toml
[project.entry-points.tox]
my_plugin = "my_tox_plugin"
docker_plugin = "tox_docker.plugin"

Toxfile Plugins

Create toxfile.py in your project root:

# toxfile.py
from tox.plugin import impl

@impl
def tox_add_option(parser):
    """Project-specific plugin hook."""
    parser.add_argument("--project-flag", help="Project specific option")

Advanced Plugin Patterns

Multi-Hook Plugins

Plugins can implement multiple hooks:

from tox.plugin import impl

class MyToxPlugin:
    """Comprehensive tox plugin."""
    
    @impl
    def tox_add_option(self, parser):
        """Add CLI options."""
        parser.add_argument("--verbose-timing", action="store_true")
    
    @impl  
    def tox_before_run_commands(self, tox_env, run_conf, opts):
        """Pre-execution hook."""
        if getattr(opts, 'verbose_timing', False):
            print(f"Starting {tox_env.name} at {time.time()}")
    
    @impl
    def tox_after_run_commands(self, tox_env, run_conf, opts, outcome):
        """Post-execution hook.""" 
        if getattr(opts, 'verbose_timing', False):
            print(f"Finished {tox_env.name} at {time.time()}")

# Register plugin instance
plugin = MyToxPlugin()

Conditional Plugin Behavior

Implement conditional logic in plugins:

@impl
def tox_before_run_commands(tox_env, run_conf, opts):
    """Conditional pre-execution logic."""
    
    # Only run for Python environments
    if hasattr(tox_env, 'python_executable'):
        print(f"Python environment: {tox_env.name}")
        
    # Only run in CI environment
    if os.getenv('CI'):
        print("Running in CI environment")
        
    # Environment-specific logic
    if tox_env.name.startswith('py3'):
        print("Python 3 environment detected")

Plugin Configuration

Plugins can define their own configuration:

@impl
def tox_add_core_config(core_conf):
    """Add plugin configuration."""
    core_conf.add_config(
        keys="my_plugin_enabled",
        desc="Enable my plugin functionality", 
        of_type=bool,
        default=True
    )

@impl
def tox_before_run_commands(tox_env, run_conf, opts):
    """Check plugin configuration."""
    if tox_env.core["my_plugin_enabled"]:
        print("Plugin is enabled")
    else:
        print("Plugin is disabled")

Plugin Testing

Test plugins using tox's testing utilities:

# test_my_plugin.py
import pytest
from tox.plugin import impl
from tox.run import main

def test_plugin_option():
    """Test custom CLI option."""
    result = main(['--my-option', '--help'])
    # Assert option is present in help output

def test_plugin_environment():
    """Test custom environment type."""
    result = main(['-e', 'docker'])  
    # Assert Docker environment runs correctly

Plugin Error Handling

Handle errors gracefully in plugins:

@impl
def tox_register_tox_env(register):
    """Register with error handling."""
    try:
        # Check if Docker is available
        import docker
        register.add_env_type(
            name="docker",
            factory=DockerToxEnv, 
            description="Docker environment"
        )
    except ImportError:
        print("Docker not available, skipping Docker environment")

Built-in Plugin Examples

Tox includes several built-in plugins that demonstrate best practices:

  • Virtual environment plugin: Creates Python virtual environments
  • Pip plugin: Handles package installation via pip
  • Configuration plugins: Extend configuration options
  • Reporting plugins: Handle output formatting and logging

These serve as reference implementations for developing custom plugins with similar functionality.

Install with Tessl CLI

npx tessl i tessl/pypi-tox

docs

cli-interface.md

configuration.md

environment-system.md

execution-system.md

index.md

plugin-system.md

session-management.md

tile.json