Improve handling of missing interpreters during discovery (#4218)

Cherry-picked from https://github.com/astral-sh/uv/pull/4214

The first commit gets us some context on an IO error during queries:

Previously:

```
failed to canonicalize path `[VENV]/bin/python3`
    Caused by: No such file or directory (os error 2)
```

Now:

```
Failed to query Python interpreter
    Caused by: failed to canonicalize path `[VENV]/bin/python3`
    Caused by: No such file or directory (os error 2)
```

but really we shouldn't attempt to query a missing interpreter during
discovery anyway, so we improve handling of that too.
This commit is contained in:
Zanie Blue 2024-06-10 18:26:34 -04:00 committed by GitHub
parent 0c1dcb797a
commit 98d1ea6bb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 34 additions and 48 deletions

View File

@ -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,
}

View File

@ -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

View File

@ -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

View File

@ -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));