Skip to content

Commit ae85910

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 5b25e89 commit ae85910

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

crates/uv-python/src/downloads.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ pub enum Error {
9696
"Remote python downloads JSON is not yet supported, please use a local path (without `file://` prefix)"
9797
)]
9898
RemoteJSONNotSupported(),
99-
#[error("The json of the python downloads is invalid: {0}")]
100-
InvalidPythonDownloadsJSON(String, #[source] serde_json::Error),
99+
#[error("The JSON of the python downloads is invalid: {0}")]
100+
InvalidPythonDownloadsJSON(PathBuf, #[source] serde_json::Error),
101101
#[error("An offline Python installation was requested, but {file} (from {url}) is missing in {}", python_builds_dir.user_display())]
102102
OfflinePythonMissing {
103103
file: Box<PythonInstallationKey>,
@@ -554,20 +554,26 @@ impl ManagedPythonDownload {
554554
let json_downloads: HashMap<String, JsonPythonDownload> = if let Some(json_source) =
555555
python_downloads_json_url
556556
{
557-
if Url::parse(json_source).is_ok() {
558-
return Err(Error::RemoteJSONNotSupported());
559-
}
560-
561-
let file = match fs_err::File::open(json_source) {
562-
Ok(file) => file,
563-
Err(e) => { Err(Error::Io(e)) }?,
557+
let json_source = if let Ok(url) = Url::parse(json_source) {
558+
if let Ok(path) = url.to_file_path() {
559+
Cow::Owned(path)
560+
} else if url.scheme().len() > 1 {
561+
// Schemes of length 1 are likely Windows drive letters.
562+
return Err(Error::RemoteJSONNotSupported());
563+
} else {
564+
Cow::Borrowed(Path::new(json_source))
565+
}
566+
} else {
567+
Cow::Borrowed(Path::new(json_source))
564568
};
565569

570+
let file = fs_err::File::open(json_source.as_ref())?;
571+
566572
serde_json::from_reader(file)
567-
.map_err(|e| Error::InvalidPythonDownloadsJSON(json_source.to_string(), e))?
573+
.map_err(|e| Error::InvalidPythonDownloadsJSON(json_source.to_path_buf(), e))?
568574
} else {
569575
serde_json::from_str(BUILTIN_PYTHON_DOWNLOADS_JSON).map_err(|e| {
570-
Error::InvalidPythonDownloadsJSON("EMBEDDED IN THE BINARY".to_string(), e)
576+
Error::InvalidPythonDownloadsJSON(PathBuf::from("EMBEDDED IN THE BINARY"), e)
571577
})?
572578
};
573579

0 commit comments

Comments
 (0)