tox plugins

New in version 2.0.

A growing number of hooks make tox modifiable in different phases of execution by writing plugins.

tox - like pytest and devpi - uses pluggy to provide an extension mechanism for pip-installable internal or devpi/PyPi-published plugins.

Using plugins

To start using a plugin you need to install it in the same environment where the tox host is installed.

e.g.:

$ pip install tox-travis

You can search for available plugins on PyPi by typing pip search tox and filter for packages that are prefixed tox- or contain the “plugin” in the description. You will get some output similar to this:

tox-pipenv (1.4.1)                   - A pipenv plugin for tox
tox-pyenv (1.1.0)                    - tox plugin that makes tox use `pyenv which` to find
                                       python executables
tox-globinterpreter (0.3)            - tox plugin to allow specification of interpreter
                                       locationspaths to use
tox-venv (0.2.0)                     - Use python3 venvs for python3 tox testenvs
tox-cmake (0.1.1)                    - Build CMake projects using Tox
tox-travis (0.10)                    - Seamless integration of Tox into Travis CI
tox-py-backwards (0.1)               - tox plugin for py-backwards
tox-pytest-summary (0.1.2)           - Tox + Py.test summary
tox-envreport (0.2.0)                - A tox-plugin to document the setup of used virtual
                                       environments.
tox-no-internet (0.1.0)              - Workarounds for using tox with no internet connection
tox-virtualenv-no-download (1.0.2)   - Disable virtualenv's download-by-default in tox
tox-run-command (0.4)                - tox plugin to run arbitrary commands in a virtualenv
tox-pip-extensions (1.2.1)           - Augment tox with different installation methods via
                                       progressive enhancement.
tox-run-before (0.1)                 - Tox plugin to run shell commands before the test
                                       environments are created.
tox-docker (1.0.0)                   - Launch a docker instance around test runs
tox-bitbucket-status (1.0)           - Update bitbucket status for each env
tox-pipenv-install (1.0.3)           - Install packages from Pipfile

There might also be some plugins not (yet) available from PyPi that could be installed directly fom source hosters like Github or Bitbucket (or from a local clone). See the

To see what is installed you can call tox --version to get the version of the host and names and locations of all installed plugins:

3.0.0 imported from /home/ob/.virtualenvs/tmp/lib/python3.6/site-packages/tox/__init__.py
registered plugins:
    tox-travis-0.10 at /home/ob/.virtualenvs/tmp/lib/python3.6/site-packages/tox_travis/hooks.py
    detox-0.12 at /home/ob/.virtualenvs/tmp/lib/python3.6/site-packages/detox/tox_proclimit.py

Creating a plugin

Start from a template

You can create a new tox plugin with all the bells and whistles via a Cookiecutter template (see cookiecutter-tox-plugin - this will create a complete pypi-releasable, documented project with license, documentation and CI.

$ pip install -U cookiecutter
$ cookiecutter gh:tox-dev/cookiecutter-tox-plugin

Tutorial: a minimal tox plugin

Note

This is the minimal implementation to demonstrate what is absolutely necessary to have a working plugin for internal use. To move from something like this to a publishable plugin you could apply cookiecutter -f cookiecutter-tox-plugin and adapt the code to the package based structure used in the cookiecutter.

Let us consider you want to extend tox behaviour by displaying fireworks at the end of a successful tox run (we won’t go into the details of how to display fireworks though).

To create a working plugin you need at least a python project with a tox entry point and a python module implementing one or more of the pluggy based hooks tox specifies (using the @tox.hookimpl decorator as marker).

minimal structure:

$ mkdir tox-fireworks
$ cd tox-fireworks
$ touch tox_fireworks.py
$ touch setup.py

contents of tox_fireworks.py:

import pluggy

hookimpl = pluggy.HookimplMarker("tox")

@hookimpl
def tox_addoption(parser):
    """Add command line option to display fireworks on request."""

@hookimpl
def tox_configure(config):
    """Post process config after parsing."""

@hookimpl
def tox_runenvreport(config):
    """Display fireworks if all was fine and requested."""

contents of setup.py:

from setuptools import setup

setup(name='tox-fireworks', py_modules=['tox_fireworks'],
      entry_points={'tox': ['fireworks = tox_fireworks']}
      classifiers=['Framework:: tox'])

Using the tox- prefix in tox-fireworks is an established convention to be able to see from the project name that this is a plugin for tox. It also makes it easier to find with e.g. pip search 'tox-' once it is released on PyPi.

To make your new plugin discoverable by tox, you need to install it. During development you should install it with -e or --editable, so that changes to the code are immediately active:

$ pip install -e </path/to/tox-fireworks>

Publish your plugin to PyPi

If you think the rest of the world could profit using your plugin you can publish it to PyPi.

You need to add some more meta data to setup.py (see cookiecutter-tox-plugin for a complete example or consult the setup.py docs).

Note

Make sure your plugin project name is prefixed by tox- to be easy to find via e.g. pip search tox-

You can and publish it like:

$ cd </path/to/tox-fireworks>
$ python setup.py sdist bdist_wheel upload

Note

You could also use twine for secure uploads.

For more information about packaging and deploying Python projects see the Python Packaging Guide.

Hook specifications and related API

Hook specifications for tox - see https://pluggy.readthedocs.io/

tox.hookspecs.tox_addoption(parser)[source]

add command line options to the argparse-style parser object.

tox.hookspecs.tox_configure(config)[source]

Called after command line options are parsed and ini-file has been read.

Please be aware that the config object layout may change between major tox versions.

tox.hookspecs.tox_get_python_executable(envconfig)[source]

Return a python executable for the given python base name.

The first plugin/hook which returns an executable path will determine it.

envconfig is the testenv configuration which contains per-testenv configuration, notably the .envname and .basepython setting.

tox.hookspecs.tox_runenvreport(venv, action)[source]

Get the installed packages and versions in this venv.

This could be used for alternative (ie non-pip) package managers, this plugin should return a list of type str

tox.hookspecs.tox_runtest(venv, redirect)[source]

Run the tests for this venv.

Note

This hook uses firstresult=True (see pluggy first result only) – hooks implementing this will be run until one returns non-None.

tox.hookspecs.tox_runtest_post(venv)[source]

Perform arbitrary action after running tests for this venv.

This could be used to have per-venv test reporting of pass/fail status.

tox.hookspecs.tox_runtest_pre(venv)[source]

Perform arbitrary action before running tests for this venv.

This could be used to indicate that tests for a given venv have started, for instance.

tox.hookspecs.tox_testenv_create(venv, action)[source]

Perform creation action for this venv.

Some example usage:

  • To add behavior but still use tox’s implementation to set up a virtualenv, implement this hook but do not return a value (or explicitly return None).
  • To override tox’s virtualenv creation, implement this hook and return a non-None value.

Note

This api is experimental due to the unstable api of tox.venv.VirtualEnv.

Note

This hook uses firstresult=True (see pluggy first result only) – hooks implementing this will be run until one returns non-None.

tox.hookspecs.tox_testenv_install_deps(venv, action)[source]

Perform install dependencies action for this venv.

Some example usage:

  • To add behavior but still use tox’s implementation to install dependencies, implement this hook but do not return a value (or explicitly return None). One use-case may be to install (or ensure) non-python dependencies such as debian packages.
  • To override tox’s installation of dependencies, implement this hook and return a non-None value. One use-case may be to install via a different installation tool such as pip-accel or pip-faster.

Note

This api is experimental due to the unstable api of tox.venv.VirtualEnv.

Note

This hook uses firstresult=True (see pluggy first result only) – hooks implementing this will be run until one returns non-None.

class tox.config.Parser[source]

Command line and ini-parser control object.

add_argument(*args, **kwargs)[source]

add argument to command line parser. This takes the same arguments that argparse.ArgumentParser.add_argument.

add_testenv_attribute(name, type, help, default=None, postprocess=None)[source]

add an ini-file variable for “testenv” section.

Types are specified as strings like “bool”, “line-list”, “string”, “argv”, “path”, “argvlist”.

The postprocess function will be called for each testenv like postprocess(testenv_config=testenv_config, value=value) where value is the value as read from the ini (or the default value) and testenv_config is a tox.config.TestenvConfig instance which will receive all ini-variables as object attributes.

Any postprocess function must return a value which will then be set as the final value in the testenv section.

add_testenv_attribute_obj(obj)[source]

add an ini-file variable as an object.

This works as the add_testenv_attribute function but expects “name”, “type”, “help”, and “postprocess” attributes on the object.

class tox.config.Config[source]

Global Tox config object.

envconfigs = None

Mapping envname -> envconfig

option = None

option namespace containing all parsed command line options

class tox.config.TestenvConfig[source]

Testenv Configuration object.

In addition to some core attributes/properties this config object holds all per-testenv ini attributes as attributes, see “tox –help-ini” for an overview.

config = None

global tox config object

envname = None

test environment name

envpython

Path to python executable.

factors = None

set of factors

get_envbindir()[source]

Path to directory where scripts/binaries reside.

get_envpython()[source]

path to python/jython executable.

get_envsitepackagesdir()[source]

Return sitepackagesdir of the virtualenv environment.

NOTE: Only available during execution, not during parsing.

missing_subs = None

Holds substitutions that could not be resolved.

Pre 2.8.1 missing substitutions crashed with a ConfigError although this would not be a problem if the env is not part of the current testrun. So we need to remember this and check later when the testenv is actually run and crash only then.

python_info

Return sitepackagesdir of the virtualenv environment.

class tox.venv.VirtualEnv[source]
getcommandpath(name, venv=True, cwd=None)[source]

Return absolute path (str or localpath) for specified command name.

  • If it’s a local path we will rewrite it as as a relative path.
  • If venv is True we will check if the command is coming from the venv or is whitelisted to come from external.
name

test environment name.

path

Path to environment base dir.

update(action)[source]

return status string for updating actual venv to match configuration. if status string is empty, all is ok.

class tox.session.Session[source]

The session object that ties together configuration, reporting, venv creation, testing.

get_installpkg_path()[source]
Returns:Path to the distribution
Return type:py.path.local
getvenv(name)[source]

return a VirtualEnv controler object for the ‘name’ env.

installpkg(venv, path)[source]

Install package in the specified virtual environment.

Parameters:
  • venv (VenvConfig) – Destination environment
  • path (str) – Path to the distribution package.
Returns:

True if package installed otherwise False.

Return type:

bool

runenvreport(venv)[source]

Run an environment report to show which package versions are installed in the venv