Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ FindPython finds Python from the following places:
- pyenv install root
- asdf python install root
- [rye](https://rye-up.com) toolchain install root
- [uv](https://docs.astral.sh/uv/) toolchain install root
- `/Library/Frameworks/Python.framework/Versions` (MacOS)
- Windows registry (Windows only)

Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ package-dir = "src"
[tool.pdm.dev-dependencies]
tests = ["pytest"]

[tool.pdm.scripts]
test = "pytest tests"

[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
Expand Down
2 changes: 2 additions & 0 deletions src/findpython/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from findpython.providers.path import PathProvider
from findpython.providers.pyenv import PyenvProvider
from findpython.providers.rye import RyeProvider
from findpython.providers.uv import UvProvider
from findpython.providers.winreg import WinregProvider

_providers: list[type[BaseProvider]] = [
Expand All @@ -19,6 +20,7 @@
AsdfProvider,
PyenvProvider,
RyeProvider,
UvProvider,
# Windows only:
WinregProvider,
# MacOS only:
Expand Down
28 changes: 28 additions & 0 deletions src/findpython/providers/uv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from __future__ import annotations

import os
import typing as t
from pathlib import Path

from findpython.providers.rye import RyeProvider
from findpython.utils import WINDOWS


class UvProvider(RyeProvider):
@classmethod
def create(cls) -> t.Self | None:
# See uv#13877(https://github.com/astral-sh/uv/issues/13877)
if WINDOWS:
default_root_str = os.getenv("APPDATA")
else:
default_root_str = "~/.local/share"
assert default_root_str is not None
root_str = os.getenv("UV_PYTHON_INSTALL_DIR")
if root_str is None:
root_str = os.getenv("XDG_DATA_HOME")
if root_str is None:
root_str = default_root_str
root = Path(root_str).expanduser() / "uv" / "python"
else:
root = Path(root_str).expanduser()
return cls(root)
32 changes: 32 additions & 0 deletions tests/test_posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from findpython.providers.asdf import AsdfProvider
from findpython.providers.pyenv import PyenvProvider
from findpython.providers.rye import RyeProvider
from findpython.providers.uv import UvProvider

if sys.platform == "win32":
pytest.skip("Skip POSIX tests on Windows", allow_module_level=True)
Expand Down Expand Up @@ -93,3 +94,34 @@ def test_find_python_from_rye_provider(mocked_python, tmp_path, monkeypatch):

find_311 = Finder(selected_providers=["rye"]).find_all(3, 11)
assert python311 in find_311


def test_find_python_from_uv_provider(mocked_python, tmp_path, monkeypatch):
python310 = mocked_python.add_python(
tmp_path / ".local/share/uv/python/cpython@3.10.9/install/bin/python3", "3.10.9"
)
python311 = mocked_python.add_python(
tmp_path / ".local/share/uv/python/cpython@3.11.8/bin/python3", "3.11.8"
)
monkeypatch.setenv("HOME", str(tmp_path))

register_provider(UvProvider)
find_310 = Finder(selected_providers=["uv"]).find_all(3, 10)
assert python310 in find_310

find_311 = Finder(selected_providers=["uv"]).find_all(3, 11)
assert python311 in find_311

monkeypatch.setenv("XDG_DATA_HOME", str(tmp_path / "xdg"))
python310_xdg = mocked_python.add_python(
tmp_path / "xdg/uv/python/cpython@3.10.9/install/bin/python3", "3.10.9"
)
find_310 = Finder(selected_providers=["uv"]).find_all(3, 10)
assert python310_xdg in find_310

monkeypatch.setenv("UV_PYTHON_INSTALL_DIR", str(tmp_path / "uv_dir"))
python311_uv_dir = mocked_python.add_python(
tmp_path / "uv_dir/cpython@3.11.8/bin/python3", "3.11.8"
)
find_311 = Finder(selected_providers=["uv"]).find_all(3, 11)
assert python311_uv_dir in find_311
Loading