Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/uv-distribution/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ uv-configuration = { workspace = true }
uv-distribution-filename = { workspace = true }
uv-distribution-types = { workspace = true }
uv-extract = { workspace = true }
uv-flags = { workspace = true }
uv-fs = { workspace = true, features = ["tokio"] }
uv-git = { workspace = true }
uv-git-types = { workspace = true }
Expand Down
12 changes: 10 additions & 2 deletions crates/uv-distribution/src/source/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2474,7 +2474,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
} else {
BuildKind::Wheel
},
BuildOutput::Debug,
if uv_flags::contains(uv_flags::EnvironmentFlags::HIDE_BUILD_OUTPUT) {
BuildOutput::Quiet
} else {
BuildOutput::Debug
},
self.build_stack.cloned().unwrap_or_default(),
)
.await
Expand Down Expand Up @@ -2575,7 +2579,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
source.as_dist(),
source_strategy,
build_kind,
BuildOutput::Debug,
if uv_flags::contains(uv_flags::EnvironmentFlags::HIDE_BUILD_OUTPUT) {
BuildOutput::Quiet
} else {
BuildOutput::Debug
},
self.build_stack.cloned().unwrap_or_default(),
)
.await
Expand Down
1 change: 1 addition & 0 deletions crates/uv-flags/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct EnvironmentFlags: u32 {
const SKIP_WHEEL_FILENAME_CHECK = 1 << 0;
const HIDE_BUILD_OUTPUT = 1 << 1;
}
}

Expand Down
5 changes: 5 additions & 0 deletions crates/uv-settings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ pub struct Concurrency {
#[derive(Debug, Clone)]
pub struct EnvironmentOptions {
pub skip_wheel_filename_check: Option<bool>,
pub hide_build_output: Option<bool>,
pub python_install_bin: Option<bool>,
pub python_install_registry: Option<bool>,
pub install_mirrors: PythonInstallMirrors,
Expand Down Expand Up @@ -613,6 +614,7 @@ impl EnvironmentOptions {
skip_wheel_filename_check: parse_boolish_environment_variable(
EnvVars::UV_SKIP_WHEEL_FILENAME_CHECK,
)?,
hide_build_output: parse_boolish_environment_variable(EnvVars::UV_HIDE_BUILD_OUTPUT)?,
python_install_bin: parse_boolish_environment_variable(EnvVars::UV_PYTHON_INSTALL_BIN)?,
python_install_registry: parse_boolish_environment_variable(
EnvVars::UV_PYTHON_INSTALL_REGISTRY,
Expand Down Expand Up @@ -775,6 +777,9 @@ impl From<&EnvironmentOptions> for EnvironmentFlags {
if options.skip_wheel_filename_check == Some(true) {
flags.insert(Self::SKIP_WHEEL_FILENAME_CHECK);
}
if options.hide_build_output == Some(true) {
flags.insert(Self::HIDE_BUILD_OUTPUT);
}
flags
}
}
5 changes: 5 additions & 0 deletions crates/uv-static/src/env_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1215,4 +1215,9 @@ impl EnvVars {
/// around invalid artifacts in rare cases.
#[attr_added_in("0.8.23")]
pub const UV_SKIP_WHEEL_FILENAME_CHECK: &'static str = "UV_SKIP_WHEEL_FILENAME_CHECK";

/// Suppress output from the build backend when building source distributions, even in the event
/// of build failures.
#[attr_added_in("0.9.14")]
pub const UV_HIDE_BUILD_OUTPUT: &'static str = "UV_HIDE_BUILD_OUTPUT";
}
2 changes: 1 addition & 1 deletion crates/uv/src/commands/build_frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ async fn build_package(

let build_output = match printer {
Printer::Default | Printer::NoProgress | Printer::Verbose => {
if build_logs {
if build_logs && !uv_flags::contains(uv_flags::EnvironmentFlags::HIDE_BUILD_OUTPUT) {
BuildOutput::Stderr
} else {
BuildOutput::Quiet
Expand Down
96 changes: 96 additions & 0 deletions crates/uv/tests/it/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,102 @@ fn build_no_build_logs() -> Result<()> {
Ok(())
}

/// Test that `UV_HIDE_BUILD_OUTPUT` suppresses build output.
#[test]
fn build_hide_build_output_env_var() -> Result<()> {
let context = TestContext::new("3.12");

let project = context.temp_dir.child("project");

let pyproject_toml = project.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["anyio==3.7.0"]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"#,
)?;

project
.child("src")
.child("project")
.child("__init__.py")
.touch()?;
project.child("README").touch()?;

uv_snapshot!(&context.filters(), context.build().arg("project").env(EnvVars::UV_HIDE_BUILD_OUTPUT, "1"), @r###"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Building source distribution...
Building wheel from source distribution...
Successfully built project/dist/project-0.1.0.tar.gz
Successfully built project/dist/project-0.1.0-py3-none-any.whl
"###);

Ok(())
}

/// Test that `UV_HIDE_BUILD_OUTPUT` hides build output even on failure.
#[test]
fn build_hide_build_output_on_failure() -> Result<()> {
let context = TestContext::new("3.12");
let filters = context
.filters()
.into_iter()
.chain([(r"\\\.", "")])
.collect::<Vec<_>>();

let project = context.temp_dir.child("project");

let pyproject_toml = project.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
"#,
)?;

// Create a `setup.py` that prints an environment variable before failing.
project.child("setup.py").write_str(indoc! {r#"
import os
import sys
print("FOO=" + os.environ.get("FOO", "not-set"), file=sys.stderr)
sys.stderr.flush()
raise Exception("Build failed intentionally!")
"#})?;

// With `UV_HIDE_BUILD_OUTPUT`, the output is hidden even on failure.
uv_snapshot!(&filters, context.build().arg("project").env(EnvVars::UV_HIDE_BUILD_OUTPUT, "1").env("FOO", "bar"), @r###"
success: false
exit_code: 2
----- stdout -----

----- stderr -----
Building source distribution...
× Failed to build `[TEMP_DIR]/project`
├─▶ The build backend returned an error
╰─▶ Call to `setuptools.build_meta.build_sdist` failed (exit status: 1)
hint: This usually indicates a problem with the package or the build environment.
"###);

Ok(())
}

#[test]
fn build_tool_uv_sources() -> Result<()> {
let context = TestContext::new("3.12");
Expand Down
6 changes: 6 additions & 0 deletions docs/reference/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ Equivalent to the `--token` argument for self update. A GitHub token for authent

Enables fetching files stored in Git LFS when installing a package from a Git repository.

### `UV_HIDE_BUILD_OUTPUT`
<small class="added-in">added in `0.9.14`</small>

Suppress output from the build backend when building source distributions, even in the event
of build failures.

### `UV_HTTP_RETRIES`
<small class="added-in">added in `0.7.21`</small>

Expand Down
Loading