From 346050bf994be9997d1b006c38448bab8487bbfb Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sat, 12 Oct 2024 16:48:03 +0200 Subject: [PATCH] Improve major-minor bounds on requires-python (#8145) --- crates/uv-resolver/src/requires_python.rs | 30 ++++++++----------- .../uv-resolver/src/requires_python/tests.rs | 10 +++++++ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/crates/uv-resolver/src/requires_python.rs b/crates/uv-resolver/src/requires_python.rs index 0fd4e3f57..318c126da 100644 --- a/crates/uv-resolver/src/requires_python.rs +++ b/crates/uv-resolver/src/requires_python.rs @@ -553,13 +553,11 @@ impl LowerBound { /// Return the [`LowerBound`] truncated to the major and minor version. fn major_minor(&self) -> Self { match &self.0 { - // Ex) `>=3.10.1` -> `>=3.10` (and `>=3.10.0` is `>=3.10`) + // Ex) `>=3.10.1` -> `>=3.10` Bound::Included(version) => Self(Bound::Included(Version::new( version.release().iter().take(2), ))), // Ex) `>3.10.1` -> `>=3.10`. - // This is unintuitive, but `>3.10.1` does indicate that _some_ version of Python 3.10 - // is supported. Bound::Excluded(version) => Self(Bound::Included(Version::new( version.release().iter().take(2), ))), @@ -668,24 +666,20 @@ impl UpperBound { /// Return the [`UpperBound`] truncated to the major and minor version. fn major_minor(&self) -> Self { match &self.0 { - // Ex) `<=3.10.1` -> `<3.11` (but `<=3.10.0` is `<=3.10`) - Bound::Included(version) => { - let major = version.release().first().copied().unwrap_or(3); - let minor = version.release().get(1).copied().unwrap_or(0); - if version.release().get(2).is_some_and(|patch| *patch > 0) { - Self(Bound::Excluded(Version::new([major, minor + 1]))) - } else { - Self(Bound::Included(Version::new([major, minor]))) - } - } - // Ex) `<3.10.1` -> `<3.11` (but `<3.10.0` is `<3.10`) + // Ex) `<=3.10.1` -> `<=3.10` + Bound::Included(version) => Self(Bound::Included(Version::new( + version.release().iter().take(2), + ))), + // Ex) `<3.10.1` -> `<=3.10` (but `<3.10.0` is `<3.10`) Bound::Excluded(version) => { - let major = version.release().first().copied().unwrap_or(3); - let minor = version.release().get(1).copied().unwrap_or(0); if version.release().get(2).is_some_and(|patch| *patch > 0) { - Self(Bound::Excluded(Version::new([major, minor + 1]))) + Self(Bound::Included(Version::new( + version.release().iter().take(2), + ))) } else { - Self(Bound::Excluded(Version::new([major, minor]))) + Self(Bound::Excluded(Version::new( + version.release().iter().take(2), + ))) } } Bound::Unbounded => Self(Bound::Unbounded), diff --git a/crates/uv-resolver/src/requires_python/tests.rs b/crates/uv-resolver/src/requires_python/tests.rs index e460cb9b4..e836e7a80 100644 --- a/crates/uv-resolver/src/requires_python/tests.rs +++ b/crates/uv-resolver/src/requires_python/tests.rs @@ -39,6 +39,16 @@ fn requires_python_included() { ); } + let version_specifiers = VersionSpecifiers::from_str("==3.12.6").unwrap(); + let requires_python = RequiresPython::from_specifiers(&version_specifiers).unwrap(); + let wheel_names = &["lxml-5.3.0-cp312-cp312-musllinux_1_2_aarch64.whl"]; + for wheel_name in wheel_names { + assert!( + requires_python.matches_wheel_tag(&WheelFilename::from_str(wheel_name).unwrap()), + "{wheel_name}" + ); + } + let version_specifiers = VersionSpecifiers::from_str("==3.12").unwrap(); let requires_python = RequiresPython::from_specifiers(&version_specifiers).unwrap(); let wheel_names = &["lxml-5.3.0-cp312-cp312-musllinux_1_2_x86_64.whl"];