Skip to content

Commit

Permalink
Improve handling of missing interpreters during discovery (#4218)
Browse files Browse the repository at this point in the history
Cherry-picked from #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.
  • Loading branch information
zanieb authored Jun 10, 2024
1 parent 0c1dcb7 commit 98d1ea6
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 50 deletions.
4 changes: 4 additions & 0 deletions crates/uv-toolchain/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
13 changes: 11 additions & 2 deletions crates/uv-toolchain/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
40 changes: 13 additions & 27 deletions crates/uv/tests/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 -----
----- 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)
"###
);
}
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
Resolved 0 packages in [TIME]
"###
);

context
.temp_dir
Expand Down
29 changes: 8 additions & 21 deletions crates/uv/tests/pip_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 -----
----- 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)
"###);
}
uv_snapshot!(context.filters(), sync_without_exclude_newer(&context).arg("requirements.txt"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: No Python interpreters found in virtual environments
"###);

assert!(predicates::path::missing().eval(&context.venv));

Expand Down

0 comments on commit 98d1ea6

Please sign in to comment.