mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Add an ArchMode
to filter displayed architectures in uv python list
This commit is contained in:
parent
e5d002beb1
commit
7ca43dd366
5 changed files with 89 additions and 11 deletions
|
@ -2799,7 +2799,8 @@ mod tests {
|
|||
arch: None,
|
||||
os: None,
|
||||
libc: None,
|
||||
prereleases: None
|
||||
prereleases: None,
|
||||
arch_mode: None,
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -2818,7 +2819,8 @@ mod tests {
|
|||
}),
|
||||
os: Some(Os(target_lexicon::OperatingSystem::Darwin(None))),
|
||||
libc: Some(Libc::None),
|
||||
prereleases: None
|
||||
prereleases: None,
|
||||
arch_mode: None,
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -2834,7 +2836,8 @@ mod tests {
|
|||
arch: None,
|
||||
os: None,
|
||||
libc: None,
|
||||
prereleases: None
|
||||
prereleases: None,
|
||||
arch_mode: None,
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -2853,7 +2856,8 @@ mod tests {
|
|||
}),
|
||||
os: None,
|
||||
libc: None,
|
||||
prereleases: None
|
||||
prereleases: None,
|
||||
arch_mode: None,
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ use crate::implementation::{
|
|||
use crate::installation::PythonInstallationKey;
|
||||
use crate::libc::LibcDetectionError;
|
||||
use crate::managed::ManagedPythonInstallation;
|
||||
use crate::platform::{self, Arch, Libc, Os};
|
||||
use crate::platform::{self, Arch, ArchMode, Libc, Os};
|
||||
use crate::{Interpreter, PythonRequest, PythonVersion, VersionRequest};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
@ -123,6 +123,8 @@ pub struct PythonDownloadRequest {
|
|||
/// Whether to allow pre-releases or not. If not set, defaults to true if [`Self::version`] is
|
||||
/// not None, and false otherwise.
|
||||
pub(crate) prereleases: Option<bool>,
|
||||
|
||||
pub(crate) arch_mode: Option<ArchMode>,
|
||||
}
|
||||
|
||||
impl PythonDownloadRequest {
|
||||
|
@ -133,6 +135,7 @@ impl PythonDownloadRequest {
|
|||
os: Option<Os>,
|
||||
libc: Option<Libc>,
|
||||
prereleases: Option<bool>,
|
||||
arch_mode: Option<ArchMode>,
|
||||
) -> Self {
|
||||
Self {
|
||||
version,
|
||||
|
@ -141,6 +144,7 @@ impl PythonDownloadRequest {
|
|||
os,
|
||||
libc,
|
||||
prereleases,
|
||||
arch_mode,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,6 +190,12 @@ impl PythonDownloadRequest {
|
|||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_arch_mode(mut self, arch_mode: ArchMode) -> Self {
|
||||
self.arch_mode = Some(arch_mode);
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct a new [`PythonDownloadRequest`] from a [`PythonRequest`] if possible.
|
||||
///
|
||||
/// Returns [`None`] if the request kind is not compatible with a download, e.g., it is
|
||||
|
@ -247,6 +257,7 @@ impl PythonDownloadRequest {
|
|||
Some(Os::from_env()),
|
||||
Some(Libc::from_env()?),
|
||||
None,
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -291,6 +302,11 @@ impl PythonDownloadRequest {
|
|||
if !arch.supports(key.arch) {
|
||||
return false;
|
||||
}
|
||||
if let Some(mode) = self.arch_mode {
|
||||
if !mode.allows(arch, &key.arch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(libc) = &self.libc {
|
||||
|
@ -412,6 +428,7 @@ impl From<&ManagedPythonInstallation> for PythonDownloadRequest {
|
|||
Some(key.os),
|
||||
Some(key.libc),
|
||||
Some(key.prerelease.is_some()),
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -483,7 +500,15 @@ impl FromStr for PythonDownloadRequest {
|
|||
_ => return Err(Error::TooManyParts(s.to_string())),
|
||||
}
|
||||
}
|
||||
Ok(Self::new(version, implementation, arch, os, libc, None))
|
||||
Ok(Self::new(
|
||||
version,
|
||||
implementation,
|
||||
arch,
|
||||
os,
|
||||
libc,
|
||||
None,
|
||||
None,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,17 @@ pub enum ArchVariant {
|
|||
V4,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, Default)]
|
||||
pub enum ArchMode {
|
||||
/// Select the most precise architecture matching the current platform, e.g., x86-64-v4
|
||||
#[default]
|
||||
BestNative,
|
||||
/// Select the most compatible architecture matching the current platform, e.g., x86-64-v1
|
||||
CompatibleNative,
|
||||
/// Select an emulated architecture, e.g., x86-64 on aarch64 macOS.
|
||||
Emulated,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
||||
pub struct Arch {
|
||||
pub(crate) family: target_lexicon::Architecture,
|
||||
|
@ -95,6 +106,37 @@ impl Os {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArchMode {
|
||||
pub fn allows(self, current: &Arch, other: &Arch) -> bool {
|
||||
match self {
|
||||
Self::CompatibleNative | Self::BestNative => {
|
||||
// The architecture is native if the family is equal
|
||||
if current.family != other.family {
|
||||
return false;
|
||||
}
|
||||
|
||||
// There is only a compatibility nuance for x86_64 here
|
||||
if current.family != target_lexicon::Architecture::X86_64 {
|
||||
return true;
|
||||
}
|
||||
|
||||
if matches!(self, Self::CompatibleNative) {
|
||||
// Only allow x86_64 without a variant
|
||||
return other.variant.is_none();
|
||||
} else if matches!(self, Self::BestNative) {
|
||||
// Only allow the variant matching the current architecture
|
||||
return current.variant == other.variant;
|
||||
}
|
||||
|
||||
// We should handle all cases above
|
||||
unreachable!();
|
||||
}
|
||||
// The architecture is emulated if the family differs
|
||||
Self::Emulated => current.family != other.family,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Arch {
|
||||
pub fn from_env() -> Self {
|
||||
Self {
|
||||
|
|
|
@ -17,7 +17,7 @@ use uv_python::downloads::{self, DownloadResult, ManagedPythonDownload, PythonDo
|
|||
use uv_python::managed::{
|
||||
ManagedPythonInstallation, ManagedPythonInstallations, python_executable_dir,
|
||||
};
|
||||
use uv_python::platform::{Arch, Libc};
|
||||
use uv_python::platform::{Arch, ArchMode, Libc};
|
||||
use uv_python::{
|
||||
PythonDownloads, PythonInstallationKey, PythonRequest, PythonVersionFile,
|
||||
VersionFileDiscoveryOptions, VersionFilePreference,
|
||||
|
@ -51,8 +51,7 @@ impl InstallRequest {
|
|||
"`{}` is not a valid Python download request; see `uv help python` for supported formats and `uv python list --only-downloads` for available versions",
|
||||
request.to_canonical_string()
|
||||
)
|
||||
})?
|
||||
.fill()?;
|
||||
})?.with_arch_mode(ArchMode::BestNative).fill()?;
|
||||
|
||||
// Find a matching download
|
||||
let download =
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::BTreeSet;
|
|||
use std::fmt::Write;
|
||||
use uv_cli::PythonListFormat;
|
||||
use uv_pep440::Version;
|
||||
use uv_python::platform::ArchMode;
|
||||
|
||||
use anyhow::Result;
|
||||
use itertools::Either;
|
||||
|
@ -80,7 +81,10 @@ pub(crate) async fn list(
|
|||
PythonListKinds::Downloads => Some(if all_platforms {
|
||||
base_download_request
|
||||
} else {
|
||||
base_download_request.fill_platform()?
|
||||
base_download_request
|
||||
.fill_platform()?
|
||||
// Only show the best, native architecture by default
|
||||
.with_arch_mode(ArchMode::BestNative)
|
||||
}),
|
||||
PythonListKinds::Default => {
|
||||
if python_downloads.is_automatic() {
|
||||
|
@ -89,7 +93,11 @@ pub(crate) async fn list(
|
|||
} else if all_arches {
|
||||
base_download_request.fill_platform()?.with_any_arch()
|
||||
} else {
|
||||
base_download_request.fill_platform()?
|
||||
base_download_request
|
||||
.fill_platform()?
|
||||
// Only show the best, native architecture by default
|
||||
// TODO(zanieb): We should expose this option to the user
|
||||
.with_arch_mode(ArchMode::BestNative)
|
||||
})
|
||||
} else {
|
||||
// If fetching is not automatic, then don't show downloads as available by default
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue