mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
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:
parent
6eb6475afd
commit
91410acf82
3 changed files with 107 additions and 31 deletions
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -82,6 +82,16 @@ fn python_find() {
|
|||
----- stderr -----
|
||||
"###);
|
||||
|
||||
// Request Python 3.12 via partial key syntax with placeholders
|
||||
uv_snapshot!(context.filters(), context.python_find().arg("any-3.12-any"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
[PYTHON-3.12]
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
|
||||
// Request CPython 3.12 for the current platform
|
||||
let os = Os::from_env();
|
||||
let arch = Arch::from_env();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue