Today I came across an older project of mine that uses tox, but since many years I'm configuring tox environments in a different way. So I decided to update the tox configuration of this project to my current knowledge.
In earlier years I specified the dependencies and their installation for my tox environments using two approaches. The first was to use the install_command
option:
[testenv]
install_command = pip install -e '.[development]' -U {opts} {packages}
commands = pytest
Ini
It works perfectly fine and there is no need to explicitly specify the dependencies as they are already specified in setup.py
:
development_extras = [
'flake8>=6.0,<7.0',
'pytest>=7.0,<8.0',
'tox>=3.28,<4.0',
]
setup(
...
extras_require={
'development': development_extras,
},
...
)
Python
But for some environments in larger projects, often linting stages like flake8
or isort
, it was expensive to install all dependencies though they were not necessary. So I decided to specify the dependencies explicitly as deps
, as you can see in the [testenv:flake8]
section:
[testenv:flake8]
deps = flake8>=6.0,<7.0
commands = flake8 src
Ini
This is redundant because the dependencies are already specified in setup.py
. As soon as the required version of a dependency changes, I had to update it in two places. Everything a human has to remember is a potential source of error.
So I decided to simplify the tox environment dependency specification by using the extras
parameter of the deps
option. And this works for both ways of specifying the dependencies. First I split the dependencies within setup.py
into more specific parts:
linting_extras = [
'flake8>=6.0,<7.0',
]
testing_extras = [
'pytest>=7.0,<8.0',
'tox>=3.28,<4.0',
]
development_extras = linting_extras + testing_extras
setup(
...
extras_require={
'development': development_extras,
'linting': linting_extras,
'testing': testing_extras,
},
...
)
Python
Then I can use the extras
parameter to specify the dependencies:
[testenv]
extras = testing
commands = pytest
[testenv:flake8]
extras = linting
commands = flake8 src
Ini
This way I can specify the dependencies in one place and have only one alternative so tox will install the correct dependencies for each environment. It makes the tox configuration clearly more readable and stable.