diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 39c8b4e..70cfa17 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -15,12 +15,10 @@ use fs_err as fs; use fs_err::File; use logging_timer::time; use ouroboros::self_referencing; -use pep440_rs::Version; use pep508_rs::MarkerEnvironment; use python_platform::{ CPythonAbiInfo, CPythonImplementation, - NonEmptyVec, PlatformDetails, PyPyImplementation, PyPyVersion, @@ -460,17 +458,12 @@ impl<'a> PythonPlatform<'a> for Interpreter { self.platform_details().marker_env() } - fn supported_tags(&self) -> NonEmptyVec<&'_ str> { + fn supported_tags(&self) -> impl Iterator { self.platform_details().supported_tags() } - fn version(&self) -> Cow<'_, Version> { - let version = self.details.version; - Cow::Owned(Version::new([ - u64::from(version.major), - u64::from(version.minor), - u64::from(version.micro), - ])) + fn primary_tag(&self) -> &str { + self.platform_details().primary_tag() } } @@ -551,8 +544,7 @@ mod tests { expected_tags, interpreter .supported_tags() - .iter() - .cloned() + .map(ToOwned::to_owned) .collect::>() ); } diff --git a/crates/interpreter/src/platform.rs b/crates/interpreter/src/platform.rs index 65663f4..dcf76a2 100644 --- a/crates/interpreter/src/platform.rs +++ b/crates/interpreter/src/platform.rs @@ -16,7 +16,7 @@ pub struct Platform<'a> { impl<'a> Platform<'a> { pub fn of(interpreter: &'a Interpreter) -> anyhow::Result { - let tag = Tag::parse(interpreter.supported_tags().first())?; + let tag = Tag::parse(interpreter.primary_tag())?; Ok(Self { implementation: &tag.python[0..2], version: interpreter.details.version, diff --git a/crates/pex/src/pex.rs b/crates/pex/src/pex.rs index f15b0fd..f877361 100644 --- a/crates/pex/src/pex.rs +++ b/crates/pex/src/pex.rs @@ -259,7 +259,6 @@ impl<'a> Pex<'a> { ) -> anyhow::Result>> { let supported_tags: HashMap = target .supported_tags() - .iter() .enumerate() .map(|(idx, tag)| Tag::parse(tag).map(|tag| (tag, idx))) .collect::>()?; diff --git a/crates/python-platform/src/lib.rs b/crates/python-platform/src/lib.rs index ae08e58..5268da8 100644 --- a/crates/python-platform/src/lib.rs +++ b/crates/python-platform/src/lib.rs @@ -44,23 +44,19 @@ pub use crate::version::{ }; #[derive(Clone, Debug, Eq, PartialEq, Hash, Deserialize, Serialize)] -pub struct NonEmptyVec(Vec); +struct NonEmptyVec(Vec); impl NonEmptyVec { - pub fn new(vec: Vec) -> anyhow::Result { + fn new(vec: Vec) -> anyhow::Result { if vec.is_empty() { bail!("Given an empty vec.") } Ok(Self(vec)) } - pub fn first(&self) -> &T { + fn first(&self) -> &T { &self.0[0] } - - fn transformed(&self, transform: impl Fn(&T) -> &U) -> NonEmptyVec<&U> { - NonEmptyVec(self.0.iter().map(transform).collect()) - } } impl Deref for NonEmptyVec { @@ -74,7 +70,8 @@ impl Deref for NonEmptyVec { pub trait PythonPlatform<'a> { fn description(&self) -> impl Display; fn marker_env(&self) -> &MarkerEnvironment; - fn supported_tags(&self) -> NonEmptyVec<&'_ str>; + fn supported_tags(&self) -> impl Iterator; + fn primary_tag(&self) -> &str; fn version(&self) -> Cow<'_, Version> { Cow::Borrowed(&self.marker_env().python_full_version().version) } @@ -82,9 +79,10 @@ pub trait PythonPlatform<'a> { #[derive(Clone, Debug, Eq, PartialEq, Hash, Deserialize, Serialize)] pub struct PlatformDetails<'a> { - pub source: String, - pub marker_env: MarkerEnvironment, - pub supported_tags: NonEmptyVec>, + #[serde(borrow)] + source: Cow<'a, str>, + marker_env: MarkerEnvironment, + supported_tags: NonEmptyVec>, } impl<'a> PlatformDetails<'a> { @@ -94,7 +92,7 @@ impl<'a> PlatformDetails<'a> { supported_tags: Vec>, ) -> anyhow::Result { Ok(Self { - source: source.to_string(), + source: Cow::Owned(source.to_string()), marker_env, supported_tags: NonEmptyVec::new(supported_tags)?, }) @@ -107,7 +105,10 @@ impl<'a> PlatformDetails<'a> { let platform = Platform::current()?; let release_info = Os::current_release()?; Ok(Self { - source: python_exe.display().to_string(), + source: Cow::Owned(format!( + "interpreter at {python_exe}", + python_exe = python_exe.display() + )), marker_env: markers::calculate( python_version, platform, @@ -133,8 +134,12 @@ impl<'a> PythonPlatform<'a> for PlatformDetails<'a> { &self.marker_env } - fn supported_tags(&self) -> NonEmptyVec<&'_ str> { - self.supported_tags.transformed(|tag| tag.as_ref()) + fn supported_tags(&self) -> impl Iterator { + self.supported_tags.iter().map(AsRef::as_ref) + } + + fn primary_tag(&self) -> &str { + self.supported_tags.first() } } diff --git a/crates/python-platform/tests/tags_test.rs b/crates/python-platform/tests/tags_test.rs index 051891e..29ddf5c 100644 --- a/crates/python-platform/tests/tags_test.rs +++ b/crates/python-platform/tests/tags_test.rs @@ -63,9 +63,9 @@ fn test_abbreviated_platform( ) .unwrap(); - assert_eq!(interpreter.marker_env(), &platform_details.marker_env); + assert_eq!(interpreter.marker_env(), platform_details.marker_env()); assert_eq!( - interpreter.supported_tags().iter().collect::>(), - platform_details.supported_tags().iter().collect::>() + interpreter.supported_tags().collect::>(), + platform_details.supported_tags().collect::>() ); } diff --git a/crates/tools/src/commands/interpreter.rs b/crates/tools/src/commands/interpreter.rs index e85b987..49b2379 100644 --- a/crates/tools/src/commands/interpreter.rs +++ b/crates/tools/src/commands/interpreter.rs @@ -64,7 +64,7 @@ pub(crate) fn display(python: &Path, pex: Pex, args: InterpreterArgs) -> anyhow: "path": interpreter.details.path, "requirement": InterpreterConstraint::exact_version(&interpreter).to_string(), "platform": Platform::of(&interpreter)?.to_string(), - "supported_tags": interpreter.supported_tags() + "supported_tags": interpreter.supported_tags().collect::>() }), )?, _ => { @@ -78,7 +78,7 @@ pub(crate) fn display(python: &Path, pex: Pex, args: InterpreterArgs) -> anyhow: "path": interpreter.details.path, "requirement": InterpreterConstraint::exact_version(&interpreter).to_string(), "platform": Platform::of(&interpreter)?.to_string(), - "supported_tags": interpreter.supported_tags(), + "supported_tags": interpreter.supported_tags().collect::>(), "env_markers": interpreter.marker_env(), "venv": true, "base_interpreter": base_interpreter.details.path @@ -91,7 +91,7 @@ pub(crate) fn display(python: &Path, pex: Pex, args: InterpreterArgs) -> anyhow: "path": interpreter.details.path, "requirement": InterpreterConstraint::exact_version(&interpreter).to_string(), "platform": Platform::of(&interpreter)?.to_string(), - "supported_tags": interpreter.supported_tags(), + "supported_tags": interpreter.supported_tags().collect::>(), "env_markers": interpreter.marker_env(), "venv": false }), diff --git a/src/commands/platform/python.rs b/src/commands/platform/python.rs index d39a62a..f8bca70 100644 --- a/src/commands/platform/python.rs +++ b/src/commands/platform/python.rs @@ -105,7 +105,7 @@ pub struct Python { /// + cpython-3.14.5-windows_11-amd64 /// /// [^1]: These chip architectures are only supported for Linux. - /// [^2]: The derived Python platform specification is complete save for the platform_release + /// [^2]: The derived Python platform specification is complete save for the platform_version /// environment marker that appears to be unused in the wild. Its value is defaulted to /// "". #[arg(value_parser = PythonPlatform::parse, verbatim_doc_comment)]