diff --git a/crates/uv-toolchain/src/discovery.rs b/crates/uv-toolchain/src/discovery.rs index f4a9974ee..72d20b4b2 100644 --- a/crates/uv-toolchain/src/discovery.rs +++ b/crates/uv-toolchain/src/discovery.rs @@ -438,6 +438,10 @@ fn should_stop_discovery(err: &Error) -> bool { trace!("Skipping bad interpreter at {}", path.display()); false } + InterpreterError::NotFound(path) => { + trace!("Skipping missing interpreter at {}", path.display()); + false + } }, _ => true, } diff --git a/crates/uv-toolchain/src/interpreter.rs b/crates/uv-toolchain/src/interpreter.rs index d88dd4573..9f772c2e8 100644 --- a/crates/uv-toolchain/src/interpreter.rs +++ b/crates/uv-toolchain/src/interpreter.rs @@ -454,8 +454,10 @@ impl ExternallyManaged { #[derive(Debug, Error)] pub enum Error { - #[error(transparent)] + #[error("Failed to query Python interpreter")] Io(#[from] io::Error), + #[error("Python interpreter not found at `{0}`")] + NotFound(PathBuf), #[error("Failed to query Python interpreter at `{path}`")] SpawnFailed { path: PathBuf, @@ -645,7 +647,14 @@ impl InterpreterInfo { // We check the timestamp of the canonicalized executable to check if an underlying // interpreter has been modified - let modified = Timestamp::from_path(uv_fs::canonicalize_executable(executable)?)?; + let modified = + Timestamp::from_path(uv_fs::canonicalize_executable(executable).map_err(|err| { + if err.kind() == io::ErrorKind::NotFound { + Error::NotFound(executable.to_path_buf()) + } else { + err.into() + } + })?)?; // Read from the cache. if cache diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index ca1a9f297..52c2895da 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -129,33 +129,19 @@ fn missing_venv() -> Result<()> { context.temp_dir.child("requirements.in").touch()?; fs_err::remove_dir_all(context.temp_dir.child(".venv").path())?; - if cfg!(windows) { - uv_snapshot!(context.filters(), context.compile() - .arg("requirements.in"), @r###" - success: false - exit_code: 2 - ----- stdout ----- + uv_snapshot!(context.filters(), context.compile() + .arg("requirements.in"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in - ----- stderr ----- - warning: Requirements file requirements.in does not contain any dependencies - error: failed to canonicalize path `[VENV]/Scripts/python.exe` - Caused by: The system cannot find the path specified. (os error 3) - "### - ); - } else { - uv_snapshot!(context.filters(), context.compile() - .arg("requirements.in"), @r###" - success: false - exit_code: 2 - ----- stdout ----- - - ----- stderr ----- - warning: Requirements file requirements.in does not contain any dependencies - error: failed to canonicalize path `[VENV]/bin/python3` - Caused by: No such file or directory (os error 2) - "### - ); - } + ----- stderr ----- + warning: Requirements file requirements.in does not contain any dependencies + Resolved 0 packages in [TIME] + "### + ); context .temp_dir diff --git a/crates/uv/tests/pip_sync.rs b/crates/uv/tests/pip_sync.rs index b675b7872..e78c1c8b5 100644 --- a/crates/uv/tests/pip_sync.rs +++ b/crates/uv/tests/pip_sync.rs @@ -110,27 +110,14 @@ fn missing_venv() -> Result<()> { requirements.write_str("anyio")?; fs::remove_dir_all(&context.venv)?; - if cfg!(windows) { - uv_snapshot!(context.filters(), sync_without_exclude_newer(&context).arg("requirements.txt"), @r###" - success: false - exit_code: 2 - ----- stdout ----- + uv_snapshot!(context.filters(), sync_without_exclude_newer(&context).arg("requirements.txt"), @r###" + success: false + exit_code: 2 + ----- stdout ----- - ----- stderr ----- - error: failed to canonicalize path `[VENV]/Scripts/python.exe` - Caused by: The system cannot find the path specified. (os error 3) - "###); - } else { - uv_snapshot!(context.filters(), sync_without_exclude_newer(&context).arg("requirements.txt"), @r###" - success: false - exit_code: 2 - ----- stdout ----- - - ----- stderr ----- - error: failed to canonicalize path `[VENV]/bin/python3` - Caused by: No such file or directory (os error 2) - "###); - } + ----- stderr ----- + error: No Python interpreters found in virtual environments + "###); assert!(predicates::path::missing().eval(&context.venv));