mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35: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,
|
arch: None,
|
||||||
os: None,
|
os: None,
|
||||||
libc: None,
|
libc: None,
|
||||||
prereleases: None
|
prereleases: None,
|
||||||
|
arch_mode: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2818,7 +2819,8 @@ mod tests {
|
||||||
}),
|
}),
|
||||||
os: Some(Os(target_lexicon::OperatingSystem::Darwin(None))),
|
os: Some(Os(target_lexicon::OperatingSystem::Darwin(None))),
|
||||||
libc: Some(Libc::None),
|
libc: Some(Libc::None),
|
||||||
prereleases: None
|
prereleases: None,
|
||||||
|
arch_mode: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2834,7 +2836,8 @@ mod tests {
|
||||||
arch: None,
|
arch: None,
|
||||||
os: None,
|
os: None,
|
||||||
libc: None,
|
libc: None,
|
||||||
prereleases: None
|
prereleases: None,
|
||||||
|
arch_mode: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2853,7 +2856,8 @@ mod tests {
|
||||||
}),
|
}),
|
||||||
os: None,
|
os: None,
|
||||||
libc: None,
|
libc: None,
|
||||||
prereleases: None
|
prereleases: None,
|
||||||
|
arch_mode: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ use crate::implementation::{
|
||||||
use crate::installation::PythonInstallationKey;
|
use crate::installation::PythonInstallationKey;
|
||||||
use crate::libc::LibcDetectionError;
|
use crate::libc::LibcDetectionError;
|
||||||
use crate::managed::ManagedPythonInstallation;
|
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};
|
use crate::{Interpreter, PythonRequest, PythonVersion, VersionRequest};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[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
|
/// Whether to allow pre-releases or not. If not set, defaults to true if [`Self::version`] is
|
||||||
/// not None, and false otherwise.
|
/// not None, and false otherwise.
|
||||||
pub(crate) prereleases: Option<bool>,
|
pub(crate) prereleases: Option<bool>,
|
||||||
|
|
||||||
|
pub(crate) arch_mode: Option<ArchMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PythonDownloadRequest {
|
impl PythonDownloadRequest {
|
||||||
|
@ -133,6 +135,7 @@ impl PythonDownloadRequest {
|
||||||
os: Option<Os>,
|
os: Option<Os>,
|
||||||
libc: Option<Libc>,
|
libc: Option<Libc>,
|
||||||
prereleases: Option<bool>,
|
prereleases: Option<bool>,
|
||||||
|
arch_mode: Option<ArchMode>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
version,
|
version,
|
||||||
|
@ -141,6 +144,7 @@ impl PythonDownloadRequest {
|
||||||
os,
|
os,
|
||||||
libc,
|
libc,
|
||||||
prereleases,
|
prereleases,
|
||||||
|
arch_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +190,12 @@ impl PythonDownloadRequest {
|
||||||
self
|
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.
|
/// 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
|
/// 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(Os::from_env()),
|
||||||
Some(Libc::from_env()?),
|
Some(Libc::from_env()?),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +302,11 @@ impl PythonDownloadRequest {
|
||||||
if !arch.supports(key.arch) {
|
if !arch.supports(key.arch) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if let Some(mode) = self.arch_mode {
|
||||||
|
if !mode.allows(arch, &key.arch) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(libc) = &self.libc {
|
if let Some(libc) = &self.libc {
|
||||||
|
@ -412,6 +428,7 @@ impl From<&ManagedPythonInstallation> for PythonDownloadRequest {
|
||||||
Some(key.os),
|
Some(key.os),
|
||||||
Some(key.libc),
|
Some(key.libc),
|
||||||
Some(key.prerelease.is_some()),
|
Some(key.prerelease.is_some()),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,7 +500,15 @@ impl FromStr for PythonDownloadRequest {
|
||||||
_ => return Err(Error::TooManyParts(s.to_string())),
|
_ => 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,
|
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)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
||||||
pub struct Arch {
|
pub struct Arch {
|
||||||
pub(crate) family: target_lexicon::Architecture,
|
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 {
|
impl Arch {
|
||||||
pub fn from_env() -> Self {
|
pub fn from_env() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -17,7 +17,7 @@ use uv_python::downloads::{self, DownloadResult, ManagedPythonDownload, PythonDo
|
||||||
use uv_python::managed::{
|
use uv_python::managed::{
|
||||||
ManagedPythonInstallation, ManagedPythonInstallations, python_executable_dir,
|
ManagedPythonInstallation, ManagedPythonInstallations, python_executable_dir,
|
||||||
};
|
};
|
||||||
use uv_python::platform::{Arch, Libc};
|
use uv_python::platform::{Arch, ArchMode, Libc};
|
||||||
use uv_python::{
|
use uv_python::{
|
||||||
PythonDownloads, PythonInstallationKey, PythonRequest, PythonVersionFile,
|
PythonDownloads, PythonInstallationKey, PythonRequest, PythonVersionFile,
|
||||||
VersionFileDiscoveryOptions, VersionFilePreference,
|
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",
|
"`{}` 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()
|
request.to_canonical_string()
|
||||||
)
|
)
|
||||||
})?
|
})?.with_arch_mode(ArchMode::BestNative).fill()?;
|
||||||
.fill()?;
|
|
||||||
|
|
||||||
// Find a matching download
|
// Find a matching download
|
||||||
let download =
|
let download =
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::BTreeSet;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use uv_cli::PythonListFormat;
|
use uv_cli::PythonListFormat;
|
||||||
use uv_pep440::Version;
|
use uv_pep440::Version;
|
||||||
|
use uv_python::platform::ArchMode;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
|
@ -80,7 +81,10 @@ pub(crate) async fn list(
|
||||||
PythonListKinds::Downloads => Some(if all_platforms {
|
PythonListKinds::Downloads => Some(if all_platforms {
|
||||||
base_download_request
|
base_download_request
|
||||||
} else {
|
} 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 => {
|
PythonListKinds::Default => {
|
||||||
if python_downloads.is_automatic() {
|
if python_downloads.is_automatic() {
|
||||||
|
@ -89,7 +93,11 @@ pub(crate) async fn list(
|
||||||
} else if all_arches {
|
} else if all_arches {
|
||||||
base_download_request.fill_platform()?.with_any_arch()
|
base_download_request.fill_platform()?.with_any_arch()
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
// If fetching is not automatic, then don't show downloads as available by default
|
// 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