Skip to content

Commit 04363ff

Browse files
authored
Pass sys.executable to uv venv if it is the same version (#40)
* Pass sys.executable to `uv venv` if it is the same version Support the case when pythonX.Y is not in the search path, but it corresponds to the currently running Python interpreter. This may happen if e.g. Tox is installed (along with tox-uv) in a virtual environment that has been created with a Python interpreter coming from a non-standard location, and then `tox` is invoked directly from the virtual environment's `bin/` directory: [roam@straylight ~]$ mkdir ~/not-in-path [roam@straylight ~]$ uv venv -p /opt/some-vendor/python3/bin/python3 ~/not-in-path/venv Using Python 3.8.17 interpreter at: /opt/some-vendor/python3/bin/python3 Creating virtualenv at: /home/roam/not-in-path/venv Activate with: source /home/roam/not-in-path/venv/bin/activate [roam@straylight ~]$ (set -e; . ~/not-in-path/venv/bin/activate; uv pip install tox tox-uv) ...snip... [roam@straylight ~]$ printf -- '%s\n' '[testenv]' 'package=skip' 'commands=python3 -c "print()"' > ~/not-in-path/tox.ini [roam@straylight ~]$ ~/not-in-path/venv/bin/tox -c ~/not-in-path/tox.ini py: venv /home/roam/not-in-path> venv/bin/uv venv -p 3.8 /home/roam/not-in-path/.tox/py/.venv × No Python 3.8 in `PATH`. Is Python 3.8 installed? py: exit 1 (0.01 seconds) /home/roam/not-in-path> venv/bin/uv venv -p 3.8 /home/roam/not-in-path/.tox/py/.venv pid=1059253 py: FAIL code 1 (0.02 seconds) evaluation failed :( (0.11 seconds) [roam@straylight ~]$ * Let Ruff know that we try to use subprocess responsibly * Tox is certainly installed during the test suite run
1 parent db7196f commit 04363ff

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/tox_uv/_venv.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,13 @@ def _default_pass_env(self) -> list[str]:
113113

114114
def create_python_env(self) -> None:
115115
base = self.base_python.version_info
116-
version_spec = f"{base.major}.{base.minor}" if base.minor else f"{base.major}"
116+
version_spec = (
117+
sys.executable
118+
if (base.major, base.minor) == sys.version_info[:2]
119+
else f"{base.major}.{base.minor}"
120+
if base.minor
121+
else f"{base.major}"
122+
)
117123
cmd: list[str] = [self.uv, "venv", "-p", version_spec]
118124
if self.options.verbosity > 2: # noqa: PLR2004
119125
cmd.append("-v")

tests/test_tox_uv_venv.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
from __future__ import annotations
22

3+
import importlib.util
4+
import os
5+
import os.path
6+
import pathlib
7+
import subprocess # noqa: S404
38
import sys
49
from configparser import ConfigParser
510
from typing import TYPE_CHECKING
@@ -86,3 +91,28 @@ def test_uv_env_site_package_dir(tox_project: ToxProjectCreator) -> None:
8691
else: # pragma: win32 no cover
8792
path = str(env_dir / "lib" / f"python{ver.major}.{ver.minor}" / "site-packages")
8893
assert path in result.out
94+
95+
96+
def test_uv_env_python_not_in_path(tox_project: ToxProjectCreator) -> None:
97+
# Make sure there is no pythonX.Y in the search path
98+
ver = sys.version_info
99+
exe_ext = ".exe" if sys.platform == "win32" else ""
100+
python_exe = f"python{ver.major}.{ver.minor}{exe_ext}"
101+
env = dict(os.environ)
102+
env["PATH"] = os.path.pathsep.join(
103+
path for path in env["PATH"].split(os.path.pathsep) if not (pathlib.Path(path) / python_exe).is_file()
104+
)
105+
106+
# Make sure the Python interpreter can find our Tox module
107+
tox_spec = importlib.util.find_spec("tox")
108+
assert tox_spec is not None
109+
tox_lines = subprocess.check_output(
110+
[sys.executable, "-c", "import tox; print(tox.__file__);"], encoding="UTF-8", env=env
111+
).splitlines()
112+
assert tox_lines == [tox_spec.origin]
113+
114+
# Now use that Python interpreter to run Tox
115+
project = tox_project({"tox.ini": "[testenv]\npackage=skip\ncommands=python -c 'print(\"{env_python}\")'"})
116+
tox_ini = project.path / "tox.ini"
117+
assert tox_ini.is_file()
118+
subprocess.check_call([sys.executable, "-m", "tox", "-c", tox_ini], env=env)

0 commit comments

Comments
 (0)