Skip to content

Commit 2d10355

Browse files
committed
📝 Simplify tox’s version range syntax
1 parent e25d599 commit 2d10355

File tree

1 file changed

+129
-86
lines changed

1 file changed

+129
-86
lines changed

docs/test/tox.rst

Lines changed: 129 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ This is a typical layout for many projects. Let’s take a look at a simple
6666
6767
[tox]
6868
envlist = py313
69-
isolated_build = True
7069
7170
[testenv]
7271
deps =
@@ -79,11 +78,6 @@ shortcut that tells tox to run our tests with Python version 3.13. We will be
7978
adding more Python versions shortly, but using one version helps to understand
8079
the flow of tox.
8180

82-
Also note the line ``isolated_build = True``: This is required for all packages
83-
configured with :file:`pyproject.toml`. However, for all projects configured
84-
with :file:`setup.py` that use the :term:`setuptools` library, this line can be
85-
omitted.
86-
8781
In the ``[testenv]`` section, ``pytest`` and ``faker`` are listed as
8882
dependencies under ``deps``. So tox knows that we need these two tools for
8983
testing. If you wish, you can also specify which version should be used, for
@@ -112,15 +106,20 @@ To run tox, simply start tox:
112106
.. code-block:: pytest
113107
114108
$ uv run tox
115-
py313: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/57/items-0.1.0.tar.gz
109+
.pkg: _optional_hooks> python /Users/veit/cusy/prj/items/.venv/lib/python3.13/site-packages/pyproject_api/_backend.py True hatchling.build
110+
.pkg: get_requires_for_build_sdist> python /Users/veit/cusy/prj/items/.venv/lib/python3.13/site-packages/pyproject_api/_backend.py True hatchling.build
111+
.pkg: build_sdist> python /Users/veit/cusy/prj/items/.venv/lib/python3.13/site-packages/pyproject_api/_backend.py True hatchling.build
112+
py313: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/18/items-0.1.0.tar.gz
116113
py313: commands[0]> python --version --version
114+
Python 3.13.0 (main, Oct 7 2024, 23:47:22) [Clang 18.1.8 ]
115+
py313: commands[1]> coverage run -m pytest
117116
============================= test session starts ==============================
118-
platform darwin -- Python 3.13.0, pytest-8.4.1, pluggy-1.6.0
117+
platform darwin -- Python 3.13.0, pytest-9.0.2, pluggy-1.6.0
119118
cachedir: .tox/py313/.pytest_cache
120119
rootdir: /Users/veit/cusy/prj/items
121120
configfile: pyproject.toml
122121
testpaths: tests
123-
plugins: anyio-4.9.0, Faker-37.4.0, cov-6.2.1
122+
plugins: Faker-40.1.0, cov-7.0.0
124123
collected 83 items
125124
126125
tests/api/test_add.py ...... [ 7%]
@@ -149,8 +148,10 @@ To run tox, simply start tox:
149148
tests/cli/test_update.py . [ 98%]
150149
tests/cli/test_version.py . [100%]
151150
152-
============================== 83 passed in 0.27s ==============================
153-
py313: OK ✔ in 1.17 seconds
151+
============================== 83 passed in 0.35s ==============================
152+
.pkg: _exit> python /Users/veit/cusy/prj/items/.venv/lib/python3.13/site-packages/pyproject_api/_backend.py True hatchling.build
153+
py313: OK (1.19=setup[0.45]+cmd[0.01,0.72] seconds)
154+
congratulations :) (1.23 seconds)
154155
155156
Testing multiple Python versions
156157
--------------------------------
@@ -162,55 +163,96 @@ Python versions:
162163
:emphasize-lines: 2, 4
163164
164165
[tox]
165-
envlist = py3{9,10,11,12,13,13t,14,14t}
166-
isolated_build = True
166+
envlist =
167+
py3{10-14}
168+
py3{13-14}t
167169
skip_missing_interpreters = True
168170
169-
We will now test Python versions from 3.8 to 3.11. In addition, we have also
171+
We will now test Python versions from 3.10 to 3.14. In addition, we have also
170172
added the setting ``skip_missing_interpreters = True`` so that tox does not fail
171173
if one of the listed Python versions is missing on your system. If the value is
172174
set to ``True``, tox will run the tests with every available Python version, but
173175
will skip versions it doesn’t find without failing. The output is very similar,
174176
although I will only highlight the differences in the following illustration:
175177

176178
.. code-block:: pytest
177-
:emphasize-lines: 3-4, 8-12, 16-20, 24-28, 32-
178-
179-
$ uv run tox
180-
...
181-
py39: install_package> python -I -m pip install --force-reinstall --no-deps /Users/veit/cusy/prj/items/.tox/.tmp/package/17/items-0.1.0.tar.gz
182-
py39: commands[0]> coverage run -m pytest
183-
============================= test session starts ==============================
184-
...
185-
============================== 49 passed in 0.16s ==============================
186-
py39: OK ✔ in 2.17 seconds
187-
py310: skipped because could not find python interpreter with spec(s): py310
188-
py310: SKIP ⚠ in 0.01 seconds
189-
py311: install_package> python -I -m pip install --force-reinstall --no-deps /Users/veit/cusy/prj/items/.tox/.tmp/package/18/items-0.1.0.tar.gz
190-
py311: commands[0]> coverage run -m pytest
191-
============================= test session starts ==============================
192-
...
193-
============================== 49 passed in 0.15s ==============================
194-
py311: OK ✔ in 1.41 seconds
195-
py312: install_package> python -I -m pip install --force-reinstall --no-deps /Users/veit/cusy/prj/items/.tox/.tmp/package/19/items-0.1.0.tar.gz
196-
py312: commands[0]> coverage run -m pytest
197-
============================= test session starts ==============================
198-
...
199-
============================== 49 passed in 0.15s ==============================
200-
py312: OK ✔ in 1.43 seconds
201-
py313: install_package> python -I -m pip install --force-reinstall --no-deps /Users/veit/cusy/prj/items/.tox/.tmp/package/20/items-0.1.0.tar.gz
202-
py313: commands[0]> coverage run -m pytest
203-
============================= test session starts ==============================
204-
...
205-
============================== 49 passed in 0.16s ==============================
206-
.pkg: _exit> python /Users/veit/cusy/prj/items/.venv/lib/python3.13/site-packages/pyproject_api/_backend.py True hatchling.build
207-
py313: OK ✔ in 1.48 seconds
208-
py39: OK (2.17=setup[1.54]+cmd[0.63] seconds)
209-
py310: SKIP (0.01 seconds)
210-
py311: OK (1.41=setup[0.81]+cmd[0.60] seconds)
211-
py312: OK (1.43=setup[0.82]+cmd[0.61] seconds)
212-
py313: OK (1.48=setup[0.82]+cmd[0.66] seconds)
213-
congratulations :) (10.46 seconds)
179+
:emphasize-lines: 3-6, 10-14, 18-22, 26-30, 34-38, 42-46, 50-54, 59-
180+
181+
$ uv run tox
182+
...
183+
py310: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/19/items-0.1.0.tar.gz
184+
py310: commands[0]> python --version --version
185+
Python 3.10.17 (main, Apr 9 2025, 03:47:39) [Clang 20.1.0 ]
186+
py310: commands[1]> coverage run -m pytest
187+
============================= test session starts ==============================
188+
...
189+
============================== 83 passed in 0.35s ==============================
190+
py310: OK ✔ in 1.3 seconds
191+
py311: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/20/items-0.1.0.tar.gz
192+
py311: commands[0]> python --version --version
193+
Python 3.11.11 (main, Feb 5 2025, 18:58:27) [Clang 19.1.6 ]
194+
py311: commands[1]> coverage run -m pytest
195+
============================= test session starts ==============================
196+
...
197+
============================== 83 passed in 0.36s ==============================
198+
py311: OK ✔ in 1.16 seconds
199+
py312: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/21/items-0.1.0.tar.gz
200+
py312: commands[0]> python --version --version
201+
Python 3.12.12 (main, Oct 14 2025, 21:38:21) [Clang 20.1.4 ]
202+
py312: commands[1]> coverage run -m pytest
203+
============================= test session starts ==============================
204+
...
205+
============================== 83 passed in 0.55s ==============================
206+
py312: OK ✔ in 1.79 seconds
207+
py313: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/22/items-0.1.0.tar.gz
208+
py313: commands[0]> python --version --version
209+
Python 3.13.0 (main, Oct 7 2024, 23:47:22) [Clang 18.1.8 ]
210+
py313: commands[1]> coverage run -m pytest
211+
============================= test session starts ==============================
212+
...
213+
============================== 83 passed in 0.35s ==============================
214+
py313: OK ✔ in 1.07 seconds
215+
py314: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/23/items-0.1.0.tar.gz
216+
py314: commands[0]> python --version --version
217+
Python 3.14.0 (main, Oct 14 2025, 21:10:22) [Clang 20.1.4 ]
218+
py314: commands[1]> coverage run -m pytest
219+
============================= test session starts ==============================
220+
...
221+
============================== 83 passed in 0.36s ==============================
222+
py314: OK ✔ in 1.28 seconds
223+
py313t: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/24/items-0.1.0.tar.gz
224+
py313t: commands[0]> python --version --version
225+
Python 3.13.0 experimental free-threading build (main, Oct 16 2024, 08:24:33) [Clang 18.1.8 ]
226+
py313t: commands[1]> coverage run -m pytest
227+
============================= test session starts ==============================
228+
...
229+
============================== 83 passed in 0.49s ==============================
230+
py313t: OK ✔ in 1.51 seconds
231+
py314t: install_package> .venv/bin/uv pip install --reinstall --no-deps items@/Users/veit/cusy/prj/items/.tox/.tmp/package/25/items-0.1.0.tar.gz
232+
py314t: commands[0]> python --version --version
233+
Python 3.14.0b4 free-threading build (main, Jul 8 2025, 21:06:49) [Clang 20.1.4 ]
234+
py314t: commands[1]> coverage run -m pytest
235+
============================= test session starts ==============================
236+
...
237+
============================== 83 passed in 0.39s ==============================
238+
.pkg: _exit> python /Users/veit/cusy/prj/items/.venv/lib/python3.13/site-packages/pyproject_api/_backend.py True hatchling.build
239+
py310: OK (1.30=setup[0.54]+cmd[0.01,0.75] seconds)
240+
py311: OK (1.16=setup[0.38]+cmd[0.01,0.76] seconds)
241+
py312: OK (1.79=setup[0.42]+cmd[0.01,1.36] seconds)
242+
py313: OK (1.07=setup[0.34]+cmd[0.01,0.71] seconds)
243+
py314: OK (1.28=setup[0.42]+cmd[0.01,0.85] seconds)
244+
py313t: OK (1.51=setup[0.44]+cmd[0.01,1.05] seconds)
245+
py314t: OK (1.34=setup[0.44]+cmd[0.01,0.89] seconds)
246+
congratulations :) (9.48 seconds)
247+
248+
.. versionchanged:: tox≥4.25.0
249+
Before tox 4.25.0 dated 27 March 2025, the versions had to be specified one
250+
by one:
251+
252+
.. code-block:: ini
253+
254+
[tox]
255+
envlist = py3{10,11,12,13,14,13t,14t}
214256
215257
Running Tox environments in parallel
216258
------------------------------------
@@ -221,17 +263,20 @@ other. It is also possible to run them in parallel with the ``-p`` option:
221263
.. code-block:: pytest
222264
223265
$ uv run tox -p
224-
py310: SKIP ⚠ in 0.09 seconds
225-
py312: OK ✔ in 2.08 seconds
226-
py313: OK ✔ in 2.18 seconds
227-
py311: OK ✔ in 2.23 seconds
228-
py39: OK ✔ in 2.91 seconds
229-
py39: OK (2.91=setup[2.17]+cmd[0.74] seconds)
230-
py310: SKIP (0.09 seconds)
231-
py311: OK (2.23=setup[1.27]+cmd[0.96] seconds)
232-
py312: OK (2.08=setup[1.22]+cmd[0.86] seconds)
233-
py313: OK (2.18=setup[1.23]+cmd[0.95] seconds)
234-
congratulations :) (3.05 seconds)
266+
py311: OK ✔ in 1.7 seconds
267+
py310: OK ✔ in 1.8 seconds
268+
py313: OK ✔ in 1.8 seconds
269+
py314t: OK ✔ in 1.89 seconds
270+
py314: OK ✔ in 1.91 seconds
271+
py313t: OK ✔ in 2.24 seconds
272+
py310: OK (1.80=setup[0.62]+cmd[0.02,1.16] seconds)
273+
py311: OK (1.70=setup[0.54]+cmd[0.02,1.15] seconds)
274+
py312: OK (2.28=setup[0.58]+cmd[0.01,1.69] seconds)
275+
py313: OK (1.80=setup[0.60]+cmd[0.02,1.18] seconds)
276+
py314: OK (1.91=setup[0.62]+cmd[0.02,1.28] seconds)
277+
py313t: OK (2.24=setup[0.72]+cmd[0.02,1.51] seconds)
278+
py314t: OK (1.89=setup[0.61]+cmd[0.02,1.26] seconds)
279+
congratulations :) (2.33 seconds)
235280
236281
.. note::
237282
The output is not abbreviated; this is the full output you will see if
@@ -247,11 +292,12 @@ the ``pytest-cov`` plugin is installed in the tox test environments. Including
247292
extend commands to ``pytest --cov=items``:
248293

249294
.. code-block::
250-
:emphasize-lines: 12-
295+
:emphasize-lines: 11-
251296
252297
[tox]
253-
envlist = py3{9,10,11,12,13,13t,14,14t}
254-
isolated_build = True
298+
envlist =
299+
py3{10-14}
300+
py3{13-14}t
255301
skip_missing_interpreters = True
256302
257303
[testenv]
@@ -273,7 +319,7 @@ When using Coverage with ``tox``, it can sometimes be useful to add a section in
273319
the :file:`pyproject.toml` file to tell Coverage which source code paths should
274320
be considered identical:
275321

276-
.. code-block:: ini
322+
.. code-block:: toml
277323
278324
[tool.coverage.paths]
279325
source = ["src", ".tox/py*/**/site-packages"]
@@ -288,23 +334,20 @@ example.
288334
289335
$ uv run tox
290336
...
291-
coverage-report: commands[0]> coverage combine
292-
Combined data file .coverage.fay.local.19539.XpQXpsGx
293-
coverage-report: commands[1]> coverage report
294-
Name Stmts Miss Branch BrPart Cover Missing
295-
--------------------------------------------------------------
296-
src/items/api.py 68 1 12 1 98% 88
297-
--------------------------------------------------------------
298-
TOTAL 428 1 32 1 99%
299-
300-
26 files skipped due to complete coverage.
301-
py39: OK (2.12=setup[1.49]+cmd[0.63] seconds)
302-
py310: SKIP (0.01 seconds)
303-
py311: OK (1.41=setup[0.80]+cmd[0.62] seconds)
304-
py312: OK (1.43=setup[0.81]+cmd[0.62] seconds)
305-
py313: OK (1.46=setup[0.83]+cmd[0.62] seconds)
306-
coverage-report: OK (0.16=setup[0.00]+cmd[0.07,0.09] seconds)
307-
congratulations :) (10.26 seconds)
337+
Name Stmts Miss Branch BrPart Cover Missing
338+
---------------------------------------------------
339+
TOTAL 540 0 32 0 100%
340+
341+
33 files skipped due to complete coverage.
342+
py310: OK (1.10=setup[0.44]+cmd[0.01,0.64] seconds)
343+
py311: OK (0.98=setup[0.31]+cmd[0.01,0.66] seconds)
344+
py312: OK (1.59=setup[0.34]+cmd[0.01,1.24] seconds)
345+
py313: OK (1.06=setup[0.34]+cmd[0.01,0.71] seconds)
346+
py314: OK (1.10=setup[0.35]+cmd[0.01,0.74] seconds)
347+
py313t: OK (1.36=setup[0.40]+cmd[0.01,0.95] seconds)
348+
py314t: OK (1.31=setup[0.44]+cmd[0.01,0.86] seconds)
349+
coverage-report: OK (1.55=setup[0.37]+cmd[1.08,0.10] seconds)
350+
congratulations :) (10.09 seconds)
308351
309352
Set minimum coverage
310353
--------------------
@@ -336,15 +379,15 @@ We can also call individual tests with tox by making another change so that
336379
:term:`parameters <Parameter>` can be passed to pytest:
337380

338381
.. code-block:: ini
339-
:emphasize-lines: 17
382+
:emphasize-lines: 16
340383
341384
[tox]
342385
envlist =
343386
pre-commit
344387
docs
345-
py3{9,10,11,12,13,13t,14,14t}
388+
py3{10-14}
389+
py3{13-14}t
346390
coverage-report
347-
isolated_build = True
348391
skip_missing_interpreters = True
349392
350393
[testenv]

0 commit comments

Comments
 (0)