Allow fallback to Python download on non-critical discovery errors (#10908)

Closes https://github.com/astral-sh/uv/issues/10898

In #10716, I broke fallback to downloading Python versions by throwing a
different error kind.
This commit is contained in:
Zanie Blue 2025-01-23 16:37:02 -06:00 committed by GitHub
parent 2a0fa8a8ee
commit cbf6d5af9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 45 additions and 37 deletions

View file

@ -92,36 +92,48 @@ impl PythonInstallation {
let request = request.unwrap_or(&PythonRequest::Default); let request = request.unwrap_or(&PythonRequest::Default);
// Search for the installation // Search for the installation
match Self::find(request, environments, preference, cache) { let err = match Self::find(request, environments, preference, cache) {
Ok(venv) => Ok(venv), Ok(installation) => return Ok(installation),
// If missing and allowed, perform a fetch Err(err) => err,
Err(Error::MissingPython(err)) };
if preference.allows_managed()
&& python_downloads.is_automatic() let downloads_enabled = preference.allows_managed()
&& client_builder.connectivity.is_online() => && python_downloads.is_automatic()
{ && client_builder.connectivity.is_online();
if let Some(request) = PythonDownloadRequest::from_request(request) {
debug!("Requested Python not found, checking for available download..."); if !downloads_enabled {
match Self::fetch( return Err(err);
request.fill()?, }
client_builder,
cache, match err {
reporter, // If Python is missing, we should attempt a download
python_install_mirror, Error::MissingPython(_) => {}
pypy_install_mirror, // If we raised a non-critical error, we should attempt a download
) Error::Discovery(ref err) if !err.is_critical() => {}
.await // Otherwise, this is fatal
{ _ => return Err(err),
Ok(installation) => Ok(installation), }
Err(Error::Download(downloads::Error::NoDownloadFound(_))) => {
Err(Error::MissingPython(err)) // If we can't convert the request to a download, throw the original error
} let Some(request) = PythonDownloadRequest::from_request(request) else {
Err(err) => Err(err), return Err(err);
} };
} else {
Err(Error::MissingPython(err)) debug!("Requested Python not found, checking for available download...");
} match Self::fetch(
} request.fill()?,
client_builder,
cache,
reporter,
python_install_mirror,
pypy_install_mirror,
)
.await
{
Ok(installation) => Ok(installation),
// Throw the original error if we couldn't find a download
Err(Error::Download(downloads::Error::NoDownloadFound(_))) => Err(err),
// But if the download failed, throw that error
Err(err) => Err(err), Err(err) => Err(err),
} }
} }

View file

@ -188,16 +188,12 @@ fn python_install_automatic() {
.env("UV_TEST_PYTHON_PATH", context.bin_dir.as_os_str()) .env("UV_TEST_PYTHON_PATH", context.bin_dir.as_os_str())
.arg("-p").arg("3.11") .arg("-p").arg("3.11")
.arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r###" .arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r###"
success: false success: true
exit_code: 2 exit_code: 0
----- stdout ----- ----- stdout -----
(3, 11)
----- stderr ----- ----- stderr -----
error: Failed to inspect Python interpreter from search path at `[BIN]/python3`
Caused by: Querying Python at `[BIN]/python3` failed with exit status exit status: 1
[stderr]
error: intentionally broken python executable
"###); "###);
} }
} }