mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-03 10:33:49 +00:00
Allow displaying the derivation tree (#6124)
I need this for debugging error messages. I used an environment variable instead of a trace log so you can do `UV_INTERNAL__SHOW_DERIVATION_TREE=1` and run a test to see the tree in the test snapshot without further changes. e.g. ```rust // Resolving should fail. uv_snapshot!(context.filters(), context.lock().arg("--preview").current_dir(&workspace), @r###" success: false exit_code: 1 ----- stdout ----- UV_INTERNAL__SHOW_DERIVATION_TREE root==0a0.dev0 depends on foo* root==0a0.dev0 depends on bar[some-extra]* foo==0.1.0 depends on anyio==4.1.0 bar[some-extra]==0.1.0 depends on anyio==4.2.0 no versions of bar[some-extra]<0.1.0 | >0.1.0 ----- stderr ----- Using Python 3.12.[X] interpreter at: [PYTHON-3.12] × No solution found when resolving dependencies: ╰─▶ Because only bar[some-extra]==0.1.0 is available and bar[some-extra] depends on anyio==4.2.0, we can conclude that all versions of bar[some-extra] depend on anyio==4.2.0. And because foo depends on anyio==4.1.0, we can conclude that foo and all versions of bar[some-extra] are incompatible. And because your workspace requires bar[some-extra] and foo, we can conclude that your workspace's requirements are unsatisfiable. "### ); ```
This commit is contained in:
parent
f2d6718038
commit
d7abe827d6
1 changed files with 58 additions and 0 deletions
|
@ -8,6 +8,7 @@ use rustc_hash::FxHashMap;
|
|||
use distribution_types::{BuiltDist, IndexLocations, InstalledDist, SourceDist};
|
||||
use pep440_rs::Version;
|
||||
use pep508_rs::MarkerTree;
|
||||
use tracing::trace;
|
||||
use uv_normalize::PackageName;
|
||||
|
||||
use crate::candidate_selector::CandidateSelector;
|
||||
|
@ -228,6 +229,13 @@ impl std::fmt::Display for NoSolutionError {
|
|||
drop_root_dependency_on_project(&mut tree, project);
|
||||
}
|
||||
|
||||
// Display the tree if enabled
|
||||
if std::env::var_os("UV_INTERNAL__SHOW_DERIVATION_TREE").is_some()
|
||||
|| tracing::enabled!(tracing::Level::TRACE)
|
||||
{
|
||||
display_tree(&tree);
|
||||
}
|
||||
|
||||
let report = DefaultStringReporter::report_with_formatter(&tree, &formatter);
|
||||
write!(f, "{report}")?;
|
||||
|
||||
|
@ -248,6 +256,56 @@ impl std::fmt::Display for NoSolutionError {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::print_stderr)]
|
||||
fn display_tree(error: &DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>) {
|
||||
let mut lines = Vec::new();
|
||||
display_tree_inner(error, &mut lines, 0);
|
||||
lines.reverse();
|
||||
|
||||
if std::env::var_os("UV_INTERNAL__SHOW_DERIVATION_TREE").is_some() {
|
||||
eprintln!("Resolver error derivation tree\n{}", lines.join("\n"));
|
||||
} else {
|
||||
trace!("Resolver error derivation tree\n{}", lines.join("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
fn display_tree_inner(
|
||||
error: &DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>,
|
||||
lines: &mut Vec<String>,
|
||||
depth: usize,
|
||||
) {
|
||||
match error {
|
||||
DerivationTree::Derived(derived) => {
|
||||
display_tree_inner(&derived.cause1, lines, depth + 1);
|
||||
display_tree_inner(&derived.cause2, lines, depth + 1);
|
||||
}
|
||||
DerivationTree::External(external) => {
|
||||
let prefix = " ".repeat(depth).to_string();
|
||||
match external {
|
||||
External::FromDependencyOf(package, version, dependency, dependency_version) => {
|
||||
lines.push(format!(
|
||||
"{prefix}{package}{version} depends on {dependency}{dependency_version}"
|
||||
));
|
||||
}
|
||||
External::Custom(package, versions, reason) => match reason {
|
||||
UnavailableReason::Package(_) => {
|
||||
lines.push(format!("{prefix}{package} {reason}"));
|
||||
}
|
||||
UnavailableReason::Version(_) => {
|
||||
lines.push(format!("{prefix}{package}{versions} {reason}"));
|
||||
}
|
||||
},
|
||||
External::NoVersions(package, versions) => {
|
||||
lines.push(format!("{prefix}no versions of {package}{versions}"));
|
||||
}
|
||||
External::NotRoot(package, versions) => {
|
||||
lines.push(format!("{prefix}not root {package}{versions}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a [`DerivationTree`], collapse any `NoVersion` incompatibilities for workspace members
|
||||
/// to avoid saying things like "only <workspace-member>==0.1.0 is available".
|
||||
fn collapse_no_versions_of_workspace_members(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue