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 find_python;
mod implementation;
mod interpreter;
pub mod managed;
pub mod platform;
mod py_launcher;
mod python_version;
pub mod selectors;
mod target;
#[derive(Debug, Error)]

View file

@ -3,7 +3,8 @@ use std::io;
use std::path::{Path, PathBuf};
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 thiserror::Error;
use uv_client::BetterReqwestError;
@ -18,7 +19,9 @@ use uv_fs::Simplified;
#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
SelectorError(#[from] PythonSelectorError),
PlatformError(#[from] PlatformError),
#[error(transparent)]
ImplementationError(#[from] ImplementationError),
#[error("invalid python version: {0}")]
InvalidPythonVersion(String),
#[error("download failed")]

View file

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

View file

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