Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve resolver error messages referencing workspace members #6092

Merged
merged 9 commits into from
Aug 15, 2024
56 changes: 55 additions & 1 deletion crates/uv-resolver/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ pub struct NoSolutionError {
incomplete_packages: FxHashMap<PackageName, BTreeMap<Version, IncompletePackage>>,
fork_urls: ForkUrls,
markers: ResolverMarkers,
workspace_members: BTreeSet<PackageName>,
}

impl NoSolutionError {
Expand All @@ -139,6 +140,7 @@ impl NoSolutionError {
incomplete_packages: FxHashMap<PackageName, BTreeMap<Version, IncompletePackage>>,
fork_urls: ForkUrls,
markers: ResolverMarkers,
workspace_members: BTreeSet<PackageName>,
) -> Self {
Self {
error,
Expand All @@ -150,6 +152,7 @@ impl NoSolutionError {
incomplete_packages,
fork_urls,
markers,
workspace_members,
}
}

Expand Down Expand Up @@ -211,8 +214,14 @@ impl std::fmt::Display for NoSolutionError {
let formatter = PubGrubReportFormatter {
available_versions: &self.available_versions,
python_requirement: &self.python_requirement,
workspace_members: &self.workspace_members,
};
let report = DefaultStringReporter::report_with_formatter(&self.error, &formatter);

// Transform the error tree for reporting
let mut tree = self.error.clone();
collapse_unavailable_workspace_members(&mut tree);

let report = DefaultStringReporter::report_with_formatter(&tree, &formatter);
write!(f, "{report}")?;

// Include any additional hints.
Expand All @@ -232,6 +241,51 @@ impl std::fmt::Display for NoSolutionError {
}
}

/// Given a [`DerivationTree`], collapse any [`UnavailablePackage::WorkspaceMember`] incompatibilities
/// to avoid saying things like "only <workspace-member>==0.1.0 is available".
fn collapse_unavailable_workspace_members(
tree: &mut DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>,
) {
match tree {
DerivationTree::External(_) => {}
DerivationTree::Derived(derived) => {
match (
Arc::make_mut(&mut derived.cause1),
Arc::make_mut(&mut derived.cause2),
) {
// If one node is an unavailable workspace member...
(
DerivationTree::External(External::Custom(
_,
_,
UnavailableReason::Package(UnavailablePackage::WorkspaceMember),
)),
ref mut other,
)
| (
ref mut other,
DerivationTree::External(External::Custom(
_,
_,
UnavailableReason::Package(UnavailablePackage::WorkspaceMember),
)),
) => {
// First, recursively collapse the other side of the tree
collapse_unavailable_workspace_members(other);

// Then, replace this node with the other tree
*tree = other.clone();
}
// If not, just recurse
_ => {
collapse_unavailable_workspace_members(Arc::make_mut(&mut derived.cause1));
collapse_unavailable_workspace_members(Arc::make_mut(&mut derived.cause2));
}
}
}
}
}

#[derive(Debug)]
pub struct NoSolutionHeader {
/// The [`ResolverMarkers`] that caused the failure.
Expand Down
7 changes: 7 additions & 0 deletions crates/uv-resolver/src/manifest.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use either::Either;
use std::borrow::Cow;
use std::collections::BTreeSet;

use pep508_rs::MarkerEnvironment;
use pypi_types::Requirement;
Expand Down Expand Up @@ -36,6 +37,9 @@ pub struct Manifest {
/// The name of the project.
pub(crate) project: Option<PackageName>,

/// Members of the project's workspace.
pub(crate) workspace_members: BTreeSet<PackageName>,

/// The installed packages to exclude from consideration during resolution.
///
/// These typically represent packages that are being upgraded or reinstalled
Expand All @@ -58,6 +62,7 @@ impl Manifest {
dev: Vec<GroupName>,
preferences: Preferences,
project: Option<PackageName>,
workspace_members: Option<BTreeSet<PackageName>>,
exclusions: Exclusions,
lookaheads: Vec<RequestedRequirements>,
) -> Self {
Expand All @@ -68,6 +73,7 @@ impl Manifest {
dev,
preferences,
project,
workspace_members: workspace_members.unwrap_or_default(),
exclusions,
lookaheads,
}
Expand All @@ -82,6 +88,7 @@ impl Manifest {
preferences: Preferences::default(),
project: None,
exclusions: Exclusions::default(),
workspace_members: BTreeSet::new(),
lookaheads: Vec::new(),
}
}
Expand Down
Loading
Loading