mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-28 18:54:10 +00:00
Show non-critical Python discovery errors if no other interpreter is found (#10716)
Previously, these errors would only be visible in the debug logs as "Skipping bad interpreter ..." which can lead us to making some ridiculous claims like "There is no virtual environment" or "Python is not installed" when really we just failed to query the interpreter for some reason. We show the first error, sort of arbitrarily — but I think it matches user expectation, i.e., this would be the first Python on your PATH. Related to #10713
This commit is contained in:
parent
a62b891e6a
commit
b543881b1b
5 changed files with 39 additions and 11 deletions
|
|
@ -977,9 +977,16 @@ pub(crate) fn find_python_installation(
|
||||||
) -> Result<FindPythonResult, Error> {
|
) -> Result<FindPythonResult, Error> {
|
||||||
let installations = find_python_installations(request, environments, preference, cache);
|
let installations = find_python_installations(request, environments, preference, cache);
|
||||||
let mut first_prerelease = None;
|
let mut first_prerelease = None;
|
||||||
|
let mut first_error = None;
|
||||||
for result in installations {
|
for result in installations {
|
||||||
// Iterate until the first critical error or happy result
|
// Iterate until the first critical error or happy result
|
||||||
if !result.as_ref().err().map_or(true, Error::is_critical) {
|
if !result.as_ref().err().map_or(true, Error::is_critical) {
|
||||||
|
// Track the first non-critical error
|
||||||
|
if first_error.is_none() {
|
||||||
|
if let Err(err) = result {
|
||||||
|
first_error = Some(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1032,6 +1039,12 @@ pub(crate) fn find_python_installation(
|
||||||
return Ok(Ok(installation));
|
return Ok(Ok(installation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we found a Python, but it was unusable for some reason, report that instead of saying we
|
||||||
|
// couldn't find any Python interpreters.
|
||||||
|
if let Some(err) = first_error {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Err(PythonNotFound {
|
Ok(Err(PythonNotFound {
|
||||||
request: request.clone(),
|
request: request.clone(),
|
||||||
environment_preference: environments,
|
environment_preference: environments,
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ mod tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
discovery::{
|
discovery::{
|
||||||
find_best_python_installation, find_python_installation, EnvironmentPreference,
|
self, find_best_python_installation, find_python_installation, EnvironmentPreference,
|
||||||
},
|
},
|
||||||
PythonPreference,
|
PythonPreference,
|
||||||
};
|
};
|
||||||
|
|
@ -589,11 +589,10 @@ mod tests {
|
||||||
PythonPreference::default(),
|
PythonPreference::default(),
|
||||||
&context.cache,
|
&context.cache,
|
||||||
)
|
)
|
||||||
})?;
|
});
|
||||||
assert!(
|
assert!(
|
||||||
matches!(result, Err(PythonNotFound { .. })),
|
matches!(result, Err(discovery::Error::Query(..))),
|
||||||
// TODO(zanieb): We could improve the error handling to hint this to the user
|
"If only Python 2 is available, we should report the interpreter query error; got {result:?}"
|
||||||
"If only Python 2 is available, we should not find a python; got {result:?}"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -636,7 +636,7 @@ impl TestContext {
|
||||||
.env(EnvVars::UV_PREVIEW, "1")
|
.env(EnvVars::UV_PREVIEW, "1")
|
||||||
.env(EnvVars::UV_PYTHON_INSTALL_DIR, "")
|
.env(EnvVars::UV_PYTHON_INSTALL_DIR, "")
|
||||||
.current_dir(&self.temp_dir);
|
.current_dir(&self.temp_dir);
|
||||||
self.add_shared_args(&mut command, true);
|
self.add_shared_args(&mut command, false);
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,10 @@ fn missing_requirements_txt() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn missing_venv() -> Result<()> {
|
fn missing_venv() -> Result<()> {
|
||||||
let context = TestContext::new("3.12");
|
let context = TestContext::new("3.12")
|
||||||
|
.with_filtered_virtualenv_bin()
|
||||||
|
.with_filtered_python_names();
|
||||||
|
|
||||||
let requirements = context.temp_dir.child("requirements.txt");
|
let requirements = context.temp_dir.child("requirements.txt");
|
||||||
requirements.write_str("anyio")?;
|
requirements.write_str("anyio")?;
|
||||||
fs::remove_dir_all(&context.venv)?;
|
fs::remove_dir_all(&context.venv)?;
|
||||||
|
|
@ -61,6 +64,19 @@ fn missing_venv() -> Result<()> {
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: Failed to inspect Python interpreter from active virtual environment at `.venv/[BIN]/python`
|
||||||
|
Caused by: Python interpreter not found at `[VENV]/[BIN]/python`
|
||||||
|
"###);
|
||||||
|
|
||||||
|
assert!(predicates::path::missing().eval(&context.venv));
|
||||||
|
|
||||||
|
// If not "active", we hint to create one
|
||||||
|
uv_snapshot!(context.filters(), context.pip_sync().arg("requirements.txt").env_remove("VIRTUAL_ENV"), @r###"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
error: No virtual environment found; run `uv venv` to create an environment, or pass `--system` to install into a non-virtual environment
|
error: No virtual environment found; run `uv venv` to create an environment, or pass `--system` to install into a non-virtual environment
|
||||||
"###);
|
"###);
|
||||||
|
|
|
||||||
|
|
@ -569,7 +569,7 @@ fn python_find_venv_invalid() {
|
||||||
.with_filtered_virtualenv_bin();
|
.with_filtered_virtualenv_bin();
|
||||||
|
|
||||||
// We find the virtual environment
|
// We find the virtual environment
|
||||||
uv_snapshot!(context.filters(), context.python_find(), @r###"
|
uv_snapshot!(context.filters(), context.python_find().env(EnvVars::VIRTUAL_ENV, context.venv.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
@ -581,7 +581,7 @@ fn python_find_venv_invalid() {
|
||||||
// If the binaries are missing from a virtual environment, we fail
|
// If the binaries are missing from a virtual environment, we fail
|
||||||
fs_err::remove_dir_all(venv_bin_path(&context.venv)).unwrap();
|
fs_err::remove_dir_all(venv_bin_path(&context.venv)).unwrap();
|
||||||
|
|
||||||
uv_snapshot!(context.filters(), context.python_find(), @r###"
|
uv_snapshot!(context.filters(), context.python_find().env(EnvVars::VIRTUAL_ENV, context.venv.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
@ -592,7 +592,7 @@ fn python_find_venv_invalid() {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Unless the virtual environment is not active
|
// Unless the virtual environment is not active
|
||||||
uv_snapshot!(context.filters(), context.python_find().env_remove(EnvVars::VIRTUAL_ENV), @r###"
|
uv_snapshot!(context.filters(), context.python_find(), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
@ -604,7 +604,7 @@ fn python_find_venv_invalid() {
|
||||||
// If there's not a `pyvenv.cfg` file, it's also non-fatal, we ignore the environment
|
// If there's not a `pyvenv.cfg` file, it's also non-fatal, we ignore the environment
|
||||||
fs_err::remove_file(context.venv.join("pyvenv.cfg")).unwrap();
|
fs_err::remove_file(context.venv.join("pyvenv.cfg")).unwrap();
|
||||||
|
|
||||||
uv_snapshot!(context.filters(), context.python_find(), @r###"
|
uv_snapshot!(context.filters(), context.python_find().env(EnvVars::VIRTUAL_ENV, context.venv.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue