diff --git a/src/dda/tools/uv.py b/src/dda/tools/uv.py index 018c60de..892068b7 100644 --- a/src/dda/tools/uv.py +++ b/src/dda/tools/uv.py @@ -39,16 +39,15 @@ def execution_context(self, command: list[str]) -> Generator[ExecutionContext, N import shutil - from dda.utils.fs import Path + from dda.utils.fs import Path, temp_directory path = Path(self.path) - safe_path = path.with_stem(f"{path.stem}-{path.id}") - shutil.copy2(self.path, safe_path) - - try: + safe_name = path.with_stem(f"{path.stem}-{path.id}").name + with temp_directory() as temp_dir: + # Always use a temporary directory to avoid permission issues. + safe_path = temp_dir / safe_name + shutil.copy2(self.path, safe_path) yield ExecutionContext(command=[str(safe_path), *command], env_vars={}) - finally: - safe_path.unlink() @cached_property def path(self) -> str | None: diff --git a/tests/cli/inv/test_inv.py b/tests/cli/inv/test_inv.py index 09652ac0..147ed23c 100644 --- a/tests/cli/inv/test_inv.py +++ b/tests/cli/inv/test_inv.py @@ -5,6 +5,7 @@ import subprocess import sys +from pathlib import Path from unittest import mock import pytest @@ -33,38 +34,41 @@ def test_default(dda, helpers, temp_dir, uv_on_path, mocker): ), ) - expected_path = str(uv_on_path.with_stem(f"{uv_on_path.stem}-{uv_on_path.id}")) - assert subprocess_run.call_args_list == [ - mock.call( - [ - expected_path, - "venv", - str(temp_dir / "data" / "venvs" / "legacy"), - "--seed", - "--python", - sys.executable, - ], - encoding="utf-8", - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ), - mock.call( - [ - expected_path, - "sync", - "--frozen", - "--no-install-project", - "--inexact", - "--only-group", - "legacy-tasks", - ], - encoding="utf-8", - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=mock.ANY, - env=mock.ANY, - ), - ] + expected_name = uv_on_path.with_stem(f"{uv_on_path.stem}-{uv_on_path.id}").name + first_call, second_call = subprocess_run.call_args_list + + assert Path(first_call.args[0][0]).name == expected_name + assert first_call == mock.call( + [ + mock.ANY, + "venv", + str(temp_dir / "data" / "venvs" / "legacy"), + "--seed", + "--python", + sys.executable, + ], + encoding="utf-8", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + + assert Path(second_call.args[0][0]).name == expected_name + assert second_call == mock.call( + [ + mock.ANY, + "sync", + "--frozen", + "--no-install-project", + "--inexact", + "--only-group", + "legacy-tasks", + ], + encoding="utf-8", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=mock.ANY, + env=mock.ANY, + ) assert exit_with.call_args_list == [ mock.call( [ diff --git a/tests/cli/test_dynamic.py b/tests/cli/test_dynamic.py index 5565da0a..1ec667ec 100644 --- a/tests/cli/test_dynamic.py +++ b/tests/cli/test_dynamic.py @@ -6,6 +6,7 @@ import os import subprocess import sys +from pathlib import Path from unittest import mock @@ -108,20 +109,21 @@ def cmd(app): ), ) - expected_path = str(uv_on_path.with_stem(f"{uv_on_path.stem}-{uv_on_path.id}")) - assert subprocess_run.call_args_list == [ - mock.call( - [ - expected_path, - "pip", - "install", - "--python", - sys.executable, - "-r", - mocker.ANY, - ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - encoding="utf-8", - ), - ] + expected_name = uv_on_path.with_stem(f"{uv_on_path.stem}-{uv_on_path.id}").name + (call,) = subprocess_run.call_args_list + + assert Path(call.args[0][0]).name == expected_name + assert call == mock.call( + [ + mocker.ANY, + "pip", + "install", + "--python", + sys.executable, + "-r", + mocker.ANY, + ], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding="utf-8", + )