Implement ordering for Python architectures to prefer native installations (#13709)

Resolves
https://github.com/astral-sh/uv/pull/13474#discussion_r2112586405

This kind of dynamic ordering freaks me out a little, but I think it's
probably the best solution and is static at compile-time.

Currently, we're just sorting by the stringified representation! which
is just convenient for reproducibility, but we rely on these orderings
for prioritization in discovery.
This commit is contained in:
Zanie Blue 2025-05-29 14:06:33 -05:00 committed by GitHub
parent 59070b5b3f
commit dfc85336f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 3 deletions

View file

@ -18,7 +18,7 @@ pub enum Error {
}
/// Architecture variants, e.g., with support for different instruction sets
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, Ord, PartialOrd)]
pub enum ArchVariant {
/// Targets 64-bit Intel/AMD CPUs newer than Nehalem (2008).
/// Includes SSE3, SSE4 and other post-2003 CPU instructions.
@ -37,6 +37,33 @@ pub struct Arch {
pub(crate) variant: Option<ArchVariant>,
}
impl Ord for Arch {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
if self.family == other.family {
return self.variant.cmp(&other.variant);
}
let native = Arch::from_env();
// Prefer native architectures
match (self.family == native.family, other.family == native.family) {
(true, true) => unreachable!(),
(true, false) => std::cmp::Ordering::Less,
(false, true) => std::cmp::Ordering::Greater,
(false, false) => {
// Both non-native, fallback to lexicographic order
self.family.to_string().cmp(&other.family.to_string())
}
}
}
}
impl PartialOrd for Arch {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
pub struct Os(pub(crate) target_lexicon::OperatingSystem);