Repository: astral-sh/uv
File: python/uv/_find_uv.py (Python)

Code before:
import os
import sys
import sysconfig


class UvNotFound(FileNotFoundError): ...


def find_uv_bin() -> str:
    """Return the uv binary path."""

    uv_exe = "uv" + sysconfig.get_config_var("EXE")

    targets = [
        # The scripts directory for the current Python
        sysconfig.get_path("scripts"),
        # The scripts directory for the base prefix
        sysconfig.get_path("scripts", vars={"base": sys.base_prefix}),
        # The user scheme scripts directory, e.g., `~/.local/bin`
        sysconfig.get_path("scripts", scheme=_user_scheme()),
        # Above the package root, e.g., from `pip install --prefix`
        # with module path `<prefix>/lib/python3.13/site-packages/uv`
        _join(_parents(_module_path(), 4), "bin"),
        # Adjacent to the package root, e.g., from `pip install --target`
        # with module path `<target>/uv`
        _join(_parents(_module_path(), 1), "bin"),
    ]

    seen = set()
    for target in targets:
        if not target:
            continue
        if target in seen:
            continue
        seen.add(target)
        path = os.path.join(target, uv_exe)
        if os.path.isfile(path):
            return path

    raise UvNotFound(
        f"Could not find the uv binary in any of the following locations:\n"
        f"{os.linesep.join(f' - {target}' for target in seen)}\n"
    )


def _module_path() -> str | None:
    path = os.path.dirname(__file__)
    return path


def _parents(path: str | None, n: int) -> str | None:

Review comment (suggestion):
Can you add tests for the prefix and the target case? We have to emulate this by copying our python files and the built test binary manually, but it catches cases such as https://github.com/astral-sh/uv/pull/14184#discussion_r2160101023 and the user scheme preference.

Code after:
import os
import sys
import sysconfig


class UvNotFound(FileNotFoundError): ...


def find_uv_bin() -> str:
    """Return the uv binary path."""

    uv_exe = "uv" + sysconfig.get_config_var("EXE")

    targets = [
        # The scripts directory for the current Python
        sysconfig.get_path("scripts"),
        # The scripts directory for the base prefix
        sysconfig.get_path("scripts", vars={"base": sys.base_prefix}),
        # The user scheme scripts directory, e.g., `~/.local/bin`
        sysconfig.get_path("scripts", scheme=_user_scheme()),
        # Above the package root, e.g., from `pip install --prefix` or `uv run --with`
        (
            # On Windows, with module path `<prefix>/Lib/site-packages/uv`
            _join(_matching_parents(_module_path(), "Lib/site-packages/uv"), "Scripts")
            if sys.platform == "win32"
            # On Unix,  with module path `<prefix>/lib/python3.13/site-packages/uv`
            else _join(
                _matching_parents(_module_path(), "lib/python*/site-packages/uv"), "bin"
            )
        ),
        # Adjacent to the package root, e.g., from `pip install --target`
        # with module path `<target>/uv`
        _join(_matching_parents(_module_path(), "uv"), "bin"),
    ]

    seen = []
    for target in targets:
        if not target:
            continue
        if target in seen:
            continue
        seen.append(target)
        path = os.path.join(target, uv_exe)
        if os.path.isfile(path):
            return path

    raise UvNotFound(
        f"Could not find the uv binary in any of the following locations:\n"
        f"{os.linesep.join(f' - {target}' for target in seen)}\n"
    )