mirror of https://github.com/astral-sh/uv
Improve legibility of build failure errors (#7854)
## Summary We now... - Only show `stdout` and/or `stderr` if they're non-empty. - Use a colorful header for the start of each section - Highlight the step that failed ## Test Plan 
This commit is contained in:
parent
d5c5a29490
commit
005bb235f0
|
|
@ -4267,6 +4267,7 @@ dependencies = [
|
||||||
"indoc",
|
"indoc",
|
||||||
"insta",
|
"insta",
|
||||||
"itertools 0.13.0",
|
"itertools 0.13.0",
|
||||||
|
"owo-colors",
|
||||||
"regex",
|
"regex",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ anyhow = { workspace = true }
|
||||||
fs-err = { workspace = true }
|
fs-err = { workspace = true }
|
||||||
indoc = { workspace = true }
|
indoc = { workspace = true }
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
|
owo-colors = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::PythonRunnerOutput;
|
|
||||||
use itertools::Itertools;
|
|
||||||
use regex::Regex;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::ExitStatus;
|
use std::process::ExitStatus;
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
|
use regex::Regex;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use uv_configuration::BuildOutput;
|
use uv_configuration::BuildOutput;
|
||||||
|
|
@ -14,6 +14,8 @@ use uv_fs::Simplified;
|
||||||
use uv_pep440::Version;
|
use uv_pep440::Version;
|
||||||
use uv_pep508::PackageName;
|
use uv_pep508::PackageName;
|
||||||
|
|
||||||
|
use crate::PythonRunnerOutput;
|
||||||
|
|
||||||
/// e.g. `pygraphviz/graphviz_wrap.c:3020:10: fatal error: graphviz/cgraph.h: No such file or directory`
|
/// e.g. `pygraphviz/graphviz_wrap.c:3020:10: fatal error: graphviz/cgraph.h: No such file or directory`
|
||||||
static MISSING_HEADER_RE_GCC: LazyLock<Regex> = LazyLock::new(|| {
|
static MISSING_HEADER_RE_GCC: LazyLock<Regex> = LazyLock::new(|| {
|
||||||
Regex::new(
|
Regex::new(
|
||||||
|
|
@ -71,35 +73,10 @@ pub enum Error {
|
||||||
Virtualenv(#[from] uv_virtualenv::Error),
|
Virtualenv(#[from] uv_virtualenv::Error),
|
||||||
#[error("Failed to run `{0}`")]
|
#[error("Failed to run `{0}`")]
|
||||||
CommandFailed(PathBuf, #[source] io::Error),
|
CommandFailed(PathBuf, #[source] io::Error),
|
||||||
#[error("{message} ({exit_code})\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")]
|
#[error(transparent)]
|
||||||
BuildBackendOutput {
|
BuildBackend(#[from] BuildBackendError),
|
||||||
message: String,
|
#[error(transparent)]
|
||||||
exit_code: ExitStatus,
|
MissingHeader(#[from] MissingHeaderError),
|
||||||
stdout: String,
|
|
||||||
stderr: String,
|
|
||||||
},
|
|
||||||
/// Nudge the user towards installing the missing dev library
|
|
||||||
#[error("{message} ({exit_code})\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")]
|
|
||||||
MissingHeaderOutput {
|
|
||||||
message: String,
|
|
||||||
exit_code: ExitStatus,
|
|
||||||
stdout: String,
|
|
||||||
stderr: String,
|
|
||||||
#[source]
|
|
||||||
missing_header_cause: MissingHeaderCause,
|
|
||||||
},
|
|
||||||
#[error("{message} ({exit_code})")]
|
|
||||||
BuildBackend {
|
|
||||||
message: String,
|
|
||||||
exit_code: ExitStatus,
|
|
||||||
},
|
|
||||||
#[error("{message} ({exit_code})")]
|
|
||||||
MissingHeader {
|
|
||||||
message: String,
|
|
||||||
exit_code: ExitStatus,
|
|
||||||
#[source]
|
|
||||||
missing_header_cause: MissingHeaderCause,
|
|
||||||
},
|
|
||||||
#[error("Failed to build PATH for build script")]
|
#[error("Failed to build PATH for build script")]
|
||||||
BuildScriptPath(#[source] env::JoinPathsError),
|
BuildScriptPath(#[source] env::JoinPathsError),
|
||||||
}
|
}
|
||||||
|
|
@ -202,6 +179,72 @@ impl Display for MissingHeaderCause {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub struct BuildBackendError {
|
||||||
|
message: String,
|
||||||
|
exit_code: ExitStatus,
|
||||||
|
stdout: Vec<String>,
|
||||||
|
stderr: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for BuildBackendError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} ({})", self.message, self.exit_code)?;
|
||||||
|
|
||||||
|
let mut non_empty = false;
|
||||||
|
|
||||||
|
if self.stdout.iter().any(|line| !line.trim().is_empty()) {
|
||||||
|
write!(f, "\n\n{}\n{}", "[stdout]".red(), self.stdout.join("\n"))?;
|
||||||
|
non_empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.stderr.iter().any(|line| !line.trim().is_empty()) {
|
||||||
|
write!(f, "\n\n{}\n{}", "[stderr]".red(), self.stderr.join("\n"))?;
|
||||||
|
non_empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if non_empty {
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub struct MissingHeaderError {
|
||||||
|
message: String,
|
||||||
|
exit_code: ExitStatus,
|
||||||
|
stdout: Vec<String>,
|
||||||
|
stderr: Vec<String>,
|
||||||
|
#[source]
|
||||||
|
cause: MissingHeaderCause,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for MissingHeaderError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} ({})", self.message, self.exit_code)?;
|
||||||
|
|
||||||
|
let mut non_empty = false;
|
||||||
|
|
||||||
|
if self.stdout.iter().any(|line| !line.trim().is_empty()) {
|
||||||
|
write!(f, "\n\n{}\n{}", "[stdout]".red(), self.stdout.join("\n"))?;
|
||||||
|
non_empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.stderr.iter().any(|line| !line.trim().is_empty()) {
|
||||||
|
write!(f, "\n\n{}\n{}", "[stderr]".red(), self.stderr.join("\n"))?;
|
||||||
|
non_empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if non_empty {
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
/// Construct an [`Error`] from the output of a failed command.
|
/// Construct an [`Error`] from the output of a failed command.
|
||||||
pub(crate) fn from_command_output(
|
pub(crate) fn from_command_output(
|
||||||
|
|
@ -241,42 +284,48 @@ impl Error {
|
||||||
|
|
||||||
if let Some(missing_library) = missing_library {
|
if let Some(missing_library) = missing_library {
|
||||||
return match level {
|
return match level {
|
||||||
BuildOutput::Stderr | BuildOutput::Quiet => Self::MissingHeader {
|
BuildOutput::Stderr | BuildOutput::Quiet => {
|
||||||
|
Self::MissingHeader(MissingHeaderError {
|
||||||
message,
|
message,
|
||||||
exit_code: output.status,
|
exit_code: output.status,
|
||||||
missing_header_cause: MissingHeaderCause {
|
stdout: vec![],
|
||||||
|
stderr: vec![],
|
||||||
|
cause: MissingHeaderCause {
|
||||||
missing_library,
|
missing_library,
|
||||||
package_name: name.cloned(),
|
package_name: name.cloned(),
|
||||||
package_version: version.cloned(),
|
package_version: version.cloned(),
|
||||||
version_id: version_id.map(ToString::to_string),
|
version_id: version_id.map(ToString::to_string),
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
BuildOutput::Debug => Self::MissingHeaderOutput {
|
}
|
||||||
|
BuildOutput::Debug => Self::MissingHeader(MissingHeaderError {
|
||||||
message,
|
message,
|
||||||
exit_code: output.status,
|
exit_code: output.status,
|
||||||
stdout: output.stdout.iter().join("\n"),
|
stdout: output.stdout.clone(),
|
||||||
stderr: output.stderr.iter().join("\n"),
|
stderr: output.stderr.clone(),
|
||||||
missing_header_cause: MissingHeaderCause {
|
cause: MissingHeaderCause {
|
||||||
missing_library,
|
missing_library,
|
||||||
package_name: name.cloned(),
|
package_name: name.cloned(),
|
||||||
package_version: version.cloned(),
|
package_version: version.cloned(),
|
||||||
version_id: version_id.map(ToString::to_string),
|
version_id: version_id.map(ToString::to_string),
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
match level {
|
match level {
|
||||||
BuildOutput::Stderr | BuildOutput::Quiet => Self::BuildBackend {
|
BuildOutput::Stderr | BuildOutput::Quiet => Self::BuildBackend(BuildBackendError {
|
||||||
message,
|
message,
|
||||||
exit_code: output.status,
|
exit_code: output.status,
|
||||||
},
|
stdout: vec![],
|
||||||
BuildOutput::Debug => Self::BuildBackendOutput {
|
stderr: vec![],
|
||||||
|
}),
|
||||||
|
BuildOutput::Debug => Self::BuildBackend(BuildBackendError {
|
||||||
message,
|
message,
|
||||||
exit_code: output.status,
|
exit_code: output.status,
|
||||||
stdout: output.stdout.iter().join("\n"),
|
stdout: output.stdout.clone(),
|
||||||
stderr: output.stderr.iter().join("\n"),
|
stderr: output.stderr.clone(),
|
||||||
},
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -325,18 +374,22 @@ mod test {
|
||||||
None,
|
None,
|
||||||
Some("pygraphviz-1.11"),
|
Some("pygraphviz-1.11"),
|
||||||
);
|
);
|
||||||
assert!(matches!(err, Error::MissingHeaderOutput { .. }));
|
|
||||||
|
assert!(matches!(err, Error::MissingHeader { .. }));
|
||||||
// Unix uses exit status, Windows uses exit code.
|
// Unix uses exit status, Windows uses exit code.
|
||||||
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
||||||
|
let formatted = anstream::adapter::strip_str(&formatted);
|
||||||
insta::assert_snapshot!(formatted, @r###"
|
insta::assert_snapshot!(formatted, @r###"
|
||||||
Failed building wheel through setup.py (exit code: 0)
|
Failed building wheel through setup.py (exit code: 0)
|
||||||
--- stdout:
|
|
||||||
|
[stdout]
|
||||||
running bdist_wheel
|
running bdist_wheel
|
||||||
running build
|
running build
|
||||||
[...]
|
[...]
|
||||||
creating build/temp.linux-x86_64-cpython-39/pygraphviz
|
creating build/temp.linux-x86_64-cpython-39/pygraphviz
|
||||||
gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -DOPENSSL_NO_SSL3 -fPIC -DSWIG_PYTHON_STRICT_BYTE_CHAR -I/tmp/.tmpy6vVes/.venv/include -I/home/konsti/.pyenv/versions/3.9.18/include/python3.9 -c pygraphviz/graphviz_wrap.c -o build/temp.linux-x86_64-cpython-39/pygraphviz/graphviz_wrap.o
|
gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -DOPENSSL_NO_SSL3 -fPIC -DSWIG_PYTHON_STRICT_BYTE_CHAR -I/tmp/.tmpy6vVes/.venv/include -I/home/konsti/.pyenv/versions/3.9.18/include/python3.9 -c pygraphviz/graphviz_wrap.c -o build/temp.linux-x86_64-cpython-39/pygraphviz/graphviz_wrap.o
|
||||||
--- stderr:
|
|
||||||
|
[stderr]
|
||||||
warning: no files found matching '*.png' under directory 'doc'
|
warning: no files found matching '*.png' under directory 'doc'
|
||||||
warning: no files found matching '*.txt' under directory 'doc'
|
warning: no files found matching '*.txt' under directory 'doc'
|
||||||
[...]
|
[...]
|
||||||
|
|
@ -346,7 +399,6 @@ mod test {
|
||||||
| ^~~~~~~~~~~~~~~~~~~
|
| ^~~~~~~~~~~~~~~~~~~
|
||||||
compilation terminated.
|
compilation terminated.
|
||||||
error: command '/usr/bin/gcc' failed with exit code 1
|
error: command '/usr/bin/gcc' failed with exit code 1
|
||||||
---
|
|
||||||
"###);
|
"###);
|
||||||
insta::assert_snapshot!(
|
insta::assert_snapshot!(
|
||||||
std::error::Error::source(&err).unwrap(),
|
std::error::Error::source(&err).unwrap(),
|
||||||
|
|
@ -380,20 +432,19 @@ mod test {
|
||||||
None,
|
None,
|
||||||
Some("pygraphviz-1.11"),
|
Some("pygraphviz-1.11"),
|
||||||
);
|
);
|
||||||
assert!(matches!(err, Error::MissingHeaderOutput { .. }));
|
assert!(matches!(err, Error::MissingHeader { .. }));
|
||||||
// Unix uses exit status, Windows uses exit code.
|
// Unix uses exit status, Windows uses exit code.
|
||||||
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
||||||
|
let formatted = anstream::adapter::strip_str(&formatted);
|
||||||
insta::assert_snapshot!(formatted, @r###"
|
insta::assert_snapshot!(formatted, @r###"
|
||||||
Failed building wheel through setup.py (exit code: 0)
|
Failed building wheel through setup.py (exit code: 0)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
1099 | n = strlen(p);
|
1099 | n = strlen(p);
|
||||||
| ^~~~~~~~~
|
| ^~~~~~~~~
|
||||||
/usr/bin/ld: cannot find -lncurses: No such file or directory
|
/usr/bin/ld: cannot find -lncurses: No such file or directory
|
||||||
collect2: error: ld returned 1 exit status
|
collect2: error: ld returned 1 exit status
|
||||||
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
|
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
|
||||||
---
|
|
||||||
"###);
|
"###);
|
||||||
insta::assert_snapshot!(
|
insta::assert_snapshot!(
|
||||||
std::error::Error::source(&err).unwrap(),
|
std::error::Error::source(&err).unwrap(),
|
||||||
|
|
@ -428,21 +479,20 @@ mod test {
|
||||||
None,
|
None,
|
||||||
Some("pygraphviz-1.11"),
|
Some("pygraphviz-1.11"),
|
||||||
);
|
);
|
||||||
assert!(matches!(err, Error::MissingHeaderOutput { .. }));
|
assert!(matches!(err, Error::MissingHeader { .. }));
|
||||||
// Unix uses exit status, Windows uses exit code.
|
// Unix uses exit status, Windows uses exit code.
|
||||||
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
||||||
|
let formatted = anstream::adapter::strip_str(&formatted);
|
||||||
insta::assert_snapshot!(formatted, @r###"
|
insta::assert_snapshot!(formatted, @r###"
|
||||||
Failed building wheel through setup.py (exit code: 0)
|
Failed building wheel through setup.py (exit code: 0)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
|
usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
|
||||||
or: setup.py --help [cmd1 cmd2 ...]
|
or: setup.py --help [cmd1 cmd2 ...]
|
||||||
or: setup.py --help-commands
|
or: setup.py --help-commands
|
||||||
or: setup.py cmd --help
|
or: setup.py cmd --help
|
||||||
|
|
||||||
error: invalid command 'bdist_wheel'
|
error: invalid command 'bdist_wheel'
|
||||||
---
|
|
||||||
"###);
|
"###);
|
||||||
insta::assert_snapshot!(
|
insta::assert_snapshot!(
|
||||||
std::error::Error::source(&err).unwrap(),
|
std::error::Error::source(&err).unwrap(),
|
||||||
|
|
@ -474,17 +524,16 @@ mod test {
|
||||||
Some(&Version::new([1, 11])),
|
Some(&Version::new([1, 11])),
|
||||||
Some("pygraphviz-1.11"),
|
Some("pygraphviz-1.11"),
|
||||||
);
|
);
|
||||||
assert!(matches!(err, Error::MissingHeaderOutput { .. }));
|
assert!(matches!(err, Error::MissingHeader { .. }));
|
||||||
// Unix uses exit status, Windows uses exit code.
|
// Unix uses exit status, Windows uses exit code.
|
||||||
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
||||||
|
let formatted = anstream::adapter::strip_str(&formatted);
|
||||||
insta::assert_snapshot!(formatted, @r###"
|
insta::assert_snapshot!(formatted, @r###"
|
||||||
Failed building wheel through setup.py (exit code: 0)
|
Failed building wheel through setup.py (exit code: 0)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
import distutils.core
|
import distutils.core
|
||||||
ModuleNotFoundError: No module named 'distutils'
|
ModuleNotFoundError: No module named 'distutils'
|
||||||
---
|
|
||||||
"###);
|
"###);
|
||||||
insta::assert_snapshot!(
|
insta::assert_snapshot!(
|
||||||
std::error::Error::source(&err).unwrap(),
|
std::error::Error::source(&err).unwrap(),
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ mod error;
|
||||||
use fs_err as fs;
|
use fs_err as fs;
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use serde::de::{value, IntoDeserializer, SeqAccess, Visitor};
|
use serde::de::{value, IntoDeserializer, SeqAccess, Visitor};
|
||||||
use serde::{de, Deserialize, Deserializer};
|
use serde::{de, Deserialize, Deserializer};
|
||||||
|
|
@ -564,7 +565,10 @@ impl SourceBuild {
|
||||||
.await?;
|
.await?;
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(Error::from_command_output(
|
return Err(Error::from_command_output(
|
||||||
format!("Build backend failed to determine metadata through `prepare_metadata_for_build_{}`", self.build_kind),
|
format!(
|
||||||
|
"Build backend failed to determine metadata through `{}`",
|
||||||
|
format!("prepare_metadata_for_build_{}", self.build_kind).green()
|
||||||
|
),
|
||||||
&output,
|
&output,
|
||||||
self.level,
|
self.level,
|
||||||
self.package_name.as_ref(),
|
self.package_name.as_ref(),
|
||||||
|
|
@ -694,8 +698,9 @@ impl SourceBuild {
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(Error::from_command_output(
|
return Err(Error::from_command_output(
|
||||||
format!(
|
format!(
|
||||||
"Build backend failed to build {} through `build_{}()`",
|
"Build backend failed to build {} through `{}`",
|
||||||
self.build_kind, self.build_kind,
|
self.build_kind,
|
||||||
|
format!("build_{}", self.build_kind).green(),
|
||||||
),
|
),
|
||||||
&output,
|
&output,
|
||||||
self.level,
|
self.level,
|
||||||
|
|
@ -709,8 +714,8 @@ impl SourceBuild {
|
||||||
if !output_dir.join(&distribution_filename).is_file() {
|
if !output_dir.join(&distribution_filename).is_file() {
|
||||||
return Err(Error::from_command_output(
|
return Err(Error::from_command_output(
|
||||||
format!(
|
format!(
|
||||||
"Build backend failed to produce {} through `build_{}()`: `{distribution_filename}` not found",
|
"Build backend failed to produce {} through `{}`: `{distribution_filename}` not found",
|
||||||
self.build_kind, self.build_kind,
|
self.build_kind, format!("build_{}", self.build_kind).green(),
|
||||||
),
|
),
|
||||||
&output,
|
&output,
|
||||||
self.level,
|
self.level,
|
||||||
|
|
@ -802,7 +807,10 @@ async fn create_pep517_build_environment(
|
||||||
.await?;
|
.await?;
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(Error::from_command_output(
|
return Err(Error::from_command_output(
|
||||||
format!("Build backend failed to determine requirements with `build_{build_kind}()`"),
|
format!(
|
||||||
|
"Build backend failed to determine requirements with `{}`",
|
||||||
|
format!("build_{build_kind}()").green()
|
||||||
|
),
|
||||||
&output,
|
&output,
|
||||||
level,
|
level,
|
||||||
package_name,
|
package_name,
|
||||||
|
|
@ -815,7 +823,8 @@ async fn create_pep517_build_environment(
|
||||||
let contents = fs_err::read(&outfile).map_err(|err| {
|
let contents = fs_err::read(&outfile).map_err(|err| {
|
||||||
Error::from_command_output(
|
Error::from_command_output(
|
||||||
format!(
|
format!(
|
||||||
"Build backend failed to read requirements from `get_requires_for_build_{build_kind}`: {err}"
|
"Build backend failed to read requirements from `{}`: {err}",
|
||||||
|
format!("get_requires_for_build_{build_kind}").green(),
|
||||||
),
|
),
|
||||||
&output,
|
&output,
|
||||||
level,
|
level,
|
||||||
|
|
@ -826,10 +835,13 @@ async fn create_pep517_build_environment(
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Deserialize the requirements from the output file.
|
// Deserialize the requirements from the output file.
|
||||||
let extra_requires: Vec<uv_pep508::Requirement<VerbatimParsedUrl>> = serde_json::from_slice::<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>(&contents).map_err(|err| {
|
let extra_requires: Vec<uv_pep508::Requirement<VerbatimParsedUrl>> =
|
||||||
|
serde_json::from_slice::<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>(&contents)
|
||||||
|
.map_err(|err| {
|
||||||
Error::from_command_output(
|
Error::from_command_output(
|
||||||
format!(
|
format!(
|
||||||
"Build backend failed to return requirements from `get_requires_for_build_{build_kind}`: {err}"
|
"Build backend failed to return requirements from `{}`: {err}",
|
||||||
|
format!("get_requires_for_build_{build_kind}").green(),
|
||||||
),
|
),
|
||||||
&output,
|
&output,
|
||||||
level,
|
level,
|
||||||
|
|
|
||||||
|
|
@ -4594,10 +4594,9 @@ fn fail_to_add_revert_project() -> Result<()> {
|
||||||
Resolved 2 packages in [TIME]
|
Resolved 2 packages in [TIME]
|
||||||
error: Failed to prepare distributions
|
error: Failed to prepare distributions
|
||||||
Caused by: Failed to fetch wheel: pytorch==1.0.2
|
Caused by: Failed to fetch wheel: pytorch==1.0.2
|
||||||
Caused by: Build backend failed to build wheel through `build_wheel()` (exit status: 1)
|
Caused by: Build backend failed to build wheel through `build_wheel` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<string>", line 11, in <module>
|
File "<string>", line 11, in <module>
|
||||||
File "[CACHE_DIR]/builds-v0/[TMP]/build_meta.py", line 410, in build_wheel
|
File "[CACHE_DIR]/builds-v0/[TMP]/build_meta.py", line 410, in build_wheel
|
||||||
|
|
@ -4611,7 +4610,7 @@ fn fail_to_add_revert_project() -> Result<()> {
|
||||||
exec(code, locals())
|
exec(code, locals())
|
||||||
File "<string>", line 15, in <module>
|
File "<string>", line 15, in <module>
|
||||||
Exception: You tried to install "pytorch". The package named for PyTorch is "torch"
|
Exception: You tried to install "pytorch". The package named for PyTorch is "torch"
|
||||||
---
|
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let pyproject_toml = context.read("pyproject.toml");
|
let pyproject_toml = context.read("pyproject.toml");
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,8 @@ dependencies = ["flask==1.0.x"]
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
error: Failed to build: `project @ file://[TEMP_DIR]/path_dep`
|
error: Failed to build: `project @ file://[TEMP_DIR]/path_dep`
|
||||||
Caused by: Build backend failed to determine requirements with `build_wheel()` (exit status: 1)
|
Caused by: Build backend failed to determine requirements with `build_wheel()` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
[stdout]
|
||||||
configuration error: `project.dependencies[0]` must be pep508
|
configuration error: `project.dependencies[0]` must be pep508
|
||||||
DESCRIPTION:
|
DESCRIPTION:
|
||||||
Project dependency specification according to PEP 508
|
Project dependency specification according to PEP 508
|
||||||
|
|
@ -257,7 +258,8 @@ dependencies = ["flask==1.0.x"]
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "pep508"
|
"format": "pep508"
|
||||||
}
|
}
|
||||||
--- stderr:
|
|
||||||
|
[stderr]
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<string>", line 14, in <module>
|
File "<string>", line 14, in <module>
|
||||||
File "[CACHE_DIR]/builds-v0/[TMP]/build_meta.py", line 325, in get_requires_for_build_wheel
|
File "[CACHE_DIR]/builds-v0/[TMP]/build_meta.py", line 325, in get_requires_for_build_wheel
|
||||||
|
|
@ -289,7 +291,7 @@ dependencies = ["flask==1.0.x"]
|
||||||
raise ValueError(f"{error}/n{summary}") from None
|
raise ValueError(f"{error}/n{summary}") from None
|
||||||
ValueError: invalid pyproject.toml config: `project.dependencies[0]`.
|
ValueError: invalid pyproject.toml config: `project.dependencies[0]`.
|
||||||
configuration error: `project.dependencies[0]` must be pep508
|
configuration error: `project.dependencies[0]` must be pep508
|
||||||
---
|
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -3834,13 +3836,12 @@ fn no_build_isolation() -> Result<()> {
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
error: Failed to download and build: `anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz`
|
error: Failed to download and build: `anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz`
|
||||||
Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1)
|
Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<string>", line 8, in <module>
|
File "<string>", line 8, in <module>
|
||||||
ModuleNotFoundError: No module named 'setuptools'
|
ModuleNotFoundError: No module named 'setuptools'
|
||||||
---
|
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -3904,13 +3905,12 @@ fn respect_no_build_isolation_env_var() -> Result<()> {
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
error: Failed to download and build: `anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz`
|
error: Failed to download and build: `anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz`
|
||||||
Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1)
|
Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<string>", line 8, in <module>
|
File "<string>", line 8, in <module>
|
||||||
ModuleNotFoundError: No module named 'setuptools'
|
ModuleNotFoundError: No module named 'setuptools'
|
||||||
---
|
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -6850,13 +6850,12 @@ fn install_build_isolation_package() -> Result<()> {
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
error: Failed to download and build: `iniconfig @ https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz`
|
error: Failed to download and build: `iniconfig @ https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz`
|
||||||
Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1)
|
Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<string>", line 8, in <module>
|
File "<string>", line 8, in <module>
|
||||||
ModuleNotFoundError: No module named 'hatchling'
|
ModuleNotFoundError: No module named 'hatchling'
|
||||||
---
|
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -7111,9 +7110,8 @@ fn sklearn() {
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
× Failed to download and build `sklearn==0.0.post12`
|
× Failed to download and build `sklearn==0.0.post12`
|
||||||
╰─▶ Build backend failed to determine requirements with `build_wheel()` (exit status: 1)
|
╰─▶ Build backend failed to determine requirements with `build_wheel()` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
The 'sklearn' PyPI package is deprecated, use 'scikit-learn'
|
The 'sklearn' PyPI package is deprecated, use 'scikit-learn'
|
||||||
rather than 'sklearn' for pip commands.
|
rather than 'sklearn' for pip commands.
|
||||||
|
|
||||||
|
|
@ -7129,7 +7127,7 @@ fn sklearn() {
|
||||||
|
|
||||||
More information is available at
|
More information is available at
|
||||||
https://github.com/scikit-learn/sklearn-pypi-package
|
https://github.com/scikit-learn/sklearn-pypi-package
|
||||||
---
|
|
||||||
help: `sklearn` is often confused for `scikit-learn` Did you mean to install `scikit-learn` instead?
|
help: `sklearn` is often confused for `scikit-learn` Did you mean to install `scikit-learn` instead?
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -577,14 +577,13 @@ fn sync_build_isolation_package() -> Result<()> {
|
||||||
Resolved 2 packages in [TIME]
|
Resolved 2 packages in [TIME]
|
||||||
error: Failed to prepare distributions
|
error: Failed to prepare distributions
|
||||||
Caused by: Failed to fetch wheel: source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz
|
Caused by: Failed to fetch wheel: source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz
|
||||||
Caused by: Build backend failed to build wheel through `build_wheel()` (exit status: 1)
|
Caused by: Build backend failed to build wheel through `build_wheel` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<string>", line 8, in <module>
|
File "<string>", line 8, in <module>
|
||||||
ModuleNotFoundError: No module named 'hatchling'
|
ModuleNotFoundError: No module named 'hatchling'
|
||||||
---
|
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Install `hatchling` for `source-distribution`.
|
// Install `hatchling` for `source-distribution`.
|
||||||
|
|
@ -669,14 +668,13 @@ fn sync_build_isolation_extra() -> Result<()> {
|
||||||
Resolved [N] packages in [TIME]
|
Resolved [N] packages in [TIME]
|
||||||
error: Failed to prepare distributions
|
error: Failed to prepare distributions
|
||||||
Caused by: Failed to fetch wheel: source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz
|
Caused by: Failed to fetch wheel: source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz
|
||||||
Caused by: Build backend failed to build wheel through `build_wheel()` (exit status: 1)
|
Caused by: Build backend failed to build wheel through `build_wheel` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<string>", line 8, in <module>
|
File "<string>", line 8, in <module>
|
||||||
ModuleNotFoundError: No module named 'hatchling'
|
ModuleNotFoundError: No module named 'hatchling'
|
||||||
---
|
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Running `uv sync` with `--all-extras` should also fail.
|
// Running `uv sync` with `--all-extras` should also fail.
|
||||||
|
|
@ -689,14 +687,13 @@ fn sync_build_isolation_extra() -> Result<()> {
|
||||||
Resolved [N] packages in [TIME]
|
Resolved [N] packages in [TIME]
|
||||||
error: Failed to prepare distributions
|
error: Failed to prepare distributions
|
||||||
Caused by: Failed to fetch wheel: source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz
|
Caused by: Failed to fetch wheel: source-distribution @ https://files.pythonhosted.org/packages/10/1f/57aa4cce1b1abf6b433106676e15f9fa2c92ed2bd4cf77c3b50a9e9ac773/source_distribution-0.0.1.tar.gz
|
||||||
Caused by: Build backend failed to build wheel through `build_wheel()` (exit status: 1)
|
Caused by: Build backend failed to build wheel through `build_wheel` (exit status: 1)
|
||||||
--- stdout:
|
|
||||||
|
|
||||||
--- stderr:
|
[stderr]
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<string>", line 8, in <module>
|
File "<string>", line 8, in <module>
|
||||||
ModuleNotFoundError: No module named 'hatchling'
|
ModuleNotFoundError: No module named 'hatchling'
|
||||||
---
|
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Install the build dependencies.
|
// Install the build dependencies.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue