mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Make version selection wheel-vs.-sdist-agnostic (#232)
Closes https://github.com/astral-sh/puffin/issues/231.
This commit is contained in:
parent
8d992dca3f
commit
0be20a41a4
4 changed files with 49 additions and 98 deletions
|
@ -156,96 +156,63 @@ impl CandidateSelector {
|
|||
range: &Range<PubGrubVersion>,
|
||||
allow_prerelease: AllowPreRelease,
|
||||
) -> Option<Candidate> {
|
||||
// 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(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
)));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue