diff --git a/crates/puffin-resolver/src/candidate_selector.rs b/crates/puffin-resolver/src/candidate_selector.rs index 8876efabc..d8657b544 100644 --- a/crates/puffin-resolver/src/candidate_selector.rs +++ b/crates/puffin-resolver/src/candidate_selector.rs @@ -156,96 +156,63 @@ impl CandidateSelector { range: &Range, allow_prerelease: AllowPreRelease, ) -> Option { - // We prefer a stable wheel, followed by a prerelease wheel, followed by a stable sdist, - // followed by a prerelease sdist. - let mut sdist = None; - let mut prerelease_sdist = None; - let mut prerelease_wheel = None; + #[derive(Debug)] + enum PreReleaseCandidate<'a> { + NotNecessary, + IfNecessary(&'a PubGrubVersion, &'a DistributionFile), + } + let mut prerelease = None; for (version, file) in versions { - if range.contains(version) { - match file { - DistributionFile::Wheel(_) => { - if version.any_prerelease() { - match allow_prerelease { - AllowPreRelease::Yes => { - // If prereleases are allowed, treat them equivalently - // to stable wheels. - return Some(Candidate { - package_name: package_name.clone(), - version: version.clone(), - file: file.clone(), - }); - } - AllowPreRelease::IfNecessary => { - // If prereleases are allowed as a fallback, store the - // first-matching prerelease wheel. - if prerelease_wheel.is_none() { - prerelease_wheel = Some(Candidate { - package_name: package_name.clone(), - version: version.clone(), - file: file.clone(), - }); - } - } - AllowPreRelease::No => { - continue; - } - } - } else { - // Always return the first-matching stable wheel. + if version.any_prerelease() { + if range.contains(version) { + match allow_prerelease { + AllowPreRelease::Yes => { + // If pre-releases are allowed, treat them equivalently + // to stable distributions. return Some(Candidate { package_name: package_name.clone(), version: version.clone(), file: file.clone(), }); } - } - DistributionFile::Sdist(_) => { - if version.any_prerelease() { - match allow_prerelease { - AllowPreRelease::Yes => { - // If prereleases are allowed, treat them equivalently to - // stable sdists. - if sdist.is_none() { - sdist = Some(Candidate { - package_name: package_name.clone(), - version: version.clone(), - file: file.clone(), - }); - } - } - AllowPreRelease::IfNecessary => { - // If prereleases are allowed as a fallback, store the - // first-matching prerelease sdist. - if prerelease_sdist.is_none() { - prerelease_sdist = Some(Candidate { - package_name: package_name.clone(), - version: version.clone(), - file: file.clone(), - }); - } - } - AllowPreRelease::No => { - continue; - } - } - } else { - // Store the first-matching stable sdist. - if sdist.is_none() { - sdist = Some(Candidate { - package_name: package_name.clone(), - version: version.clone(), - file: file.clone(), - }); + AllowPreRelease::IfNecessary => { + // If pre-releases are allowed as a fallback, store the + // first-matching prerelease. + if prerelease.is_none() { + prerelease = Some(PreReleaseCandidate::IfNecessary(version, file)); } } + AllowPreRelease::No => { + continue; + } } } + } else { + // If we have at least one stable release, we shouldn't allow the "if-necessary" + // pre-release strategy, regardless of whether that stable release satisfies the + // current range. + prerelease = Some(PreReleaseCandidate::NotNecessary); + + // Always return the first-matching stable distribution. + if range.contains(version) { + return Some(Candidate { + package_name: package_name.clone(), + version: version.clone(), + file: file.clone(), + }); + } } } - - sdist.or(prerelease_wheel).or(prerelease_sdist) + match prerelease { + None => None, + Some(PreReleaseCandidate::NotNecessary) => None, + Some(PreReleaseCandidate::IfNecessary(version, file)) => Some(Candidate { + package_name: package_name.clone(), + version: version.clone(), + file: file.clone(), + }), + } } } diff --git a/crates/puffin-resolver/src/resolver.rs b/crates/puffin-resolver/src/resolver.rs index 1e7446c1a..ac23ab163 100644 --- a/crates/puffin-resolver/src/resolver.rs +++ b/crates/puffin-resolver/src/resolver.rs @@ -515,11 +515,10 @@ impl<'a, Context: BuildContext + Sync> Resolver<'a, Context> { if let Ok(name) = WheelFilename::from_str(file.filename.as_str()) { if name.is_compatible(self.tags) { let version = PubGrubVersion::from(name.version); - match version_map.entry(version) { std::collections::btree_map::Entry::Occupied(mut entry) => { - if let DistributionFile::Sdist(_) = entry.get() { - // Wheels get precedence over source distributions + if matches!(entry.get(), DistributionFile::Sdist(_)) { + // Wheels get precedence over source distributions. entry.insert(DistributionFile::from(WheelFile::from( file, ))); diff --git a/crates/puffin-resolver/tests/resolver.rs b/crates/puffin-resolver/tests/resolver.rs index 4c86638a7..3c82b4af0 100644 --- a/crates/puffin-resolver/tests/resolver.rs +++ b/crates/puffin-resolver/tests/resolver.rs @@ -134,7 +134,7 @@ async fn black_mypy_extensions() -> Result<()> { let manifest = Manifest::new( vec![Requirement::from_str("black<=23.9.1").unwrap()], - vec![Requirement::from_str("mypy-extensions<1").unwrap()], + vec![Requirement::from_str("mypy-extensions<0.4.4").unwrap()], vec![], ResolutionMode::default(), PreReleaseMode::default(), @@ -158,7 +158,7 @@ async fn black_mypy_extensions_extra() -> Result<()> { let manifest = Manifest::new( vec![Requirement::from_str("black<=23.9.1").unwrap()], - vec![Requirement::from_str("mypy-extensions[extra]<1").unwrap()], + vec![Requirement::from_str("mypy-extensions[extra]<0.4.4").unwrap()], vec![], ResolutionMode::default(), PreReleaseMode::default(), @@ -321,7 +321,7 @@ async fn black_allow_prerelease_if_necessary() -> Result<()> { ); let resolver = Resolver::new(manifest, &MARKERS_311, &TAGS_311, &client, &DummyContext); - let resolution = resolver.resolve().await?; + let resolution = resolver.resolve().await.unwrap_err(); insta::assert_display_snapshot!(resolution); diff --git a/crates/puffin-resolver/tests/snapshots/resolver__black_allow_prerelease_if_necessary.snap b/crates/puffin-resolver/tests/snapshots/resolver__black_allow_prerelease_if_necessary.snap index 84472682f..fee91039f 100644 --- a/crates/puffin-resolver/tests/snapshots/resolver__black_allow_prerelease_if_necessary.snap +++ b/crates/puffin-resolver/tests/snapshots/resolver__black_allow_prerelease_if_necessary.snap @@ -2,19 +2,4 @@ source: crates/puffin-resolver/tests/resolver.rs expression: resolution --- -appdirs==1.4.4 - # via black -attrs==23.1.0 - # via black -black==19.10b0 -click==8.1.7 - # via black -pathspec==0.11.2 - # via black -regex==2023.10.3 - # via black -toml==0.10.2 - # via black -typed-ast==1.5.5 - # via black - +No solution