From 2ca39f1a2dcd379b16a82910eb63eaf521617694 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 11 Dec 2024 14:59:48 -0500 Subject: [PATCH] Skip root when assessing prefix viability (#9823) ## Summary In CPython, it appears that `/` is not considered as a valid path in `search_up`: ```c static PyObject * getpath_dirname(PyObject *Py_UNUSED(self), PyObject *args) { PyObject *path; if (!PyArg_ParseTuple(args, "U", &path)) { return NULL; } Py_ssize_t end = PyUnicode_GET_LENGTH(path); Py_ssize_t pos = PyUnicode_FindChar(path, SEP, 0, end, -1); if (pos < 0) { return PyUnicode_FromStringAndSize(NULL, 0); } return PyUnicode_Substring(path, 0, pos); } ``` ```python def search_up(prefix, *landmarks, test=isfile): while prefix: if any(test(joinpath(prefix, f)) for f in landmarks): return prefix prefix = dirname(prefix) ``` Closes https://github.com/astral-sh/uv/issues/9818. --- crates/uv-virtualenv/src/virtualenv.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/uv-virtualenv/src/virtualenv.rs b/crates/uv-virtualenv/src/virtualenv.rs index 85438c734..e3412992b 100644 --- a/crates/uv-virtualenv/src/virtualenv.rs +++ b/crates/uv-virtualenv/src/virtualenv.rs @@ -655,6 +655,12 @@ fn copy_launcher_windows( /// /// See: fn find_base_python(executable: &Path, major: u8, minor: u8) -> Result { + /// Returns `true` if `path` is the root directory. + fn is_root(path: &Path) -> bool { + let mut components = path.components(); + components.next() == Some(std::path::Component::RootDir) && components.next().is_none() + } + /// Determining whether `dir` is a valid Python prefix by searching for a "landmark". /// /// See: @@ -678,7 +684,7 @@ fn find_base_python(executable: &Path, major: u8, minor: u8) -> Result