Skip to content

Commit 075166a

Browse files
committed
Windows paths are valid URLs
Currently, it is not possible to set a custom Python downloads JSON on Windows, as Windows paths can be valid URLs. ```rust use url::Url; fn main() { dbg!(Url::parse(r"C:\Users\Ferris\download.json")); } ``` Tested by #13585 (where it is currently failing CI)
1 parent de64f1d commit 075166a

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

crates/uv-python/src/downloads.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,10 @@ pub enum Error {
9393
Mirror(&'static str, &'static str),
9494
#[error(transparent)]
9595
LibcDetection(#[from] LibcDetectionError),
96-
#[error(
97-
"Remote python downloads JSON is not yet supported, please use a local path (without `file://` prefix)"
98-
)]
99-
RemoteJSONNotSupported(),
100-
#[error("The json of the python downloads is invalid: {0}")]
101-
InvalidPythonDownloadsJSON(String, #[source] serde_json::Error),
96+
#[error("Remote python downloads JSON is not yet supported, please use a local path")]
97+
RemoteJSONNotSupported,
98+
#[error("The JSON of the python downloads is invalid: {0}")]
99+
InvalidPythonDownloadsJSON(PathBuf, #[source] serde_json::Error),
102100
#[error("An offline Python installation was requested, but {file} (from {url}) is missing in {}", python_builds_dir.user_display())]
103101
OfflinePythonMissing {
104102
file: Box<PythonInstallationKey>,
@@ -559,20 +557,26 @@ impl ManagedPythonDownload {
559557
let json_downloads: HashMap<String, JsonPythonDownload> = if let Some(json_source) =
560558
python_downloads_json_url
561559
{
562-
if Url::parse(json_source).is_ok() {
563-
return Err(Error::RemoteJSONNotSupported());
564-
}
565-
566-
let file = match fs_err::File::open(json_source) {
567-
Ok(file) => file,
568-
Err(e) => { Err(Error::Io(e)) }?,
560+
// Windows paths are also valid URLs
561+
let json_source = if let Ok(url) = Url::parse(json_source) {
562+
if let Ok(path) = url.to_file_path() {
563+
Cow::Owned(path)
564+
} else if matches!(url.scheme(), "http" | "https") {
565+
return Err(Error::RemoteJSONNotSupported);
566+
} else {
567+
Cow::Borrowed(Path::new(json_source))
568+
}
569+
} else {
570+
Cow::Borrowed(Path::new(json_source))
569571
};
570572

573+
let file = fs_err::File::open(json_source.as_ref())?;
574+
571575
serde_json::from_reader(file)
572-
.map_err(|e| Error::InvalidPythonDownloadsJSON(json_source.to_string(), e))?
576+
.map_err(|e| Error::InvalidPythonDownloadsJSON(json_source.to_path_buf(), e))?
573577
} else {
574578
serde_json::from_str(BUILTIN_PYTHON_DOWNLOADS_JSON).map_err(|e| {
575-
Error::InvalidPythonDownloadsJSON("EMBEDDED IN THE BINARY".to_string(), e)
579+
Error::InvalidPythonDownloadsJSON(PathBuf::from("EMBEDDED IN THE BINARY"), e)
576580
})?
577581
};
578582

0 commit comments

Comments
 (0)