tox-dev / tox-uv

Use https://github.com/astral-sh/uv with tox
MIT License
135 stars 19 forks source link

Fails to run test for on the defined Python versions, except on uv's pinned Python version. #97

Closed flowgunso closed 1 month ago

flowgunso commented 2 months ago

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

Output of uv --version of the host Python. ```console uv 0.4.14 ```
Output of tox --version of the host Python. Tox was installed using uv tool install tox --with tox-uv ```console 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 ```console 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. ```console 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 ```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 ```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 ```Makefile sync: uv sync tests: uv run pytest --cov=env tests.py ```
gaborbernat commented 2 months ago

Do you have a docker image where you can replicate this? It doesn't replicate for me with the information provided.

flowgunso commented 2 months ago

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 .: ```console 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 ```console [ { "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.

gaborbernat commented 2 months ago

Why are you installing the tool twice?

gaborbernat commented 2 months ago

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.

flowgunso commented 2 months ago

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.

flowgunso commented 1 month ago

Is there any way I can help you ?

butterlyn commented 1 month ago

I'm also getting this same error on a Windows 10 environment.

butterlyn commented 1 month ago

Are there workarounds for this issue perchance? @flowgunso

gaborbernat commented 1 month ago

Is there any way I can help you ?

At this point only by putting in a pull request to fix the issue.

flowgunso commented 1 month ago

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 ?

gaborbernat commented 1 month ago

Nothing jumps out to the top of my mind.

gaborbernat commented 1 month ago

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)
flowgunso commented 1 month ago

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.

gaborbernat commented 1 month ago

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.

DavidWalshe93 commented 1 month ago

@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.

flowgunso commented 1 month ago

@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.

flowgunso commented 1 month ago

@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.