diff --git a/python/uv/_find_uv.py b/python/uv/_find_uv.py index 4d1940d75..c0668e959 100644 --- a/python/uv/_find_uv.py +++ b/python/uv/_find_uv.py @@ -16,16 +16,22 @@ def find_uv_bin() -> str: targets = [ # The scripts directory for the current Python sysconfig.get_path("scripts"), - # The scripts directory for the base prefix (if different) + # 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()), - # Adjacent to the package root, e.g. from, `pip install --target` - os.path.join(os.path.dirname(os.path.dirname(__file__)), "bin"), + # Above the package root, e.g., from `pip install --prefix` + # with module path `/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 `/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) @@ -39,6 +45,26 @@ def find_uv_bin() -> str: ) +def _module_path() -> str | None: + path = os.path.dirname(__file__) + return path + + +def _parents(path: str | None, n: int) -> str | None: + if not path: + return None + parts = path.split(os.sep) + if len(parts) < n: + return None + return os.sep.join(parts[:-n]) + + +def _join(path: str | None, *parts: str) -> str | None: + if not path: + return None + return os.path.join(path, *parts) + + def _user_scheme() -> str: if sys.version_info >= (3, 10): user_scheme = sysconfig.get_preferred_scheme("user")