diff --git a/crates/uv-platform-tags/src/abi_tag.rs b/crates/uv-platform-tags/src/abi_tag.rs index 1d5f2ee8c..2f205048c 100644 --- a/crates/uv-platform-tags/src/abi_tag.rs +++ b/crates/uv-platform-tags/src/abi_tag.rs @@ -32,7 +32,7 @@ pub enum AbiTag { }, /// Ex) `pypy39_pp73` PyPy { - python_version: (u8, u8), + python_version: Option<(u8, u8)>, implementation_version: (u8, u8), }, /// Ex) `graalpy310_graalpy240_310_native` @@ -55,12 +55,20 @@ impl AbiTag { AbiTag::CPython { python_version, .. } => { Some(format!("CPython {}.{}", python_version.0, python_version.1)) } - AbiTag::PyPy { python_version, .. } => { - Some(format!("PyPy {}.{}", python_version.0, python_version.1)) - } - AbiTag::GraalPy { python_version, .. } => { - Some(format!("GraalPy {}.{}", python_version.0, python_version.1)) - } + AbiTag::PyPy { + implementation_version, + .. + } => Some(format!( + "PyPy {}.{}", + implementation_version.0, implementation_version.1 + )), + AbiTag::GraalPy { + implementation_version, + .. + } => Some(format!( + "GraalPy {}.{}", + implementation_version.0, implementation_version.1 + )), AbiTag::Pyston { .. } => Some("Pyston".to_string()), AbiTag::Unknown { .. } => None, } @@ -88,11 +96,17 @@ impl std::fmt::Display for AbiTag { } } Self::PyPy { - python_version: (py_major, py_minor), + python_version: Some((py_major, py_minor)), implementation_version: (impl_major, impl_minor), } => { write!(f, "pypy{py_major}{py_minor}_pp{impl_major}{impl_minor}") } + Self::PyPy { + python_version: None, + implementation_version: (impl_major, impl_minor), + } => { + write!(f, "pypy_{impl_major}{impl_minor}") + } Self::GraalPy { python_version: (py_major, py_minor), implementation_version: (impl_major, impl_minor), @@ -196,25 +210,34 @@ impl AbiTag { python_version: (major, minor), }) } else if let Some(rest) = s.strip_prefix("pypy") { - // Ex) `pypy39_pp73` - let (version_str, rest) = - rest.split_once('_') - .ok_or_else(|| ParseAbiTagError::InvalidFormat { - implementation: "PyPy", - tag: s.to_string(), - })?; - let (major, minor) = parse_python_version(version_str, "PyPy", s)?; - let rest = rest - .strip_prefix("pp") - .ok_or_else(|| ParseAbiTagError::InvalidFormat { - implementation: "PyPy", - tag: s.to_string(), - })?; - let (impl_major, impl_minor) = parse_impl_version(rest, "PyPy", s)?; - Ok(Self::PyPy { - python_version: (major, minor), - implementation_version: (impl_major, impl_minor), - }) + if let Some(rest) = rest.strip_prefix('_') { + // Ex) `pypy_73` + let (impl_major, impl_minor) = parse_impl_version(rest, "PyPy", s)?; + Ok(Self::PyPy { + python_version: None, + implementation_version: (impl_major, impl_minor), + }) + } else { + // Ex) `pypy39_pp73` + let (version_str, rest) = + rest.split_once('_') + .ok_or_else(|| ParseAbiTagError::InvalidFormat { + implementation: "PyPy", + tag: s.to_string(), + })?; + let (major, minor) = parse_python_version(version_str, "PyPy", s)?; + let rest = + rest.strip_prefix("pp") + .ok_or_else(|| ParseAbiTagError::InvalidFormat { + implementation: "PyPy", + tag: s.to_string(), + })?; + let (impl_major, impl_minor) = parse_impl_version(rest, "PyPy", s)?; + Ok(Self::PyPy { + python_version: Some((major, minor)), + implementation_version: (impl_major, impl_minor), + }) + } } else if let Some(rest) = s.strip_prefix("graalpy") { // Ex) `graalpy310_graalpy240_310_native` let version_end = rest @@ -377,12 +400,19 @@ mod tests { #[test] fn pypy_abi() { let tag = AbiTag::PyPy { - python_version: (3, 9), + python_version: Some((3, 9)), implementation_version: (7, 3), }; assert_eq!(AbiTag::parse("pypy39_pp73").as_ref(), Ok(&tag)); assert_eq!(tag.to_string(), "pypy39_pp73"); + let tag = AbiTag::PyPy { + python_version: None, + implementation_version: (7, 3), + }; + assert_eq!(AbiTag::parse("pypy_73").as_ref(), Ok(&tag)); + assert_eq!(tag.to_string(), "pypy_73"); + assert_eq!( AbiTag::parse("pypy39"), Err(ParseAbiTagError::InvalidFormat { diff --git a/crates/uv-platform-tags/src/tags.rs b/crates/uv-platform-tags/src/tags.rs index fd567e115..3a0ae2ad3 100644 --- a/crates/uv-platform-tags/src/tags.rs +++ b/crates/uv-platform-tags/src/tags.rs @@ -392,7 +392,7 @@ impl Implementation { }, // Ex) `pypy39_pp73` Self::PyPy => AbiTag::PyPy { - python_version, + python_version: Some(python_version), implementation_version, }, // Ex) `graalpy310_graalpy240_310_native diff --git a/crates/uv-resolver/src/requires_python.rs b/crates/uv-resolver/src/requires_python.rs index cef410c92..7bc7eb428 100644 --- a/crates/uv-resolver/src/requires_python.rs +++ b/crates/uv-resolver/src/requires_python.rs @@ -464,7 +464,7 @@ impl RequiresPython { python_version: (2, ..), .. } | AbiTag::PyPy { - python_version: (2, ..), + python_version: None | Some((2, ..)), .. } | AbiTag::GraalPy { python_version: (2, ..), @@ -478,7 +478,7 @@ impl RequiresPython { .. } | AbiTag::PyPy { - python_version: (3, minor), + python_version: Some((3, minor)), .. } | AbiTag::GraalPy {