From e9d833cec70509fbb7d4105c84a76ddd058a1d7c Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Wed, 10 Jun 2026 13:01:12 -0500 Subject: [PATCH] Fix explicit paths in parallel Python listing --- crates/uv-python/src/discovery.rs | 28 ++++++++++------- crates/uv/tests/python/python_list.rs | 45 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/crates/uv-python/src/discovery.rs b/crates/uv-python/src/discovery.rs index f6daefc94137b..9c12a237eac77 100644 --- a/crates/uv-python/src/discovery.rs +++ b/crates/uv-python/src/discovery.rs @@ -1274,12 +1274,14 @@ pub fn find_all_python_installations( source: PythonSource::ProvidedPath, interpreter, }]), - Err(InterpreterError::NotFound(_) | InterpreterError::BrokenLink(_)) => Ok(vec![]), - Err(err) => Err(Error::Query( - Box::new(err), - path.clone(), - PythonSource::ProvidedPath, - )), + Err(err) => { + let err = Error::Query(Box::new(err), path.clone(), PythonSource::ProvidedPath); + if err.is_critical() { + Err(err) + } else { + Ok(vec![]) + } + } } } PythonRequest::Directory(path) => { @@ -1287,12 +1289,14 @@ pub fn find_all_python_installations( debug!("Checking for Python interpreter in {request}"); match python_installation_from_directory(path, cache) { Ok(installation) => Ok(vec![installation]), - Err(InterpreterError::NotFound(_) | InterpreterError::BrokenLink(_)) => Ok(vec![]), - Err(err) => Err(Error::Query( - Box::new(err), - path.clone(), - PythonSource::ProvidedPath, - )), + Err(err) => { + let err = Error::Query(Box::new(err), path.clone(), PythonSource::ProvidedPath); + if err.is_critical() { + Err(err) + } else { + Ok(vec![]) + } + } } } PythonRequest::ExecutableName(name) => { diff --git a/crates/uv/tests/python/python_list.rs b/crates/uv/tests/python/python_list.rs index 9a2e41ae5d3a8..c94f23554acc4 100644 --- a/crates/uv/tests/python/python_list.rs +++ b/crates/uv/tests/python/python_list.rs @@ -131,6 +131,51 @@ fn python_list() { "); } +#[cfg(unix)] +#[test] +fn python_list_ignores_noncritical_explicit_path_errors() -> Result<()> { + use std::os::unix::fs::PermissionsExt; + + let context = uv_test::test_context_with_versions!(&[]); + let contents = r"#!/bin/sh + echo 'error: intentionally broken python executable' >&2 + exit 1"; + + let python = context.temp_dir.join("python"); + fs_err::write(&python, contents)?; + let mut permissions = fs_err::metadata(&python)?.permissions(); + permissions.set_mode(0o755); + fs_err::set_permissions(&python, permissions)?; + + uv_snapshot!(context.filters(), context.python_list() + .arg(&python) + .arg("--only-installed"), @" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + "); + + let environment = context.temp_dir.join("environment"); + let environment_bin = environment.join("bin"); + let environment_python = environment_bin.join("python"); + fs_err::create_dir_all(&environment_bin)?; + fs_err::copy(&python, &environment_python)?; + + uv_snapshot!(context.filters(), context.python_list() + .arg(&environment) + .arg("--only-installed"), @" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + "); + + Ok(()) +} + #[test] fn python_list_pin() { let context = uv_test::test_context_with_versions!(&["3.11", "3.12"])