Fails to run test for on the defined Python versions, except on uv's pinned Python version.
Issue
Tox does not manage to run the tests on the defined Python version list, but it does manage to run the tests on the Python version pinned with uv. The remaining fails when trying to create a log file.
FileNotFoundError: [Errno 2] No such file or directory: '/home/[...]/snippets/get_configuration/.tox/py312/log/2-uv-sync.log'
The log/ directory does not exist. Creating it prior to running tox does not solves the issue.
Environment
- OS: Ubuntu 22.04.4 LTS
Output of uv --version of the host Python.
uv 0.4.14
Output of tox --version of the host Python. Tox was installed using uv tool install tox --with tox-uv
4.20.0 from /home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/__init__.py
registered plugins:
tox-uv-1.13.0 at /home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox_uv/plugin.py with uv==0.4.14
Output of running tox
Output of tox -rvv
py38: 209 W remove tox env folder /home/[...]/snippets/get_configuration/.tox/py38 [tox/tox_env/api.py:324]
py38: 214 W venv> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p 3.8 --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py38 [tox/tox_env/api.py:426]
DEBUG uv 0.4.14
DEBUG Found project root: `/home/[...]/snippets/get_configuration`
DEBUG No workspace root found, using project root
DEBUG Searching for Python 3.8 in managed installations
DEBUG Searching for managed installations at `/home/[...]/.local/share/uv/python`
DEBUG Found managed installation `cpython-3.8.19-linux-x86_64-gnu`
DEBUG Found `cpython-3.8.19-linux-x86_64-gnu` at `/home/[...]/.local/share/uv/python/cpython-3.8.19-linux-x86_64-gnu/bin/python3` (managed installations)
Using Python 3.8.19
Creating virtual environment at: .tox/py38
DEBUG Allowing existing directory
py38: 231 I exit 0 (0.02 seconds) /home/[...]/snippets/get_configuration> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p 3.8 --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py38 pid=1729520 [tox/execute/api.py:286]
py38: 233 W uv-sync> uv sync --frozen --no-dev [tox/tox_env/api.py:426]
py38: 254 E internal error [tox/session/cmd/run/single.py:60]
Traceback (most recent call last):
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 249, in setup
self._setup_env()
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox_uv/_run_lock.py", line 59, in _setup_env
outcome = self.execute(cmd, stdin=StdinSource.OFF, run_id="uv-sync", show=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 388, in execute
with self.execute_async(cmd, stdin, show, cwd, run_id, executor) as status:
File "/home/[...]/.local/share/uv/python/cpython-3.12.5-linux-x86_64-gnu/lib/python3.12/contextlib.py", line 144, in __exit__
next(self.gen)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 442, in execute_async
self._log_execute(request, execute_status)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 448, in _log_execute
self._write_execute_log(self.name, self.env_log_dir / f"{self._log_id}-{request.run_id}.log", request, status)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 452, in _write_execute_log
with log_file.open("wt", encoding="utf-8") as file:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/[...]/.local/share/uv/python/cpython-3.12.5-linux-x86_64-gnu/lib/python3.12/pathlib.py", line 1013, in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/home/[...]/snippets/get_configuration/.tox/py38/log/2-uv-sync.log'
py38: FAIL ✖ in 0.05 seconds
py39: 256 W remove tox env folder /home/[...]/snippets/get_configuration/.tox/py39 [tox/tox_env/api.py:324]
py39: 260 W venv> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p 3.9 --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py39 [tox/tox_env/api.py:426]
DEBUG uv 0.4.14
DEBUG Found project root: `/home/[...]/snippets/get_configuration`
DEBUG No workspace root found, using project root
DEBUG Searching for Python 3.9 in managed installations
DEBUG Searching for managed installations at `/home/[...]/.local/share/uv/python`
DEBUG Found managed installation `cpython-3.9.19-linux-x86_64-gnu`
DEBUG Found `cpython-3.9.19-linux-x86_64-gnu` at `/home/[...]/.local/share/uv/python/cpython-3.9.19-linux-x86_64-gnu/bin/python3` (managed installations)
Using Python 3.9.19
Creating virtual environment at: .tox/py39
DEBUG Allowing existing directory
py39: 280 I exit 0 (0.02 seconds) /home/[...]/snippets/get_configuration> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p 3.9 --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py39 pid=1729555 [tox/execute/api.py:286]
py39: 281 W uv-sync> uv sync --frozen --no-dev [tox/tox_env/api.py:426]
py39: 305 E internal error [tox/session/cmd/run/single.py:60]
Traceback (most recent call last):
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 249, in setup
self._setup_env()
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox_uv/_run_lock.py", line 59, in _setup_env
outcome = self.execute(cmd, stdin=StdinSource.OFF, run_id="uv-sync", show=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 388, in execute
with self.execute_async(cmd, stdin, show, cwd, run_id, executor) as status:
File "/home/[...]/.local/share/uv/python/cpython-3.12.5-linux-x86_64-gnu/lib/python3.12/contextlib.py", line 144, in __exit__
next(self.gen)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 442, in execute_async
self._log_execute(request, execute_status)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 448, in _log_execute
self._write_execute_log(self.name, self.env_log_dir / f"{self._log_id}-{request.run_id}.log", request, status)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 452, in _write_execute_log
with log_file.open("wt", encoding="utf-8") as file:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/[...]/.local/share/uv/python/cpython-3.12.5-linux-x86_64-gnu/lib/python3.12/pathlib.py", line 1013, in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/home/[...]/snippets/get_configuration/.tox/py39/log/2-uv-sync.log'
py39: FAIL ✖ in 0.05 seconds
py310: 307 W remove tox env folder /home/[...]/snippets/get_configuration/.tox/py310 [tox/tox_env/api.py:324]
py310: 318 W venv> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p 3.10 --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py310 [tox/tox_env/api.py:426]
DEBUG uv 0.4.14
DEBUG Found project root: `/home/[...]/snippets/get_configuration`
DEBUG No workspace root found, using project root
DEBUG Searching for Python 3.10 in managed installations
DEBUG Searching for managed installations at `/home/[...]/.local/share/uv/python`
DEBUG Found managed installation `cpython-3.10.14-linux-x86_64-gnu`
DEBUG Found `cpython-3.10.14-linux-x86_64-gnu` at `/home/[...]/.local/share/uv/python/cpython-3.10.14-linux-x86_64-gnu/bin/python3` (managed installations)
Using Python 3.10.14
Creating virtual environment at: .tox/py310
DEBUG Allowing existing directory
py310: 338 I exit 0 (0.02 seconds) /home/[...]/snippets/get_configuration> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p 3.10 --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py310 pid=1729591 [tox/execute/api.py:286]
py310: 340 W uv-sync> uv sync --frozen --no-dev [tox/tox_env/api.py:426]
py310: 366 E internal error [tox/session/cmd/run/single.py:60]
Traceback (most recent call last):
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 249, in setup
self._setup_env()
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox_uv/_run_lock.py", line 59, in _setup_env
outcome = self.execute(cmd, stdin=StdinSource.OFF, run_id="uv-sync", show=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 388, in execute
with self.execute_async(cmd, stdin, show, cwd, run_id, executor) as status:
File "/home/[...]/.local/share/uv/python/cpython-3.12.5-linux-x86_64-gnu/lib/python3.12/contextlib.py", line 144, in __exit__
next(self.gen)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 442, in execute_async
self._log_execute(request, execute_status)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 448, in _log_execute
self._write_execute_log(self.name, self.env_log_dir / f"{self._log_id}-{request.run_id}.log", request, status)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 452, in _write_execute_log
with log_file.open("wt", encoding="utf-8") as file:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/[...]/.local/share/uv/python/cpython-3.12.5-linux-x86_64-gnu/lib/python3.12/pathlib.py", line 1013, in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/home/[...]/snippets/get_configuration/.tox/py310/log/2-uv-sync.log'
py311: 368 W remove tox env folder /home/[...]/snippets/get_configuration/.tox/py311 [tox/tox_env/api.py:324]
py310: FAIL ✖ in 0.06 seconds
py311: 391 W venv> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p 3.11 --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py311 [tox/tox_env/api.py:426]
DEBUG uv 0.4.14
DEBUG Found project root: `/home/[...]/snippets/get_configuration`
DEBUG No workspace root found, using project root
DEBUG Searching for Python 3.11 in managed installations
DEBUG Searching for managed installations at `/home/[...]/.local/share/uv/python`
DEBUG Found managed installation `cpython-3.11.9-linux-x86_64-gnu`
DEBUG Found `cpython-3.11.9-linux-x86_64-gnu` at `/home/[...]/.local/share/uv/python/cpython-3.11.9-linux-x86_64-gnu/bin/python3` (managed installations)
Using Python 3.11.9
Creating virtual environment at: .tox/py311
DEBUG Allowing existing directory
py311: 411 I exit 0 (0.02 seconds) /home/[...]/snippets/get_configuration> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p 3.11 --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py311 pid=1729626 [tox/execute/api.py:286]
py311: 413 W uv-sync> uv sync --frozen --no-dev [tox/tox_env/api.py:426]
py311: 430 I exit 0 (0.02 seconds) /home/[...]/snippets/get_configuration> uv sync --frozen --no-dev pid=1729645 [tox/execute/api.py:286]
py311: 431 W commands[0]> make tests [tox/tox_env/api.py:426]
uv run pytest --cov=env tests.py
Installed 7 packages in 12ms
================================================ test session starts ================================================
platform linux -- Python 3.11.9, pytest-8.3.3, pluggy-1.5.0
cachedir: .tox/py311/.pytest_cache
rootdir: /home/[...]/snippets/get_configuration
configfile: pyproject.toml
plugins: cov-5.0.0, mock-3.14.0
collected 6 items
tests.py ...... [100%]
---------- coverage: platform linux, python 3.11.9-final-0 -----------
Name Stmts Miss Cover
----------------------------------------------
src/env/__init__.py 2 0 100%
src/env/configuration.py 24 0 100%
----------------------------------------------
TOTAL 26 0 100%
================================================= 6 passed in 0.07s =================================================
py311: 1349 I exit 0 (0.92 seconds) /home/[...]/snippets/get_configuration> make tests pid=1729659 [tox/execute/api.py:286]
py311: OK ✔ in 0.98 seconds
py312: 1349 W remove tox env folder /home/[...]/snippets/get_configuration/.tox/py312 [tox/tox_env/api.py:324]
py312: 1357 W venv> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p /home/[...]/.local/share/uv/tools/tox/bin/python --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py312 [tox/tox_env/api.py:426]
DEBUG uv 0.4.14
DEBUG Found project root: `/home/[...]/snippets/get_configuration`
DEBUG No workspace root found, using project root
DEBUG Checking for Python interpreter at path `/home/[...]/.local/share/uv/tools/tox/bin/python`
Using Python 3.12.5 interpreter at: /home/[...]/.local/share/uv/tools/tox/bin/python
Creating virtual environment at: .tox/py312
DEBUG Allowing existing directory
py312: 1380 I exit 0 (0.02 seconds) /home/[...]/snippets/get_configuration> /home/[...]/.local/share/uv/tools/tox/bin/uv venv -p /home/[...]/.local/share/uv/tools/tox/bin/python --allow-existing -v --python-preference only-managed /home/[...]/snippets/get_configuration/.tox/py312 pid=1729739 [tox/execute/api.py:286]
py312: 1382 W uv-sync> uv sync --frozen --no-dev [tox/tox_env/api.py:426]
py312: 1407 E internal error [tox/session/cmd/run/single.py:60]
Traceback (most recent call last):
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 249, in setup
self._setup_env()
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox_uv/_run_lock.py", line 59, in _setup_env
outcome = self.execute(cmd, stdin=StdinSource.OFF, run_id="uv-sync", show=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 388, in execute
with self.execute_async(cmd, stdin, show, cwd, run_id, executor) as status:
File "/home/[...]/.local/share/uv/python/cpython-3.12.5-linux-x86_64-gnu/lib/python3.12/contextlib.py", line 144, in __exit__
next(self.gen)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 442, in execute_async
self._log_execute(request, execute_status)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 448, in _log_execute
self._write_execute_log(self.name, self.env_log_dir / f"{self._log_id}-{request.run_id}.log", request, status)
File "/home/[...]/.local/share/uv/tools/tox/lib/python3.12/site-packages/tox/tox_env/api.py", line 452, in _write_execute_log
with log_file.open("wt", encoding="utf-8") as file:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/[...]/.local/share/uv/python/cpython-3.12.5-linux-x86_64-gnu/lib/python3.12/pathlib.py", line 1013, in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/home/[...]/snippets/get_configuration/.tox/py312/log/2-uv-sync.log'
py38: FAIL code 2 (0.05 seconds)
py39: FAIL code 2 (0.05 seconds)
py310: FAIL code 2 (0.06 seconds)
py311: OK (0.98=setup[0.06]+cmd[0.92] seconds)
py312: FAIL code 2 (0.06 seconds)
evaluation failed :( (1.27 seconds)
Any Python version pinned with uv will pass without any issues, and sometimes, the two most recent pinned Python version will also pass.
Trimmed output of tox showing only the report, after the Python version 3.8 then 3.9 were pinned.
py38: OK (1.10=setup[0.04]+cmd[1.06] seconds)
py39: OK (0.97=setup[0.03]+cmd[0.94] seconds)
py310: FAIL code 2 (0.04 seconds)
py311: FAIL code 2 (0.14 seconds)
py312: FAIL code 2 (0.06 seconds)
evaluation failed :( (2.39 seconds)
Related code
You can find the whole related code in the Gitlab snippet 1941025, but here are the tox.ini, pyproject.toml and the Makefile:
tox.ini
[tox]
env_list = py{38,39,310,311,312}
[testenv]
description = run unit tests
runner = uv-venv-lock-runner
allowlist_externals = make
commands =
make tests
pyproject.toml
[project]
name = "env"
version = "3.1.0"
description = """
A helper function to retrieve configuration values from environment variables or Docker secrets.
The function supports reading secrets from files (if *_FILE is set) and can return default values
when no environment variable is found. Raises appropriate exceptions when required configuration
is missing or when errors occur during file reading.
"""
readme = "README.md"
requires-python = ">=3.8"
[tool.uv]
dev-dependencies = [
"pytest>=8.3.3",
"pytest-mock>=3.14.0",
"pytest-cov>=5.0.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Makefile
sync:
uv sync
tests:
uv run pytest --cov=env tests.py
Do you have a docker image where you can replicate this? It doesn't replicate for me with the information provided.
I've managed to reproduce with the following Dockerfile, with same installation steps:
FROM python:3-bookworm
# FROM python@sha256:096c49cf57695962d6d5e2998d0d23640b4234dfffcd8472d48adceb518582de
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
RUN apt update && \
apt install -y pipx && \
pipx ensurepath && \
pipx install tox
WORKDIR /opt/env
COPY . .
RUN uv sync && \
uv tool install tox --with tox-uv --force
ENV PATH="$PATH:/root/.local/bin"
CMD [ "tox" ]
I suppose installing tox with pipx then with uv, but still using the tox from pipx is the actual problem ?
I've specified the Docker image digest so you can reproduce exactly with the same image.
Here the output of docker run --rm env, considering it's built with docker build -t env .:
py38: venv> /root/.local/share/uv/tools/tox/bin/uv venv -p 3.8 --allow-existing /opt/env/.tox/py38
py38: uv-sync> uv sync --frozen --no-dev
py38: internal error
Traceback (most recent call last):
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 249, in setup
self._setup_env()
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox_uv/_run_lock.py", line 59, in _setup_env
outcome = self.execute(cmd, stdin=StdinSource.OFF, run_id="uv-sync", show=False)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 390, in execute
pass # pragma: no cover
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/contextlib.py", line 126, in __exit__
next(self.gen)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 442, in execute_async
self._log_execute(request, execute_status)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 448, in _log_execute
self._write_execute_log(self.name, self.env_log_dir / f"{self._log_id}-{request.run_id}.log", request, status)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 452, in _write_execute_log
with log_file.open("wt", encoding="utf-8") as file:
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/pathlib.py", line 1252, in open
return io.open(self, mode, buffering, encoding, errors, newline,
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/pathlib.py", line 1120, in _opener
return self._accessor.open(self, flags, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/opt/env/.tox/py38/log/2-uv-sync.log'
py38: FAIL ✖ in 9.62 seconds
py39: uv-sync> uv sync --frozen --no-dev
py39: commands[0]> make tests
uv run pytest --cov=env tests.py
Installed 9 packages in 181ms
=============================================== test session starts ===============================================
platform linux -- Python 3.9.20, pytest-8.3.3, pluggy-1.5.0
cachedir: .tox/py39/.pytest_cache
rootdir: /opt/env
configfile: pyproject.toml
plugins: cov-5.0.0, mock-3.14.0
collected 6 items
tests.py ...... [100%]
---------- coverage: platform linux, python 3.9.20-final-0 -----------
Name Stmts Miss Cover
----------------------------------------------
src/env/__init__.py 2 0 100%
src/env/configuration.py 24 0 100%
----------------------------------------------
TOTAL 26 0 100%
================================================ 6 passed in 0.11s ================================================
py39: OK ✔ in 1.33 seconds
py310: venv> /root/.local/share/uv/tools/tox/bin/uv venv -p 3.10 --allow-existing /opt/env/.tox/py310
py310: uv-sync> uv sync --frozen --no-dev
py310: internal error
Traceback (most recent call last):
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 249, in setup
self._setup_env()
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox_uv/_run_lock.py", line 59, in _setup_env
outcome = self.execute(cmd, stdin=StdinSource.OFF, run_id="uv-sync", show=False)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 390, in execute
pass # pragma: no cover
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/contextlib.py", line 126, in __exit__
next(self.gen)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 442, in execute_async
self._log_execute(request, execute_status)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 448, in _log_execute
self._write_execute_log(self.name, self.env_log_dir / f"{self._log_id}-{request.run_id}.log", request, status)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 452, in _write_execute_log
with log_file.open("wt", encoding="utf-8") as file:
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/pathlib.py", line 1252, in open
return io.open(self, mode, buffering, encoding, errors, newline,
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/pathlib.py", line 1120, in _opener
return self._accessor.open(self, flags, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/opt/env/.tox/py310/log/2-uv-sync.log'
py310: FAIL ✖ in 8.46 seconds
py311: venv> /root/.local/share/uv/tools/tox/bin/uv venv -p 3.11 --allow-existing /opt/env/.tox/py311
py311: uv-sync> uv sync --frozen --no-dev
py311: internal error
Traceback (most recent call last):
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 249, in setup
self._setup_env()
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox_uv/_run_lock.py", line 59, in _setup_env
outcome = self.execute(cmd, stdin=StdinSource.OFF, run_id="uv-sync", show=False)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 390, in execute
pass # pragma: no cover
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/contextlib.py", line 126, in __exit__
next(self.gen)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 442, in execute_async
self._log_execute(request, execute_status)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 448, in _log_execute
self._write_execute_log(self.name, self.env_log_dir / f"{self._log_id}-{request.run_id}.log", request, status)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 452, in _write_execute_log
with log_file.open("wt", encoding="utf-8") as file:
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/pathlib.py", line 1252, in open
return io.open(self, mode, buffering, encoding, errors, newline,
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/pathlib.py", line 1120, in _opener
return self._accessor.open(self, flags, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/opt/env/.tox/py311/log/2-uv-sync.log'
py311: FAIL ✖ in 0.18 seconds
py312: venv> /root/.local/share/uv/tools/tox/bin/uv venv -p 3.12 --allow-existing /opt/env/.tox/py312
py312: uv-sync> uv sync --frozen --no-dev
py312: internal error
Traceback (most recent call last):
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/session/cmd/run/single.py", line 47, in _evaluate
tox_env.setup()
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 249, in setup
self._setup_env()
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox_uv/_run_lock.py", line 59, in _setup_env
outcome = self.execute(cmd, stdin=StdinSource.OFF, run_id="uv-sync", show=False)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 390, in execute
pass # pragma: no cover
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/contextlib.py", line 126, in __exit__
next(self.gen)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 442, in execute_async
self._log_execute(request, execute_status)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 448, in _log_execute
self._write_execute_log(self.name, self.env_log_dir / f"{self._log_id}-{request.run_id}.log", request, status)
File "/root/.local/share/uv/tools/tox/lib/python3.9/site-packages/tox/tox_env/api.py", line 452, in _write_execute_log
with log_file.open("wt", encoding="utf-8") as file:
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/pathlib.py", line 1252, in open
return io.open(self, mode, buffering, encoding, errors, newline,
File "/root/.local/share/uv/python/cpython-3.9.20-linux-x86_64-gnu/lib/python3.9/pathlib.py", line 1120, in _opener
return self._accessor.open(self, flags, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/opt/env/.tox/py312/log/2-uv-sync.log'
py38: FAIL code 2 (9.62 seconds)
py39: OK (1.33=setup[0.05]+cmd[1.28] seconds)
py310: FAIL code 2 (8.46 seconds)
py311: FAIL code 2 (0.17 seconds)
py312: FAIL code 2 (0.28 seconds)
evaluation failed :( (20.15 seconds)
And here's the output of docker inspect python:3-bookworm
[
{
"Id": "sha256:ea2ebd905ab246ece277be25520ca0cfe82758b3d2b369e2fd69b374c1d6c7fa",
"RepoTags": [
"python:3-bookworm"
],
"RepoDigests": [
"python@sha256:096c49cf57695962d6d5e2998d0d23640b4234dfffcd8472d48adceb518582de"
],
"Parent": "",
"Comment": "buildkit.dockerfile.v0",
"Created": "2024-09-09T17:16:05Z",
"DockerVersion": "",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=C.UTF-8",
"GPG_KEY=7169605F62C751356D054A26A821E680E5FA6305",
"PYTHON_VERSION=3.12.6"
],
"Cmd": [
"python3"
],
"ArgsEscaped": true,
"Image": "",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 1013190869,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/051b0a9d04d61de48810f9c937b7e8906a033ba351c17728341731202c7ae0fd/diff:/var/lib/docker/overlay2/46b6a9fc05d056deb798b7146af19c201eba7dcd2b1129164d8215505c958d5c/diff:/var/lib/docker/overlay2/de3be5f9fed6b0f7f2604c915a53a0fbb27cab000052c902a9eb139b9aec18c6/diff:/var/lib/docker/overlay2/b9bb0329cb3b9e3bec568453a93df05047637784f6e3b44ccf1760c02c812400/diff:/var/lib/docker/overlay2/64ef49fe5ad37bb84f39c69c95d887ae8589738d685d8e303bf7555933a80dbb/diff:/var/lib/docker/overlay2/573e85a97762b77d08cf33b18c20021f68a8da341ce9311dcfb658fe02c76bf5/diff",
"MergedDir": "/var/lib/docker/overlay2/350d94ad279f878cd1da8167c2462f30d37ff0c47e42ed1db970494618deb55a/merged",
"UpperDir": "/var/lib/docker/overlay2/350d94ad279f878cd1da8167c2462f30d37ff0c47e42ed1db970494618deb55a/diff",
"WorkDir": "/var/lib/docker/overlay2/350d94ad279f878cd1da8167c2462f30d37ff0c47e42ed1db970494618deb55a/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:6abe10f2f60150ae9768e117986e4f8af5546137221553228eb5d21066f596b4",
"sha256:25879f85bbb0206e6870e7073a576acd49be6e8c3a15ba4b443166f92b041327",
"sha256:045d8b74bf0ddedb671bd1ba1ab114e3a3e7b86dc5c7e18f9b7edda74193174d",
"sha256:3a8081ce85fac02e6d87b062aff5ace4027e2409de4a65a1844308b6510068cf",
"sha256:4bad8619a2548e688aa5c0d066ef602a13ddd73f25f80c97a5e9e1722fdb0b44",
"sha256:6e12f34fe52a9891444cf01c5d0b0741f3f27b9e6636d1f22530955dd0ce0b66",
"sha256:d78767df0001818e81271ed8884312feb3af5b0cf392b642930c2c9a9bca7a3a"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
The Python version is 3.12 in the Docker image, but it pass with tox with Python 3.9, somehow.
Why are you installing the tool twice?
In this case, inside the Docker image, I do not see any project files or lock files you are working on. Can you post a reproducible that contains the project too, that you are testing with? Thank you.
Sure, I've pushed the image to Docker Hub, you can get it from the image flowgunso/env, it calls tox directly. You can find the full code in the Gitlab snippet 1941025, though.
I wasn't sure how to link tox and tox-uv from uv with the system itself. That's why I've installed tox with pipx. Reading uv's documentation, I've learned about uv tool update-shell that makes sure ~/.local/bin is in my PATH.
I've updated the Dockerfile accordingly:
FROM python:3-bookworm
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /opt/env
COPY . .
RUN uv sync && \
uv tool install tox --with tox-uv
ENV PATH="$PATH:/root/.local/bin"
CMD [ "tox" ]
Thanks for you help.
Is there any way I can help you ?
I'm also getting this same error on a Windows 10 environment.
Are there workarounds for this issue perchance? @flowgunso
Is there any way I can help you ?
At this point only by putting in a pull request to fix the issue.
I'm fine with making a PR with the fix.
Knowing the codebase, do you have any ideas what the origin of the issue might be, so I can be on the right track, please ?
Nothing jumps out to the top of my mind.
Tox does not manage to run the tests on the defined Python version list, but it does manage to run the tests on the Python version pinned with
uv
What does pinning with uv mean? I can't seem to replicate this:
~/git/github/tox-uv/magic/1941025 on master [!]
❯ tox r -e 3.12
3.12: uv-sync> uv sync --frozen --no-dev
Uninstalled 7 packages in 51ms
- coverage==7.6.1
- iniconfig==2.0.0
- packaging==24.1
- pluggy==1.5.0
- pytest==8.3.3
- pytest-cov==5.0.0
- pytest-mock==3.14.0
3.12: commands[0]> make tests
uv run pytest --cov=env tests.py
Installed 7 packages in 7ms
=========================================================================== test session starts ============================================================================
platform darwin -- Python 3.12.6, pytest-8.3.3, pluggy-1.5.0
cachedir: .tox/3.12/.pytest_cache
rootdir: /Users/x/git/github/tox-uv/magic/1941025
configfile: pyproject.toml
plugins: cov-5.0.0, mock-3.14.0
collected 6 items
tests.py ...... [100%]
---------- coverage: platform darwin, python 3.12.6-final-0 ----------
Name Stmts Miss Cover
----------------------------------------------
src/env/__init__.py 2 0 100%
src/env/configuration.py 24 0 100%
----------------------------------------------
TOTAL 26 0 100%
============================================================================ 6 passed in 0.08s =============================================================================
3.12: OK (1.22=setup[0.09]+cmd[1.13] seconds)
congratulations :) (1.28 seconds)
It allows to pin a specific Python version to a project. For example, uv python pin 3.12 or uv python pin 3.8 to use Python 3.12 or 3.8 in the project. See uv python pin.
I do not use the pinning feature at all and it still works for me. See my output from above so I don't know what to say to you.
@flowgunso I ran into this issue also when using uv in the make target. The issue here stems from using the global uv app (via make) inside the tox context.
Here we assume uv run pytest --cov=env tests.py will be auto-loaded with the desired version of Python used by tox, this is not the case as uv is configured outside of the tox runner with your development version of python, not the tox version.
I do not think there is a bug here, instead an unexpected (but valid) behaviour to what a developer thinks will/should happen. In this case, tox is behaving as expected. It is your make target you will need to refactor.
Here is how I got around it:
pyproject.toml
[tool.tox]
envlist = [
"3.8",
"3.9",
"3.10",
"3.11",
"3.12",
]
isolated_build = true
[tool.tox.env_run_base]
description = "Run the tests for {base_python}"
runner = "uv-venv-runner"
extras = [
"test",
]
setenv = { TOX_BIN_DIR = "{envbindir}", TOX_PYTHON_BIN = "{envpython}" }
allowlist_externals = [
"make",
]
commands = [
["make", "test"],
]
Makefile
VENV_DIR_NAME = ./.venv # Default `uv` venv directory path
SCRIPTS_DIR = $(or $(TOX_BIN_DIR), ${VENV_DIR_NAME}/bin) # Path to `venv/bin` dir
PYTHON_VENV ?= $(or $(TOX_PYTHON_BIN), ${SCRIPTS_DIR}/python) # Path to python venv executable
TESTS_DIR = tests # Location of my test suite
test:
@echo "🧪 *** Running tests..."; \
${PYTHON_VENV} -m pytest -vv -s ${TESTS_DIR}
Note: Comments in Makefile above may need to be removed, I added these for clarity but are not in my running config.
In the above, I dynamically set SCRIPTS_DIR and PYTHON_VENV based on if the envvars TOX_BIN_DIR and TOX_PYTHON_BIN are set by tox or if they do not exist, set them to a default value which means running in development mode. As the make target is called for each version of python in tox, the envvars TOX_BIN_DIR and TOX_PYTHON_BIN are set each time to the current version being used by tox. This allows you to simply call pytest referencing the current active python version. This removes the global reference to uv in make and makes the makefile more generalisable for both dev and tox usage.
@gaborbernat
I do not use the pinning feature at all and it still works for me. See my output from above so I don't know what to say to you.
After doing a system update, I cannot reproduce the error either, all tests pass on the Python versions:
================================================ 4 passed in 0.09s =================================================
py38: OK (0.97=setup[0.11]+cmd[0.86] seconds)
py39: OK (1.04=setup[0.12]+cmd[0.92] seconds)
py310: OK (1.01=setup[0.13]+cmd[0.88] seconds)
py311: OK (0.99=setup[0.10]+cmd[0.89] seconds)
py312: OK (1.30=setup[0.10]+cmd[1.20] seconds)
congratulations :) (5.38 seconds)
uv did not update, so I sadly cannot say what solved the issue. I think that issue can be closed.
@DavidWalshe93 thanks for the in-depth description. I've found another solution, after the issue solved itself with a system update.
Instead of using uv in the make target, like you pointed out, I'm using uv in the tox commands:
[tox]
env_list = py{38,39,310,311,312}
[testenv]
description = run unit tests
runner = uv-venv-lock-runner
allowlist_externals = make
commands =
uv run pytest --cov=env_secrets tests/
And then, I'm using tox in the make target directly.
test:
tox
That works as well.