From b6ed3d2a882b46d2efd7c05fab08005f0d31f2d4 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 1 Oct 2024 12:36:32 -0400 Subject: [PATCH] Improve error message copy for failed builds --- crates/uv-build-frontend/src/error.rs | 18 ++++++++++-------- crates/uv-build-frontend/src/lib.rs | 22 ++++++++-------------- crates/uv/tests/build.rs | 10 +++++----- crates/uv/tests/edit.rs | 2 +- crates/uv/tests/pip_compile.rs | 2 +- crates/uv/tests/pip_install.rs | 16 +++++++--------- crates/uv/tests/pip_sync.rs | 2 +- crates/uv/tests/sync.rs | 6 +++--- 8 files changed, 36 insertions(+), 42 deletions(-) diff --git a/crates/uv-build-frontend/src/error.rs b/crates/uv-build-frontend/src/error.rs index 3b37a2b5d989..3ccbf9871507 100644 --- a/crates/uv-build-frontend/src/error.rs +++ b/crates/uv-build-frontend/src/error.rs @@ -63,13 +63,15 @@ pub enum Error { InvalidPyprojectTomlSchema(#[from] toml_edit::de::Error), #[error("Editable installs with setup.py legacy builds are unsupported, please specify a build backend in pyproject.toml")] EditableSetupPy, + #[error("Failed to resolve requirements from {0}")] + RequirementsResolve(&'static str, #[source] anyhow::Error), #[error("Failed to install requirements from {0}")] RequirementsInstall(&'static str, #[source] anyhow::Error), #[error("Failed to create temporary virtualenv")] Virtualenv(#[from] uv_virtualenv::Error), #[error("Failed to run `{0}`")] CommandFailed(PathBuf, #[source] io::Error), - #[error("{message} with {exit_code}\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")] + #[error("{message} ({exit_code})\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")] BuildBackendOutput { message: String, exit_code: ExitStatus, @@ -77,7 +79,7 @@ pub enum Error { stderr: String, }, /// Nudge the user towards installing the missing dev library - #[error("{message} with {exit_code}\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")] + #[error("{message} ({exit_code})\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")] MissingHeaderOutput { message: String, exit_code: ExitStatus, @@ -86,12 +88,12 @@ pub enum Error { #[source] missing_header_cause: MissingHeaderCause, }, - #[error("{message} with {exit_code}")] + #[error("{message} ({exit_code})")] BuildBackend { message: String, exit_code: ExitStatus, }, - #[error("{message} with {exit_code}")] + #[error("{message} ({exit_code})")] MissingHeader { message: String, exit_code: ExitStatus, @@ -327,7 +329,7 @@ mod test { // Unix uses exit status, Windows uses exit code. let formatted = err.to_string().replace("exit status: ", "exit code: "); insta::assert_snapshot!(formatted, @r###" - Failed building wheel through setup.py with exit code: 0 + Failed building wheel through setup.py (exit code: 0) --- stdout: running bdist_wheel running build @@ -382,7 +384,7 @@ mod test { // Unix uses exit status, Windows uses exit code. let formatted = err.to_string().replace("exit status: ", "exit code: "); insta::assert_snapshot!(formatted, @r###" - Failed building wheel through setup.py with exit code: 0 + Failed building wheel through setup.py (exit code: 0) --- stdout: --- stderr: @@ -430,7 +432,7 @@ mod test { // Unix uses exit status, Windows uses exit code. let formatted = err.to_string().replace("exit status: ", "exit code: "); insta::assert_snapshot!(formatted, @r###" - Failed building wheel through setup.py with exit code: 0 + Failed building wheel through setup.py (exit code: 0) --- stdout: --- stderr: @@ -476,7 +478,7 @@ mod test { // Unix uses exit status, Windows uses exit code. let formatted = err.to_string().replace("exit status: ", "exit code: "); insta::assert_snapshot!(formatted, @r###" - Failed building wheel through setup.py with exit code: 0 + Failed building wheel through setup.py (exit code: 0) --- stdout: --- stderr: diff --git a/crates/uv-build-frontend/src/lib.rs b/crates/uv-build-frontend/src/lib.rs index 7e61d9e40ff1..862be6a0ffb8 100644 --- a/crates/uv-build-frontend/src/lib.rs +++ b/crates/uv-build-frontend/src/lib.rs @@ -310,9 +310,7 @@ impl SourceBuild { build_context .install(&resolved_requirements, &venv) .await - .map_err(|err| { - Error::RequirementsInstall("`build-system.requires` (install)", err) - })?; + .map_err(|err| Error::RequirementsInstall("`build-system.requires`", err))?; } else { debug!("Proceeding without build isolation"); } @@ -407,9 +405,7 @@ impl SourceBuild { let resolved_requirements = build_context .resolve(&default_backend.requirements) .await - .map_err(|err| { - Error::RequirementsInstall("`setup.py` build (resolve)", err) - })?; + .map_err(|err| Error::RequirementsResolve("`setup.py` build", err))?; *resolution = Some(resolved_requirements.clone()); resolved_requirements } @@ -417,9 +413,7 @@ impl SourceBuild { build_context .resolve(&pep517_backend.requirements) .await - .map_err(|err| { - Error::RequirementsInstall("`build-system.requires` (resolve)", err) - })? + .map_err(|err| Error::RequirementsResolve("`build-system.requires`", err))? }, ) } @@ -808,7 +802,7 @@ async fn create_pep517_build_environment( .await?; if !output.status.success() { return Err(Error::from_command_output( - format!("Build backend failed to determine extra requires with `build_{build_kind}()`"), + format!("Build backend failed to determine requirements with `build_{build_kind}()`"), &output, level, package_name, @@ -821,7 +815,7 @@ async fn create_pep517_build_environment( let contents = fs_err::read(&outfile).map_err(|err| { Error::from_command_output( format!( - "Build backend failed to read extra requires from `get_requires_for_build_{build_kind}`: {err}" + "Build backend failed to read requirements from `get_requires_for_build_{build_kind}`: {err}" ), &output, level, @@ -835,7 +829,7 @@ async fn create_pep517_build_environment( let extra_requires: Vec> = serde_json::from_slice::>>(&contents).map_err(|err| { Error::from_command_output( format!( - "Build backend failed to return extra requires with `get_requires_for_build_{build_kind}`: {err}" + "Build backend failed to return requirements from `get_requires_for_build_{build_kind}`: {err}" ), &output, level, @@ -864,12 +858,12 @@ async fn create_pep517_build_environment( let resolution = build_context .resolve(&requirements) .await - .map_err(|err| Error::RequirementsInstall("`build-system.requires` (resolve)", err))?; + .map_err(|err| Error::RequirementsResolve("`build-system.requires`", err))?; build_context .install(&resolution, venv) .await - .map_err(|err| Error::RequirementsInstall("`build-system.requires` (install)", err))?; + .map_err(|err| Error::RequirementsInstall("`build-system.requires`", err))?; } Ok(()) diff --git a/crates/uv/tests/build.rs b/crates/uv/tests/build.rs index bfaf2ce35dac..9099f3fcc0ae 100644 --- a/crates/uv/tests/build.rs +++ b/crates/uv/tests/build.rs @@ -888,7 +888,7 @@ fn fail() -> Result<()> { File "", line 2 from setuptools import setup IndentationError: unexpected indent - error: Build backend failed to determine extra requires with `build_sdist()` with exit status: 1 + error: Build backend failed to determine requirements with `build_sdist()` (exit status: 1) "###); Ok(()) @@ -1328,7 +1328,7 @@ 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 extra requires with `build_sdist()` with exit status: 1 + [PKG] error: 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 "###); @@ -1397,7 +1397,7 @@ fn build_constraints() -> Result<()> { ----- stderr ----- Building source distribution... - error: Failed to install requirements from `build-system.requires` (resolve) + 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. "###); @@ -1551,7 +1551,7 @@ fn sha() -> Result<()> { ----- stderr ----- Building source distribution... - error: Failed to install requirements from `build-system.requires` (install) + error: Failed to install requirements from `build-system.requires` Caused by: Failed to prepare distributions Caused by: Failed to fetch wheel: setuptools==68.2.2 Caused by: Hash mismatch for `setuptools==68.2.2` @@ -1585,7 +1585,7 @@ fn sha() -> Result<()> { ----- stderr ----- Building source distribution... - error: Failed to install requirements from `build-system.requires` (resolve) + 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` "###); diff --git a/crates/uv/tests/edit.rs b/crates/uv/tests/edit.rs index 417d824f2e91..f8132ca4d384 100644 --- a/crates/uv/tests/edit.rs +++ b/crates/uv/tests/edit.rs @@ -4594,7 +4594,7 @@ fn fail_to_add_revert_project() -> Result<()> { Resolved 2 packages in [TIME] error: Failed to prepare distributions Caused by: Failed to fetch wheel: pytorch==1.0.2 - Caused by: Build backend failed to build wheel through `build_wheel()` with exit status: 1 + Caused by: Build backend failed to build wheel through `build_wheel()` (exit status: 1) --- stdout: --- stderr: diff --git a/crates/uv/tests/pip_compile.rs b/crates/uv/tests/pip_compile.rs index bee02f8d6f84..2638aa3dd62d 100644 --- a/crates/uv/tests/pip_compile.rs +++ b/crates/uv/tests/pip_compile.rs @@ -11782,7 +11782,7 @@ fn incompatible_build_constraint() -> Result<()> { ----- stderr ----- × Failed to download and build `requests==1.2.0` - ├─▶ Failed to install requirements from `setup.py` build (resolve) + ├─▶ Failed to resolve requirements from `setup.py` build ├─▶ No solution found when resolving: `setuptools>=40.8.0` ╰─▶ Because you require setuptools>=40.8.0 and setuptools==1, we can conclude that your requirements are unsatisfiable. "### diff --git a/crates/uv/tests/pip_install.rs b/crates/uv/tests/pip_install.rs index 9d74853a8f48..e8a889512599 100644 --- a/crates/uv/tests/pip_install.rs +++ b/crates/uv/tests/pip_install.rs @@ -227,11 +227,9 @@ dependencies = ["flask==1.0.x"] let requirements_txt = context.temp_dir.child("requirements.txt"); requirements_txt.write_str("./path_dep")?; - let filters = [("exit status", "exit code")] - .into_iter() + let filters = std::iter::once((r"exit code: 1", "exit status: 1")) .chain(context.filters()) .collect::>(); - uv_snapshot!(filters, context.pip_install() .arg("-r") .arg("requirements.txt"), @r###" @@ -241,7 +239,7 @@ dependencies = ["flask==1.0.x"] ----- stderr ----- error: Failed to build: `project @ file://[TEMP_DIR]/path_dep` - Caused by: Build backend failed to determine extra requires with `build_wheel()` with exit code: 1 + Caused by: Build backend failed to determine requirements with `build_wheel()` (exit status: 1) --- stdout: configuration error: `project.dependencies[0]` must be pep508 DESCRIPTION: @@ -3820,7 +3818,7 @@ fn no_build_isolation() -> Result<()> { ----- stderr ----- 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` with exit status: 1 + Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1) --- stdout: --- stderr: @@ -3890,7 +3888,7 @@ fn respect_no_build_isolation_env_var() -> Result<()> { ----- stderr ----- 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` with exit status: 1 + Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1) --- stdout: --- stderr: @@ -6759,7 +6757,7 @@ fn incompatible_build_constraint() -> Result<()> { ----- stderr ----- × Failed to download and build `requests==1.2.0` - ├─▶ Failed to install requirements from `setup.py` build (resolve) + ├─▶ Failed to resolve requirements from `setup.py` build ├─▶ No solution found when resolving: `setuptools>=40.8.0` ╰─▶ Because you require setuptools>=40.8.0 and setuptools==1, we can conclude that your requirements are unsatisfiable. "### @@ -6835,7 +6833,7 @@ fn install_build_isolation_package() -> Result<()> { ----- stderr ----- 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` with exit status: 1 + Caused by: Build backend failed to determine metadata through `prepare_metadata_for_build_wheel` (exit status: 1) --- stdout: --- stderr: @@ -7096,7 +7094,7 @@ fn sklearn() { ----- stderr ----- × Failed to download and build `sklearn==0.0.post12` - ╰─▶ Build backend failed to determine extra requires with `build_wheel()` with exit status: 1 + ╰─▶ Build backend failed to determine requirements with `build_wheel()` (exit status: 1) --- stdout: --- stderr: diff --git a/crates/uv/tests/pip_sync.rs b/crates/uv/tests/pip_sync.rs index fa0c02d048b6..c07f583f710a 100644 --- a/crates/uv/tests/pip_sync.rs +++ b/crates/uv/tests/pip_sync.rs @@ -5499,7 +5499,7 @@ fn incompatible_build_constraint() -> Result<()> { Resolved 1 package in [TIME] error: Failed to prepare distributions Caused by: Failed to fetch wheel: requests==1.2.0 - Caused by: Failed to install requirements from `setup.py` build (resolve) + Caused by: Failed to resolve requirements from `setup.py` build Caused by: No solution found when resolving: `setuptools>=40.8.0` Caused by: Because you require setuptools>=40.8.0 and setuptools==1, we can conclude that your requirements are unsatisfiable. "### diff --git a/crates/uv/tests/sync.rs b/crates/uv/tests/sync.rs index 33d501707b61..d5076da02911 100644 --- a/crates/uv/tests/sync.rs +++ b/crates/uv/tests/sync.rs @@ -577,7 +577,7 @@ fn sync_build_isolation_package() -> Result<()> { Resolved 2 packages in [TIME] 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: Build backend failed to build wheel through `build_wheel()` with exit status: 1 + Caused by: Build backend failed to build wheel through `build_wheel()` (exit status: 1) --- stdout: --- stderr: @@ -669,7 +669,7 @@ fn sync_build_isolation_extra() -> Result<()> { Resolved [N] packages in [TIME] 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: Build backend failed to build wheel through `build_wheel()` with exit status: 1 + Caused by: Build backend failed to build wheel through `build_wheel()` (exit status: 1) --- stdout: --- stderr: @@ -689,7 +689,7 @@ fn sync_build_isolation_extra() -> Result<()> { Resolved [N] packages in [TIME] 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: Build backend failed to build wheel through `build_wheel()` with exit status: 1 + Caused by: Build backend failed to build wheel through `build_wheel()` (exit status: 1) --- stdout: --- stderr: