Skip to content

Commit

Permalink
Use rich diagnostics for build failures (#9335)
Browse files Browse the repository at this point in the history
## Summary

Closes #9323.
  • Loading branch information
charliermarsh authored Nov 26, 2024
1 parent 916d5d7 commit 2534156
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 46 deletions.
48 changes: 29 additions & 19 deletions crates/uv/src/commands/build_frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ async fn build_impl(
}))
.await;

for (source, result) in &results {
let mut success = true;
for (source, result) in results {
match result {
Ok(assets) => match assets {
BuiltDistributions::Wheel(wheel) => {
Expand All @@ -318,31 +319,30 @@ async fn build_impl(
}
},
Err(err) => {
let mut causes = err.chain();
#[derive(Debug, miette::Diagnostic, thiserror::Error)]
#[error("Failed to build `{source}`", source = source.cyan())]
#[diagnostic()]
struct Diagnostic {
source: String,
#[source]
cause: anyhow::Error,
}

let message = format!(
"{}: {}",
"error".red().bold(),
causes.next().unwrap().to_string().trim()
);
writeln!(printer.stderr(), "{}", source.annotate(&message))?;
let report = miette::Report::new(Diagnostic {
source: source.to_string(),
cause: err,
});
anstream::eprint!("{report:?}");

for err in causes {
writeln!(
printer.stderr(),
" {}: {}",
"Caused by".red().bold(),
err.to_string().trim()
)?;
}
success = false;
}
}
}

if results.iter().any(|(_, result)| result.is_err()) {
Ok(BuildResult::Failure)
} else {
if success {
Ok(BuildResult::Success)
} else {
Ok(BuildResult::Failure)
}
}

Expand Down Expand Up @@ -818,6 +818,16 @@ impl<'a> From<Source<'a>> for AnnotatedSource<'a> {
}
}

impl std::fmt::Display for AnnotatedSource<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(package) = &self.package {
write!(f, "{} @ {}", package, self.path().simplified_display())
} else {
write!(f, "{}", self.path().simplified_display())
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
enum Source<'a> {
/// The input source is a file (i.e., a source distribution in a `.tar.gz` or `.zip` file).
Expand Down
63 changes: 36 additions & 27 deletions crates/uv/tests/it/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ fn build() -> Result<()> {
----- stderr -----
Building source distribution...
error: [TEMP_DIR]/ does not appear to be a Python project, as neither `pyproject.toml` nor `setup.py` are present in the directory
× Failed to build `[TEMP_DIR]/`
╰─▶ [TEMP_DIR]/ does not appear to be a Python project, as neither `pyproject.toml` nor `setup.py` are present in the directory
"###);

// Build to a specified path.
Expand Down Expand Up @@ -738,7 +738,8 @@ fn wheel_from_sdist() -> Result<()> {
----- stdout -----
----- stderr -----
error: Pass `--wheel` explicitly to build a wheel from a source distribution
× Failed to build `[TEMP_DIR]/project/dist/project-0.1.0.tar.gz`
╰─▶ Pass `--wheel` explicitly to build a wheel from a source distribution
"###);

// Error if `--sdist` is specified.
Expand All @@ -748,7 +749,8 @@ fn wheel_from_sdist() -> Result<()> {
----- stdout -----
----- stderr -----
error: Building an `--sdist` from a source distribution is not supported
× Failed to build `[TEMP_DIR]/project/dist/project-0.1.0.tar.gz`
╰─▶ Building an `--sdist` from a source distribution is not supported
"###);

// Build the wheel from the sdist.
Expand Down Expand Up @@ -816,7 +818,8 @@ fn wheel_from_sdist() -> Result<()> {
----- stderr -----
Building wheel from source distribution...
error: `dist/project-0.1.0-py3-none-any.whl` is not a valid build source. Expected to receive a source directory, or a source distribution ending in one of: `.tar.gz`, `.zip`, `.tar.bz2`, `.tar.lz`, `.tar.lzma`, `.tar.xz`, `.tar.zst`, `.tar`, `.tbz`, `.tgz`, `.tlz`, or `.txz`.
× Failed to build `[TEMP_DIR]/project/dist/project-0.1.0-py3-none-any.whl`
╰─▶ `dist/project-0.1.0-py3-none-any.whl` is not a valid build source. Expected to receive a source directory, or a source distribution ending in one of: `.tar.gz`, `.zip`, `.tar.bz2`, `.tar.lz`, `.tar.lzma`, `.tar.xz`, `.tar.zst`, `.tar`, `.tbz`, `.tgz`, `.tlz`, or `.txz`.
"###);

Ok(())
Expand Down Expand Up @@ -888,7 +891,8 @@ fn fail() -> Result<()> {
File "<string>", line 2
from setuptools import setup
IndentationError: unexpected indent
error: Build backend failed to determine requirements with `build_sdist()` (exit status: 1)
× Failed to build `[TEMP_DIR]/project`
╰─▶ Build backend failed to determine requirements with `build_sdist()` (exit status: 1)
"###);

Ok(())
Expand Down Expand Up @@ -1328,7 +1332,8 @@ fn build_all_with_failure() -> Result<()> {
[PKG] Building wheel from source distribution...
[PKG] Building wheel from source distribution...
Successfully built dist/member_a-0.1.0.tar.gz and dist/member_a-0.1.0-py3-none-any.whl
[PKG] error: Build backend failed to determine requirements with `build_sdist()` (exit status: 1)
× Failed to build `member-b @ [TEMP_DIR]/project/packages/member_b`
╰─▶ Build backend failed to determine requirements with `build_sdist()` (exit status: 1)
Successfully built dist/project-0.1.0.tar.gz and dist/project-0.1.0-py3-none-any.whl
"###);

Expand Down Expand Up @@ -1397,9 +1402,10 @@ fn build_constraints() -> Result<()> {
----- stderr -----
Building source distribution...
error: Failed to resolve requirements from `build-system.requires`
Caused by: No solution found when resolving: `setuptools>=42`
Caused by: Because you require setuptools>=42 and setuptools==0.1.0, we can conclude that your requirements are unsatisfiable.
× Failed to build `[TEMP_DIR]/project`
├─▶ Failed to resolve requirements from `build-system.requires`
├─▶ No solution found when resolving: `setuptools>=42`
╰─▶ Because you require setuptools>=42 and setuptools==0.1.0, we can conclude that your requirements are unsatisfiable.
"###);

project
Expand Down Expand Up @@ -1458,15 +1464,16 @@ fn sha() -> Result<()> {
----- stderr -----
Building source distribution...
error: Failed to install requirements from `build-system.requires`
Caused by: Failed to download `setuptools==68.2.2`
Caused by: Hash mismatch for `setuptools==68.2.2`
× Failed to build `[TEMP_DIR]/project`
├─▶ Failed to install requirements from `build-system.requires`
├─▶ Failed to download `setuptools==68.2.2`
╰─▶ Hash mismatch for `setuptools==68.2.2`
Expected:
sha256:a248cb506794bececcddeddb1678bc722f9cfcacf02f98f7c0af6b9ed893caf2
Expected:
sha256:a248cb506794bececcddeddb1678bc722f9cfcacf02f98f7c0af6b9ed893caf2
Computed:
sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a
Computed:
sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a
"###);

project
Expand All @@ -1488,15 +1495,16 @@ fn sha() -> Result<()> {
----- stderr -----
Building source distribution...
error: Failed to install requirements from `build-system.requires`
Caused by: Failed to download `setuptools==68.2.2`
Caused by: Hash mismatch for `setuptools==68.2.2`
× Failed to build `[TEMP_DIR]/project`
├─▶ Failed to install requirements from `build-system.requires`
├─▶ Failed to download `setuptools==68.2.2`
╰─▶ Hash mismatch for `setuptools==68.2.2`
Expected:
sha256:a248cb506794bececcddeddb1678bc722f9cfcacf02f98f7c0af6b9ed893caf2
Expected:
sha256:a248cb506794bececcddeddb1678bc722f9cfcacf02f98f7c0af6b9ed893caf2
Computed:
sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a
Computed:
sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a
"###);

project
Expand All @@ -1521,9 +1529,10 @@ fn sha() -> Result<()> {
----- stderr -----
Building source distribution...
error: Failed to resolve requirements from `build-system.requires`
Caused by: No solution found when resolving: `setuptools>=42`
Caused by: In `--require-hashes` mode, all requirements must be pinned upfront with `==`, but found: `setuptools`
× Failed to build `[TEMP_DIR]/project`
├─▶ Failed to resolve requirements from `build-system.requires`
├─▶ No solution found when resolving: `setuptools>=42`
╰─▶ In `--require-hashes` mode, all requirements must be pinned upfront with `==`, but found: `setuptools`
"###);

project
Expand Down

0 comments on commit 2534156

Please sign in to comment.