mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 10:58:28 +00:00
Show available pre-releases in error hints (#844)
## Summary If pre-releases are available for a package that we otherwise couldn't resolve, we now show a hint that includes one of the example versions. Closes https://github.com/astral-sh/puffin/issues/811.
This commit is contained in:
parent
b1edecdf1f
commit
ee3a6431c7
3 changed files with 78 additions and 30 deletions
|
@ -522,6 +522,8 @@ fn requires_package_only_prereleases_in_range() -> Result<()> {
|
|||
----- stderr -----
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because there are no versions of a>0.1.0 and root depends on a>0.1.0, version solving failed.
|
||||
|
||||
hint: Pre-releases are available for a in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||||
"###);
|
||||
});
|
||||
|
||||
|
@ -1116,6 +1118,8 @@ fn requires_transitive_package_only_prereleases_in_range() -> Result<()> {
|
|||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because there are no versions of b>0.1 and a==0.1.0 depends on b>0.1, a==0.1.0 is forbidden.
|
||||
And because there are no versions of a<0.1.0 | >0.1.0 and root depends on a, version solving failed.
|
||||
|
||||
hint: Pre-releases are available for b in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||||
"###);
|
||||
});
|
||||
|
||||
|
|
|
@ -158,39 +158,57 @@ impl PubGrubReportFormatter<'_> {
|
|||
derivation_tree: &DerivationTree<PubGrubPackage, Range<PubGrubVersion>>,
|
||||
selector: &CandidateSelector,
|
||||
) -> FxHashSet<PubGrubHint> {
|
||||
/// Returns `true` if pre-releases were allowed for a package.
|
||||
fn allowed_prerelease(package: &PubGrubPackage, selector: &CandidateSelector) -> bool {
|
||||
match selector.prerelease_strategy() {
|
||||
PreReleaseStrategy::Disallow => false,
|
||||
PreReleaseStrategy::Allow => true,
|
||||
PreReleaseStrategy::IfNecessary => false,
|
||||
PreReleaseStrategy::Explicit(packages) => {
|
||||
if let PubGrubPackage::Package(package, ..) = package {
|
||||
packages.contains(package)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
PreReleaseStrategy::IfNecessaryOrExplicit(packages) => {
|
||||
if let PubGrubPackage::Package(package, ..) = package {
|
||||
packages.contains(package)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut hints = FxHashSet::default();
|
||||
match derivation_tree {
|
||||
DerivationTree::External(external) => match external {
|
||||
External::NoVersions(package, set) => {
|
||||
// Determine whether a pre-release marker appeared in the version requirements.
|
||||
if set.bounds().any(PubGrubVersion::any_prerelease) {
|
||||
// Determine whether pre-releases were allowed for this package.
|
||||
let allowed_prerelease = match selector.prerelease_strategy() {
|
||||
PreReleaseStrategy::Disallow => false,
|
||||
PreReleaseStrategy::Allow => true,
|
||||
PreReleaseStrategy::IfNecessary => false,
|
||||
PreReleaseStrategy::Explicit(packages) => {
|
||||
if let PubGrubPackage::Package(package, ..) = package {
|
||||
packages.contains(package)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
PreReleaseStrategy::IfNecessaryOrExplicit(packages) => {
|
||||
if let PubGrubPackage::Package(package, ..) = package {
|
||||
packages.contains(package)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if !allowed_prerelease {
|
||||
hints.insert(PubGrubHint::NoVersionsWithPreRelease {
|
||||
// A pre-release marker appeared in the version requirements.
|
||||
if !allowed_prerelease(package, selector) {
|
||||
hints.insert(PubGrubHint::PreReleaseRequested {
|
||||
package: package.clone(),
|
||||
range: self.simplify_set(set, package).into_owned(),
|
||||
});
|
||||
}
|
||||
} else if let Some(version) =
|
||||
self.available_versions.get(package).and_then(|versions| {
|
||||
versions
|
||||
.iter()
|
||||
.rev()
|
||||
.filter(|version| version.any_prerelease())
|
||||
.find(|version| set.contains(version))
|
||||
})
|
||||
{
|
||||
// There are pre-release versions available for the package.
|
||||
if !allowed_prerelease(package, selector) {
|
||||
hints.insert(PubGrubHint::PreReleaseAvailable {
|
||||
package: package.clone(),
|
||||
version: version.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
External::NotRoot(..) => {}
|
||||
|
@ -210,9 +228,17 @@ impl PubGrubReportFormatter<'_> {
|
|||
#[derive(Derivative, Debug, Clone)]
|
||||
#[derivative(Hash, PartialEq, Eq)]
|
||||
pub(crate) enum PubGrubHint {
|
||||
/// A package was requested with a pre-release marker, but pre-releases weren't enabled for
|
||||
/// that package.
|
||||
NoVersionsWithPreRelease {
|
||||
/// There are pre-release versions available for a package, but pre-releases weren't enabled
|
||||
/// for that package.
|
||||
///
|
||||
PreReleaseAvailable {
|
||||
package: PubGrubPackage,
|
||||
#[derivative(PartialEq = "ignore", Hash = "ignore")]
|
||||
version: PubGrubVersion,
|
||||
},
|
||||
/// A requirement included a pre-release marker, but pre-releases weren't enabled for that
|
||||
/// package.
|
||||
PreReleaseRequested {
|
||||
package: PubGrubPackage,
|
||||
#[derivative(PartialEq = "ignore", Hash = "ignore")]
|
||||
range: Range<PubGrubVersion>,
|
||||
|
@ -222,7 +248,17 @@ pub(crate) enum PubGrubHint {
|
|||
impl std::fmt::Display for PubGrubHint {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
PubGrubHint::NoVersionsWithPreRelease { package, range } => {
|
||||
PubGrubHint::PreReleaseAvailable { package, version } => {
|
||||
write!(
|
||||
f,
|
||||
"{}{} Pre-releases are available for {} in the requested range (e.g., {}), but pre-releases weren't enabled (try: `--prerelease=allow`)",
|
||||
"hint".bold().cyan(),
|
||||
":".bold(),
|
||||
package.bold(),
|
||||
version.bold()
|
||||
)
|
||||
}
|
||||
PubGrubHint::PreReleaseRequested { package, range } => {
|
||||
write!(
|
||||
f,
|
||||
"{}{} {} was requested with a pre-release marker (e.g., {}), but pre-releases weren't enabled (try: `--prerelease=allow`)",
|
||||
|
|
|
@ -493,7 +493,11 @@ async fn black_disallow_prerelease() -> Result<()> {
|
|||
.await
|
||||
.unwrap_err();
|
||||
|
||||
assert_snapshot!(err, @"Because there are no versions of black<=20.0 and root depends on black<=20.0, version solving failed.");
|
||||
assert_snapshot!(err, @r###"
|
||||
Because there are no versions of black<=20.0 and root depends on black<=20.0, version solving failed.
|
||||
|
||||
hint: Pre-releases are available for black in the requested range (e.g., 19.10b0), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -511,7 +515,11 @@ async fn black_allow_prerelease_if_necessary() -> Result<()> {
|
|||
.await
|
||||
.unwrap_err();
|
||||
|
||||
assert_snapshot!(err, @"Because there are no versions of black<=20.0 and root depends on black<=20.0, version solving failed.");
|
||||
assert_snapshot!(err, @r###"
|
||||
Because there are no versions of black<=20.0 and root depends on black<=20.0, version solving failed.
|
||||
|
||||
hint: Pre-releases are available for black in the requested range (e.g., 19.10b0), but pre-releases weren't enabled (try: `--prerelease=allow`)
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue