Extending tox

Extensions points

tox uses pluggy to customize the default behavior. It provides an extension mechanism for plugin management by calling hooks.

Pluggy discovers a plugin by looking up for entry-points named tox, for example in a pyproject.toml:

[project.entry-points.tox]
your_plugin = "your_plugin.hooks"

Therefore, to start using a plugin, you solely need to install it in the same environment tox is running in and it will be discovered via the defined entry-point (in the example above, tox will load your_plugin.hooks).

A plugin is created by implementing extension points in the form of hooks. For example the following code snippet would define a new --magic command line interface flag the user can specify:

from tox.config.cli.parser import ToxParser
from tox.plugin import impl


@impl
def tox_add_option(parser: ToxParser) -> None:
    parser.add_argument("--magic", action="store_true", help="magical flag")

You can define such hooks either in a package installed alongside tox or within a toxfile.py found alongside your tox configuration file (root of your project).

tox.plugin.NAME = 'tox'

the name of the tox hook

tox.plugin.impl

decorator to mark tox plugin hooks

tox.plugin.spec.tox_add_core_config(core_conf, state)

Called when the core configuration is built for a tox environment.

Parameters:
  • core_conf (ConfigSet) – the core configuration object

  • state (State) – the global tox state object

Return type:

None

tox.plugin.spec.tox_add_env_config(env_conf, state)

Called when configuration is built for a tox environment.

Parameters:
  • env_conf (EnvConfigSet) – the core configuration object

  • state (State) – the global tox state object

Return type:

None

tox.plugin.spec.tox_add_option(parser)

Add a command line argument. This is the first hook to be called, right after the logging setup and config source discovery.

Parameters:

parser (ToxParser) – the command line parser

Return type:

None

tox.plugin.spec.tox_after_run_commands(tox_env, exit_code, outcomes)

Called after the commands set is executed.

Parameters:
  • tox_env (ToxEnv) – the tox environment being executed

  • exit_code (int) – exit code of the command

  • outcomes (list[Outcome]) – outcome of each command execution

Return type:

None

tox.plugin.spec.tox_before_run_commands(tox_env)

Called before the commands set is executed.

Parameters:

tox_env (ToxEnv) – the tox environment being executed

Return type:

None

tox.plugin.spec.tox_env_teardown(tox_env)

Called after a tox environment has been teared down.

Parameters:

tox_env (ToxEnv) – the tox environment

Return type:

None

tox.plugin.spec.tox_on_install(tox_env, arguments, section, of_type)

Called before executing an installation command.

Parameters:
  • tox_env (ToxEnv) – the tox environment where the command runs in

  • arguments (Any) – installation arguments

  • section (str) – section of the installation

  • of_type (str) – type of the installation

Return type:

None

tox.plugin.spec.tox_register_tox_env(register)

Register new tox environment type. You can register:

  • run environment: by default this is a local subprocess backed virtualenv Python

  • packaging environment: by default this is a PEP-517 compliant local subprocess backed virtualenv Python

Parameters:

register (ToxEnvRegister) – a object that can be used to register new tox environment types

Return type:

None

A plugin can define its plugin module a:

def tox_append_version_info() -> str:
    return "magic"

and this message will be appended to the output of the --version flag.

Adoption of a plugin under tox-dev Github organization

You’re free to host your plugin on your favorite platform, however the core tox development is happening on Github, under the tox-dev org organization. We are happy to adopt tox plugins under the tox-dev organization if:

  • we determine it’s trying to solve a valid use case and it’s not malicious (e.g. no plugin that deletes the users home directory),

  • it’s released on PyPI with at least 100 downloads per month (to ensure it’s a plugin used by people).

What’s in for you in this:

  • you get owner rights on the repository under the tox-dev organization,

  • exposure of your plugin under the core umbrella,

  • backup maintainers from other tox plugin development.

How to apply:

Migration from tox 3

This section explains how the plugin interface changed between tox 3 and 4, and provides guidance for plugin developers on how to migrate.

tox_get_python_executable

With tox 4 the Python discovery is performed tox.tox_env.python.virtual_env.api._get_python that delegates the job to virtualenv. Therefore first define a new virtualenv discovery mechanism and then set that by setting the VIRTUALENV_DISCOVERY environment variable.

tox_package

Register new packager types via tox_register_tox_env.

tox_addoption

Renamed to tox_add_option.