Skip to content

Commit

Permalink
fix: look for uv next to python if it's not on PATH
Browse files Browse the repository at this point in the history
  • Loading branch information
cjolowicz committed Mar 6, 2024
1 parent 419b98a commit 74dd8ac
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 2 deletions.
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ repos:
- jinja2
- packaging
- importlib_metadata
- uv

- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
Expand Down
21 changes: 19 additions & 2 deletions nox/virtualenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,23 @@
_SYSTEM = platform.system()


def find_uv() -> str | None:
uv = shutil.which("uv")
if uv is not None:
return uv

# Look for uv in Nox's environment as well, to handle `pipx install nox[uv]`.
with contextlib.suppress(ImportError, FileNotFoundError):
from uv import find_uv_bin

return find_uv_bin()

return None


UV = find_uv()


class InterpreterNotFound(OSError):
def __init__(self, interpreter: str) -> None:
super().__init__(f"Python interpreter {interpreter} not found")
Expand Down Expand Up @@ -524,7 +541,7 @@ def create(self) -> bool:
cmd.extend(["-p", self._resolved_interpreter])
elif self.venv_backend == "uv":
cmd = [
"uv",
UV or "uv",
"venv",
"-p",
self._resolved_interpreter if self.interpreter else sys.executable,
Expand Down Expand Up @@ -560,5 +577,5 @@ def create(self) -> bool:
OPTIONAL_VENVS = {
"conda": shutil.which("conda") is not None,
"mamba": shutil.which("mamba") is not None,
"uv": shutil.which("uv") is not None,
"uv": UV is not None,
}
23 changes: 23 additions & 0 deletions tests/test_virtualenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import shutil
import subprocess
import sys
import types
from textwrap import dedent
from typing import NamedTuple
from unittest import mock
Expand Down Expand Up @@ -538,6 +539,28 @@ def test_create_reuse_uv_environment(make_one):
assert reused


UV_IN_PIPX_VENV = "/home/user/.local/pipx/venvs/nox/bin/uv"


@pytest.mark.parametrize(
["which_result", "find_uv_bin_result", "expected"],
[
("/usr/bin/uv", UV_IN_PIPX_VENV, "/usr/bin/uv"),
("/usr/bin/uv", None, "/usr/bin/uv"),
(None, UV_IN_PIPX_VENV, UV_IN_PIPX_VENV),
(None, None, None),
],
)
def test_find_uv_path(monkeypatch, which_result, find_uv_bin_result, expected):
monkeypatch.setattr(shutil, "which", lambda _: which_result)
monkeypatch.setitem(
sys.modules,
"uv",
types.SimpleNamespace(find_uv_bin=lambda: find_uv_bin_result),
)
assert nox.virtualenv.find_uv() == expected


def test_create_reuse_venv_environment(make_one, monkeypatch):
# Making the reuse requirement more strict
monkeypatch.setenv("NOX_ENABLE_STALENESS_CHECK", "1")
Expand Down

0 comments on commit 74dd8ac

Please sign in to comment.