Fix PythonDownloadRequest parsing for partial keys (#12925)
In #12909, I noticed we failed to parse partial download keys with `any` placeholders. Here, parsing for that is fixed.
This commit is contained in:
@@ -2705,12 +2705,15 @@ mod tests {
|
||||
use std::{path::PathBuf, str::FromStr};
|
||||
|
||||
use assert_fs::{prelude::*, TempDir};
|
||||
use target_lexicon::{Aarch64Architecture, Architecture};
|
||||
use test_log::test;
|
||||
use uv_pep440::{Prerelease, PrereleaseKind, VersionSpecifiers};
|
||||
|
||||
use crate::{
|
||||
discovery::{PythonRequest, VersionRequest},
|
||||
downloads::PythonDownloadRequest,
|
||||
implementation::ImplementationName,
|
||||
platform::{Arch, Libc, Os},
|
||||
};
|
||||
|
||||
use super::{Error, PythonVariant};
|
||||
@@ -2763,6 +2766,7 @@ mod tests {
|
||||
PythonRequest::parse("cpython"),
|
||||
PythonRequest::Implementation(ImplementationName::CPython)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
PythonRequest::parse("cpython3.12.2"),
|
||||
PythonRequest::ImplementationVersion(
|
||||
@@ -2770,6 +2774,78 @@ mod tests {
|
||||
VersionRequest::from_str("3.12.2").unwrap(),
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
PythonRequest::parse("cpython-3.13.2"),
|
||||
PythonRequest::Key(PythonDownloadRequest {
|
||||
version: Some(VersionRequest::MajorMinorPatch(
|
||||
3,
|
||||
13,
|
||||
2,
|
||||
PythonVariant::Default
|
||||
)),
|
||||
implementation: Some(ImplementationName::CPython),
|
||||
arch: None,
|
||||
os: None,
|
||||
libc: None,
|
||||
prereleases: None
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
PythonRequest::parse("cpython-3.13.2-macos-aarch64-none"),
|
||||
PythonRequest::Key(PythonDownloadRequest {
|
||||
version: Some(VersionRequest::MajorMinorPatch(
|
||||
3,
|
||||
13,
|
||||
2,
|
||||
PythonVariant::Default
|
||||
)),
|
||||
implementation: Some(ImplementationName::CPython),
|
||||
arch: Some(Arch {
|
||||
family: Architecture::Aarch64(Aarch64Architecture::Aarch64),
|
||||
variant: None
|
||||
}),
|
||||
os: Some(Os(target_lexicon::OperatingSystem::Darwin(None))),
|
||||
libc: Some(Libc::None),
|
||||
prereleases: None
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
PythonRequest::parse("any-3.13.2"),
|
||||
PythonRequest::Key(PythonDownloadRequest {
|
||||
version: Some(VersionRequest::MajorMinorPatch(
|
||||
3,
|
||||
13,
|
||||
2,
|
||||
PythonVariant::Default
|
||||
)),
|
||||
implementation: None,
|
||||
arch: None,
|
||||
os: None,
|
||||
libc: None,
|
||||
prereleases: None
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
PythonRequest::parse("any-3.13.2-any-aarch64"),
|
||||
PythonRequest::Key(PythonDownloadRequest {
|
||||
version: Some(VersionRequest::MajorMinorPatch(
|
||||
3,
|
||||
13,
|
||||
2,
|
||||
PythonVariant::Default
|
||||
)),
|
||||
implementation: None,
|
||||
arch: Some(Arch {
|
||||
family: Architecture::Aarch64(Aarch64Architecture::Aarch64),
|
||||
variant: None
|
||||
}),
|
||||
os: None,
|
||||
libc: None,
|
||||
prereleases: None
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
PythonRequest::parse("pypy"),
|
||||
PythonRequest::Implementation(ImplementationName::PyPy)
|
||||
|
||||
@@ -107,15 +107,15 @@ pub struct ManagedPythonDownload {
|
||||
|
||||
#[derive(Debug, Clone, Default, Eq, PartialEq)]
|
||||
pub struct PythonDownloadRequest {
|
||||
version: Option<VersionRequest>,
|
||||
implementation: Option<ImplementationName>,
|
||||
arch: Option<Arch>,
|
||||
os: Option<Os>,
|
||||
libc: Option<Libc>,
|
||||
pub(crate) version: Option<VersionRequest>,
|
||||
pub(crate) implementation: Option<ImplementationName>,
|
||||
pub(crate) arch: Option<Arch>,
|
||||
pub(crate) os: Option<Os>,
|
||||
pub(crate) libc: Option<Libc>,
|
||||
|
||||
/// Whether to allow pre-releases or not. If not set, defaults to true if [`Self::version`] is
|
||||
/// not None, and false otherwise.
|
||||
prereleases: Option<bool>,
|
||||
pub(crate) prereleases: Option<bool>,
|
||||
}
|
||||
|
||||
impl PythonDownloadRequest {
|
||||
@@ -424,39 +424,29 @@ impl FromStr for PythonDownloadRequest {
|
||||
let mut arch = None;
|
||||
let mut libc = None;
|
||||
|
||||
let mut position = 0;
|
||||
loop {
|
||||
// Consume each part
|
||||
let Some(part) = parts.next() else { break };
|
||||
position += 1;
|
||||
|
||||
if implementation.is_none() {
|
||||
implementation = Some(ImplementationName::from_str(part)?);
|
||||
if part.eq_ignore_ascii_case("any") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if version.is_none() {
|
||||
version = Some(
|
||||
VersionRequest::from_str(part)
|
||||
.map_err(|_| Error::InvalidPythonVersion(part.to_string()))?,
|
||||
);
|
||||
continue;
|
||||
match position {
|
||||
1 => implementation = Some(ImplementationName::from_str(part)?),
|
||||
2 => {
|
||||
version = Some(
|
||||
VersionRequest::from_str(part)
|
||||
.map_err(|_| Error::InvalidPythonVersion(part.to_string()))?,
|
||||
);
|
||||
}
|
||||
3 => os = Some(Os::from_str(part)?),
|
||||
4 => arch = Some(Arch::from_str(part)?),
|
||||
5 => libc = Some(Libc::from_str(part)?),
|
||||
_ => return Err(Error::TooManyParts(s.to_string())),
|
||||
}
|
||||
|
||||
if os.is_none() {
|
||||
os = Some(Os::from_str(part)?);
|
||||
continue;
|
||||
}
|
||||
|
||||
if arch.is_none() {
|
||||
arch = Some(Arch::from_str(part)?);
|
||||
continue;
|
||||
}
|
||||
|
||||
if libc.is_none() {
|
||||
libc = Some(Libc::from_str(part)?);
|
||||
continue;
|
||||
}
|
||||
|
||||
return Err(Error::TooManyParts(s.to_string()));
|
||||
}
|
||||
Ok(Self::new(version, implementation, arch, os, libc, None))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user