diff --git a/crates/puffin-resolver/src/pubgrub/mod.rs b/crates/puffin-resolver/src/pubgrub/mod.rs index 59370e796..52fa4df00 100644 --- a/crates/puffin-resolver/src/pubgrub/mod.rs +++ b/crates/puffin-resolver/src/pubgrub/mod.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use itertools::Itertools; use pubgrub::range::Range; use pep508_rs::{MarkerEnvironment, Requirement}; @@ -8,7 +9,7 @@ use puffin_package::package_name::PackageName; pub(crate) use crate::pubgrub::package::PubGrubPackage; pub(crate) use crate::pubgrub::priority::{PubGrubPriorities, PubGrubPriority}; pub(crate) use crate::pubgrub::specifier::PubGrubSpecifier; -pub(crate) use crate::pubgrub::version::{PubGrubVersion, MAX_VERSION, MIN_VERSION}; +pub(crate) use crate::pubgrub::version::{PubGrubVersion, MIN_VERSION}; mod package; mod priority; @@ -67,19 +68,10 @@ pub(crate) fn version_range( return Ok(Range::full()); }; - let mut final_range = Range::full(); - for spec in specifiers.iter() { - let spec_range = - PubGrubSpecifier::try_from(spec)? - .into_iter() - .fold(Range::empty(), |accum, range| { - accum.union(&if range.end < *MAX_VERSION { - Range::between(range.start, range.end) - } else { - Range::higher_than(range.start) - }) - }); - final_range = final_range.intersection(&spec_range); - } - Ok(final_range) + specifiers + .iter() + .map(PubGrubSpecifier::try_from) + .fold_ok(Range::full(), |range, specifier| { + range.intersection(&specifier.into()) + }) } diff --git a/crates/puffin-resolver/src/pubgrub/specifier.rs b/crates/puffin-resolver/src/pubgrub/specifier.rs index c3a95de60..4099c45cc 100644 --- a/crates/puffin-resolver/src/pubgrub/specifier.rs +++ b/crates/puffin-resolver/src/pubgrub/specifier.rs @@ -1,21 +1,18 @@ -use std::ops::Range; - use anyhow::Result; +use pubgrub::range::Range; use pep440_rs::{Operator, VersionSpecifier}; -use crate::pubgrub::version::{PubGrubVersion, MAX_VERSION, MIN_VERSION}; +use crate::pubgrub::version::PubGrubVersion; /// A range of versions that can be used to satisfy a requirement. #[derive(Debug)] -pub(crate) struct PubGrubSpecifier(Vec>); +pub(crate) struct PubGrubSpecifier(Range); -impl IntoIterator for PubGrubSpecifier { - type Item = Range; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() +impl From for Range { + /// Convert a `PubGrub` specifier to a range of versions. + fn from(specifier: PubGrubSpecifier) -> Self { + specifier.0 } } @@ -27,18 +24,15 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier { let ranges = match specifier.operator() { Operator::Equal => { let version = PubGrubVersion::from(specifier.version().clone()); - vec![version.clone()..version.next()] + Range::singleton(version) } Operator::ExactEqual => { let version = PubGrubVersion::from(specifier.version().clone()); - vec![version.clone()..version.next()] + Range::singleton(version) } Operator::NotEqual => { let version = PubGrubVersion::from(specifier.version().clone()); - vec![ - MIN_VERSION.clone()..version.clone(), - version.next()..MAX_VERSION.clone(), - ] + Range::singleton(version).complement() } Operator::TildeEqual => { let [rest @ .., last, _] = specifier.version().release.as_slice() else { @@ -58,29 +52,16 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier { .copied() .collect(), }); - let lower = PubGrubVersion::from(specifier.version().clone()); - vec![lower..upper] + let version = PubGrubVersion::from(specifier.version().clone()); + Range::from_range_bounds(version..upper) } Operator::LessThan => { - // Per PEP 440: "The exclusive ordered comparison { let version = PubGrubVersion::from(specifier.version().clone()); - vec![MIN_VERSION.clone()..version.next()] + Range::lower_than(version) } Operator::GreaterThan => { // Per PEP 440: "The exclusive ordered comparison >V MUST NOT allow a post-release of @@ -93,20 +74,18 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier { } else { low.post = Some(usize::MAX); } - - let version = PubGrubVersion::from(low); - vec![version..MAX_VERSION.clone()] + let version = PubGrubVersion::from(specifier.version().clone()); + Range::strictly_higher_than(version) } Operator::GreaterThanEqual => { let version = PubGrubVersion::from(specifier.version().clone()); - vec![version..MAX_VERSION.clone()] + Range::higher_than(version) } Operator::EqualStar => { let low = pep440_rs::Version { dev: Some(0), ..specifier.version().clone() }; - let mut high = pep440_rs::Version { dev: Some(0), ..specifier.version().clone() @@ -122,15 +101,13 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier { } else { *high.release.last_mut().unwrap() += 1; } - - vec![PubGrubVersion::from(low)..PubGrubVersion::from(high)] + Range::from_range_bounds(PubGrubVersion::from(low)..PubGrubVersion::from(high)) } Operator::NotEqualStar => { let low = pep440_rs::Version { dev: Some(0), ..specifier.version().clone() }; - let mut high = pep440_rs::Version { dev: Some(0), ..specifier.version().clone() @@ -146,11 +123,8 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier { } else { *high.release.last_mut().unwrap() += 1; } - - vec![ - MIN_VERSION.clone()..PubGrubVersion::from(low), - PubGrubVersion::from(high)..MAX_VERSION.clone(), - ] + Range::from_range_bounds(PubGrubVersion::from(low)..PubGrubVersion::from(high)) + .complement() } }; diff --git a/crates/puffin-resolver/src/pubgrub/version.rs b/crates/puffin-resolver/src/pubgrub/version.rs index 884d44d1b..412c2dbc0 100644 --- a/crates/puffin-resolver/src/pubgrub/version.rs +++ b/crates/puffin-resolver/src/pubgrub/version.rs @@ -62,14 +62,3 @@ impl From for pep440_rs::Version { pub(crate) static MIN_VERSION: Lazy = Lazy::new(|| PubGrubVersion::from(pep440_rs::Version::from_str("0a0.dev0").unwrap())); - -pub(crate) static MAX_VERSION: Lazy = Lazy::new(|| { - PubGrubVersion(pep440_rs::Version { - epoch: usize::MAX, - release: vec![usize::MAX, usize::MAX, usize::MAX], - pre: None, - post: Some(usize::MAX), - dev: None, - local: None, - }) -});