Skip to content

Commit cbf6d5a

Browse files
authored
Allow fallback to Python download on non-critical discovery errors (#10908)
Closes #10898 In #10716, I broke fallback to downloading Python versions by throwing a different error kind.
1 parent 2a0fa8a commit cbf6d5a

File tree

2 files changed

+45
-37
lines changed

2 files changed

+45
-37
lines changed

crates/uv-python/src/installation.rs

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -92,36 +92,48 @@ impl PythonInstallation {
9292
let request = request.unwrap_or(&PythonRequest::Default);
9393

9494
// Search for the installation
95-
match Self::find(request, environments, preference, cache) {
96-
Ok(venv) => Ok(venv),
97-
// If missing and allowed, perform a fetch
98-
Err(Error::MissingPython(err))
99-
if preference.allows_managed()
100-
&& python_downloads.is_automatic()
101-
&& client_builder.connectivity.is_online() =>
102-
{
103-
if let Some(request) = PythonDownloadRequest::from_request(request) {
104-
debug!("Requested Python not found, checking for available download...");
105-
match Self::fetch(
106-
request.fill()?,
107-
client_builder,
108-
cache,
109-
reporter,
110-
python_install_mirror,
111-
pypy_install_mirror,
112-
)
113-
.await
114-
{
115-
Ok(installation) => Ok(installation),
116-
Err(Error::Download(downloads::Error::NoDownloadFound(_))) => {
117-
Err(Error::MissingPython(err))
118-
}
119-
Err(err) => Err(err),
120-
}
121-
} else {
122-
Err(Error::MissingPython(err))
123-
}
124-
}
95+
let err = match Self::find(request, environments, preference, cache) {
96+
Ok(installation) => return Ok(installation),
97+
Err(err) => err,
98+
};
99+
100+
let downloads_enabled = preference.allows_managed()
101+
&& python_downloads.is_automatic()
102+
&& client_builder.connectivity.is_online();
103+
104+
if !downloads_enabled {
105+
return Err(err);
106+
}
107+
108+
match err {
109+
// If Python is missing, we should attempt a download
110+
Error::MissingPython(_) => {}
111+
// If we raised a non-critical error, we should attempt a download
112+
Error::Discovery(ref err) if !err.is_critical() => {}
113+
// Otherwise, this is fatal
114+
_ => return Err(err),
115+
}
116+
117+
// If we can't convert the request to a download, throw the original error
118+
let Some(request) = PythonDownloadRequest::from_request(request) else {
119+
return Err(err);
120+
};
121+
122+
debug!("Requested Python not found, checking for available download...");
123+
match Self::fetch(
124+
request.fill()?,
125+
client_builder,
126+
cache,
127+
reporter,
128+
python_install_mirror,
129+
pypy_install_mirror,
130+
)
131+
.await
132+
{
133+
Ok(installation) => Ok(installation),
134+
// Throw the original error if we couldn't find a download
135+
Err(Error::Download(downloads::Error::NoDownloadFound(_))) => Err(err),
136+
// But if the download failed, throw that error
125137
Err(err) => Err(err),
126138
}
127139
}

crates/uv/tests/it/python_install.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,16 +188,12 @@ fn python_install_automatic() {
188188
.env("UV_TEST_PYTHON_PATH", context.bin_dir.as_os_str())
189189
.arg("-p").arg("3.11")
190190
.arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r###"
191-
success: false
192-
exit_code: 2
191+
success: true
192+
exit_code: 0
193193
----- stdout -----
194+
(3, 11)
194195
195196
----- stderr -----
196-
error: Failed to inspect Python interpreter from search path at `[BIN]/python3`
197-
Caused by: Querying Python at `[BIN]/python3` failed with exit status exit status: 1
198-
199-
[stderr]
200-
error: intentionally broken python executable
201197
"###);
202198
}
203199
}

0 commit comments

Comments
 (0)