Separate interpreter selectors into implementation and platform modules (#3332)

Split out of #3266

The "selector" concept doesn't seem well enough defined as-is. For
example, `PythonVersion` belongs there but isn't present. Going for
smaller modules instead.
This commit is contained in:
Zanie Blue 2024-05-02 06:55:01 -05:00 committed by GitHub
parent 5048ccef3a
commit c28a2806b3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 69 additions and 50 deletions

View file

@ -0,0 +1,47 @@
use std::{
fmt::{self, Display},
str::FromStr,
};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("Unknown Python implementation `{0}`")]
UnknownImplementation(String),
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum ImplementationName {
Cpython,
}
impl ImplementationName {
#[allow(dead_code)]
pub(crate) fn iter() -> impl Iterator<Item = &'static ImplementationName> {
static NAMES: &[ImplementationName] = &[ImplementationName::Cpython];
NAMES.iter()
}
pub fn as_str(&self) -> &str {
match self {
Self::Cpython => "cpython",
}
}
}
impl FromStr for ImplementationName {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"cpython" => Ok(Self::Cpython),
_ => Err(Error::UnknownImplementation(s.to_string())),
}
}
}
impl Display for ImplementationName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}

View file

@ -25,11 +25,12 @@ pub use crate::target::Target;
mod environment; mod environment;
mod find_python; mod find_python;
mod implementation;
mod interpreter; mod interpreter;
pub mod managed; pub mod managed;
pub mod platform;
mod py_launcher; mod py_launcher;
mod python_version; mod python_version;
pub mod selectors;
mod target; mod target;
#[derive(Debug, Error)] #[derive(Debug, Error)]

View file

@ -3,7 +3,8 @@ use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use crate::selectors::{Arch, ImplementationName, Libc, Os, PythonSelectorError}; use crate::implementation::{Error as ImplementationError, ImplementationName};
use crate::platform::{Arch, Error as PlatformError, Libc, Os};
use crate::PythonVersion; use crate::PythonVersion;
use thiserror::Error; use thiserror::Error;
use uv_client::BetterReqwestError; use uv_client::BetterReqwestError;
@ -18,7 +19,9 @@ use uv_fs::Simplified;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum Error {
#[error(transparent)] #[error(transparent)]
SelectorError(#[from] PythonSelectorError), PlatformError(#[from] PlatformError),
#[error(transparent)]
ImplementationError(#[from] ImplementationError),
#[error("invalid python version: {0}")] #[error("invalid python version: {0}")]
InvalidPythonVersion(String), InvalidPythonVersion(String),
#[error("download failed")] #[error("download failed")]

View file

@ -3,8 +3,10 @@ use std::ffi::OsStr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::managed::downloads::Error; use crate::managed::downloads::Error;
use crate::python_version::PythonVersion; use crate::{
use crate::selectors::{Arch, Libc, Os}; platform::{Arch, Libc, Os},
python_version::PythonVersion,
};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;

View file

@ -1,14 +1,9 @@
use std::{ use std::{
fmt::{self, Display}, fmt::{self},
str::FromStr, str::FromStr,
}; };
use thiserror::Error; use thiserror::Error;
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum ImplementationName {
Cpython,
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Platform { pub struct Platform {
os: Os, os: Os,
@ -51,49 +46,20 @@ pub enum Libc {
} }
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum PythonSelectorError { pub enum Error {
#[error("Operating system not supported: {0}")] #[error("Operating system not supported: {0}")]
OsNotSupported(String), OsNotSupported(String),
#[error("Architecture not supported: {0}")] #[error("Architecture not supported: {0}")]
ArchNotSupported(String), ArchNotSupported(String),
#[error("Libc type could not be detected")] #[error("Libc type could not be detected")]
LibcNotDetected(), LibcNotDetected(),
#[error("Implementation not supported: {0}")]
ImplementationNotSupported(String),
}
impl ImplementationName {
pub fn as_str(&self) -> &str {
match self {
Self::Cpython => "cpython",
}
}
}
impl FromStr for ImplementationName {
type Err = PythonSelectorError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"cpython" => Ok(Self::Cpython),
_ => Err(PythonSelectorError::ImplementationNotSupported(
s.to_string(),
)),
}
}
}
impl Display for ImplementationName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
} }
impl Platform { impl Platform {
pub fn new(os: Os, arch: Arch, libc: Libc) -> Self { pub fn new(os: Os, arch: Arch, libc: Libc) -> Self {
Self { os, arch, libc } Self { os, arch, libc }
} }
pub fn from_env() -> Result<Self, PythonSelectorError> { pub fn from_env() -> Result<Self, Error> {
Ok(Self::new( Ok(Self::new(
Os::from_env()?, Os::from_env()?,
Arch::from_env()?, Arch::from_env()?,
@ -119,13 +85,13 @@ impl fmt::Display for Os {
} }
impl Os { impl Os {
pub(crate) fn from_env() -> Result<Self, PythonSelectorError> { pub(crate) fn from_env() -> Result<Self, Error> {
Self::from_str(std::env::consts::OS) Self::from_str(std::env::consts::OS)
} }
} }
impl FromStr for Os { impl FromStr for Os {
type Err = PythonSelectorError; type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() { match s.to_lowercase().as_str() {
@ -138,7 +104,7 @@ impl FromStr for Os {
"dragonfly" => Ok(Self::Dragonfly), "dragonfly" => Ok(Self::Dragonfly),
"illumos" => Ok(Self::Illumos), "illumos" => Ok(Self::Illumos),
"haiku" => Ok(Self::Haiku), "haiku" => Ok(Self::Haiku),
_ => Err(PythonSelectorError::OsNotSupported(s.to_string())), _ => Err(Error::OsNotSupported(s.to_string())),
} }
} }
} }
@ -159,7 +125,7 @@ impl fmt::Display for Arch {
} }
impl FromStr for Arch { impl FromStr for Arch {
type Err = PythonSelectorError; type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() { match s.to_lowercase().as_str() {
@ -171,24 +137,24 @@ impl FromStr for Arch {
"x86" | "i686" | "i386" => Ok(Self::X86), "x86" | "i686" | "i386" => Ok(Self::X86),
"x86_64" | "amd64" => Ok(Self::X86_64), "x86_64" | "amd64" => Ok(Self::X86_64),
"s390x" => Ok(Self::S390X), "s390x" => Ok(Self::S390X),
_ => Err(PythonSelectorError::ArchNotSupported(s.to_string())), _ => Err(Error::ArchNotSupported(s.to_string())),
} }
} }
} }
impl Arch { impl Arch {
pub(crate) fn from_env() -> Result<Self, PythonSelectorError> { pub(crate) fn from_env() -> Result<Self, Error> {
Self::from_str(std::env::consts::ARCH) Self::from_str(std::env::consts::ARCH)
} }
} }
impl Libc { impl Libc {
pub(crate) fn from_env() -> Result<Self, PythonSelectorError> { pub(crate) fn from_env() -> Result<Self, Error> {
// TODO(zanieb): Perform this lookup // TODO(zanieb): Perform this lookup
match std::env::consts::OS { match std::env::consts::OS {
"linux" => Ok(Libc::Gnu), "linux" => Ok(Libc::Gnu),
"windows" | "macos" => Ok(Libc::None), "windows" | "macos" => Ok(Libc::None),
_ => Err(PythonSelectorError::LibcNotDetected()), _ => Err(Error::LibcNotDetected()),
} }
} }
} }