Version 4 is mostly backwards compatible. This document covers all breaking changes and, where applicable, includes guidance on how to update.
See also the list of new features in the FAQ <faq>
.
- tox now requires Python
3.7
or later and is tested only against CPython. You can still create test environments for earlier Python versions or different Python interpreters. PyPy support is best effort, meaning we do not test it as part of our CI runs, however if you discover issues under PyPy we will accept PRs addressing it.
The hash sign (
#
) now always acts as comment withintox.ini
orsetup.cfg
tox configuration file. Where you need to pass on a#
character you will need to escape it in form of\#
so tox does not handle everything right of the#
character as a comment. Valid in tox 3:# valid in tox 3 commands = bash -c "echo 'foo#bar'" # valid in tox 4 commands = bash -c "echo 'foo\#bar'"
Within the
pass_env
you can no longer use space as value separator, instead you need to use the,
or the newline character. This is to have the same value separation rules for all tox configuration lines.# valid in tox 3 passenv = ALPHA BETA passenv = ALPHA BETA # valid in tox 4 passenv = ALPHA, BETA passenv = ALPHA BETA
- tox 4 now errors when using the
-U
flag when defining dependencies, e.g.deps = -Ur requirements.txt
. While this worked in tox 3, it was never supported officially. Additionally, in the context of a new virtual environment this flag makes no sense anyway. - tox 4 requires the
install_command
to evaluate to a non-empty value for each target environment. In tox 3, an empty value would be substituted for the default install command.
- With tox 4 the tty trait of the caller environment is no longer passed through. The most notable impact of this is that some tools no longer print colored output. A PR to address this is welcomed, in the meantime you can use the
tty
substitution to force color mode for these tools, see for example tox itself with pytest and mypy here in tox.ini.
tox 4 is a grounds up rewrite of the code base, and while we kept the configuration layer compatibility no such effort has been made for the programmatic API. Therefore, all plugins will need to redo their integration against the new code base. If you're a plugin developer refer to the plugin documentation for more information.
Configuration key | Migration path |
---|---|
indexserver |
See Using a custom PyPI server <faq_custom_pypi_server> . |
whitelist_externals |
Use allowlist_externals key instead. |
isolated_build |
Isolated builds are now always used. |
distdir |
Use the TOX_PACKAGE environment variable. |
The base python configuration is no longer resolved to pythonx.y
format, instead is kept as py39
, and is the virtualenv project that handles mapping that to a Python interpreter. If you were using this variable we recommend moving to the newly added py_impl
and py_dot_ver
variables, for example:
deps = -r{py_impl}{py_dot_ver}-req.txt
- The
distshare
substitution has been removed.
- Environment names that contain multiple Python variants, such as
name-py39-pypy
orpy39-py310
will now raise an error, previously this only warned, you can useignore_basepython_conflict
to disable this error, but we recommend changing the name to avoid this name that can be confusing.
- The
--parallel--safe-build
CLI argument has been removed, no longer needed. - When you want to pass an option to a test command, e.g. to
pytest
, now you must use--
as a separator, this worked with version 3 also, but any unknown trailing arguments were automatically passed through, while now this is no longer the case. - Running
--showconfig
or--help-ini
with the-v
flag will add interleaved debugging information, whereas tox 3 added additional lines at the start. If you want to generate valid ini files you must not use the-v
flag. - The
--index-url
is now removed, usePIP_INDEX_URL
inset_env
instead.
- We use isolated builds (always) as specified by
518
and use517
to communicate with the build backend. - The
--develop
CLI flag or theuse_develop
settings now enables editable installations via the660
mechanism rather than the legacypip install -e
behaviour. The old functionality can still be forced by setting thepackage
setting for the run environment toeditable-legacy
.
- We now use colors for reporting, to help make the output easier to read for humans. This can be disabled via the
TERM=dumb
orNO_COLOR=1
environment variables, or the--colored no
CLI argument.
- It is no longer possible to re-use environments. While this might have been possible with tox version 3, this behavior was never supported, and possibly caused wrong results as illustrated in the following example.
[testenv]
envdir = .tox/venv
[testenv:a]
deps = pytest>7
[testenv:b]
deps = pytest<7
tox
4 introduced dedicated subcommands for various usages. However, when no subcommand is given the legacy entry point which imitates tox
3 is used.
This compatibility feature makes most tox
3 commands work in tox
4, but there are some exceptions.
In tox
3, environments could be specified to run with the -e
flag. In tox
4, environments should always be specified using the -e
flag to the run
subcommand.
Rewrite usages as follows
# tox 3
tox -e py310,style
# tox 4
tox run -e py310,style
# or, tox 4 with the short alias
tox r -e py310,style
Now that tox
has subcommands, it is possible for arguments to tox
or its options to match those subcommand names. When that happens, parsing can become ambiguous between the tox
4 usage and the legacy fallback behavior.
For example, consider the following tox config:
[tox]
env_list = py39,py310
[testenv]
commands =
python -c 'print("hi")'
[testenv:list]
commands =
python -c 'print("a, b, c")'
This defines an environment whose name matches a tox
4 command, list
.
Under tox
3, tox -e list
specified the list
environment. However, under tox
4, the parse of this usage as an invocation of tox list
takes precedence over the legacy behavior.
Therefore, attempting that same usage results in an error:
$ tox -e list
...
tox: error: unrecognized arguments: -e
This is best avoided by updating to non-legacy usage:
$ tox run -e list
# or, equivalently...
$ tox r -e list