mirror of https://github.com/astral-sh/uv
Suppress resolver output by default in `uv run` and `uv tool run` (#5580)
## Summary The idea here is that we hide all resolver output (the grayed out resolver messages, plus the list of environment modifications) by default in `uv run` and `uv tool run`. You can pass `--show-resolution` to re-enable them. Closes https://github.com/astral-sh/uv/issues/5458.
This commit is contained in:
parent
f7494f24cf
commit
d6c319a368
|
|
@ -1946,6 +1946,12 @@ pub struct RunArgs {
|
||||||
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
||||||
#[arg(long, short, env = "UV_PYTHON", verbatim_doc_comment)]
|
#[arg(long, short, env = "UV_PYTHON", verbatim_doc_comment)]
|
||||||
pub python: Option<String>,
|
pub python: Option<String>,
|
||||||
|
|
||||||
|
/// Whether to show resolver and installer output from any environment modifications.
|
||||||
|
///
|
||||||
|
/// By default, environment modifications are omitted, but enabled under `--verbose`.
|
||||||
|
#[arg(long, env = "UV_SHOW_RESOLUTION", value_parser = clap::builder::BoolishValueParser::new(), hide = true)]
|
||||||
|
pub show_resolution: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
@ -2307,6 +2313,12 @@ pub struct ToolRunArgs {
|
||||||
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
||||||
#[arg(long, short, env = "UV_PYTHON", verbatim_doc_comment)]
|
#[arg(long, short, env = "UV_PYTHON", verbatim_doc_comment)]
|
||||||
pub python: Option<String>,
|
pub python: Option<String>,
|
||||||
|
|
||||||
|
/// Whether to show resolver and installer output from any environment modifications.
|
||||||
|
///
|
||||||
|
/// By default, environment modifications are omitted, but enabled under `--verbose`.
|
||||||
|
#[arg(long, env = "UV_SHOW_RESOLUTION", value_parser = clap::builder::BoolishValueParser::new(), hide = true)]
|
||||||
|
pub show_resolution: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ use crate::settings::ResolverInstallerSettings;
|
||||||
pub(crate) async fn run(
|
pub(crate) async fn run(
|
||||||
command: ExternalCommand,
|
command: ExternalCommand,
|
||||||
requirements: Vec<RequirementsSource>,
|
requirements: Vec<RequirementsSource>,
|
||||||
|
show_resolution: bool,
|
||||||
locked: bool,
|
locked: bool,
|
||||||
frozen: bool,
|
frozen: bool,
|
||||||
package: Option<PackageName>,
|
package: Option<PackageName>,
|
||||||
|
|
@ -87,7 +88,7 @@ pub(crate) async fn run(
|
||||||
// Initialize any shared state.
|
// Initialize any shared state.
|
||||||
let state = SharedState::default();
|
let state = SharedState::default();
|
||||||
|
|
||||||
let reporter = PythonDownloadReporter::single(printer);
|
let reporter = PythonDownloadReporter::single(printer.filter(show_resolution));
|
||||||
|
|
||||||
// Determine whether the command to execute is a PEP 723 script.
|
// Determine whether the command to execute is a PEP 723 script.
|
||||||
let script_interpreter = if let RunCommand::Python(target, _) = &command {
|
let script_interpreter = if let RunCommand::Python(target, _) = &command {
|
||||||
|
|
@ -144,7 +145,7 @@ pub(crate) async fn run(
|
||||||
concurrency,
|
concurrency,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
printer,
|
printer.filter(show_resolution),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -202,7 +203,7 @@ pub(crate) async fn run(
|
||||||
connectivity,
|
connectivity,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
printer,
|
printer.filter(show_resolution),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -218,7 +219,7 @@ pub(crate) async fn run(
|
||||||
concurrency,
|
concurrency,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
printer,
|
printer.filter(show_resolution),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|
@ -247,7 +248,7 @@ pub(crate) async fn run(
|
||||||
concurrency,
|
concurrency,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
printer,
|
printer.filter(show_resolution),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -403,7 +404,7 @@ pub(crate) async fn run(
|
||||||
concurrency,
|
concurrency,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
printer,
|
printer.filter(show_resolution),
|
||||||
)
|
)
|
||||||
.await?,
|
.await?,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ use crate::commands::reporters::PythonDownloadReporter;
|
||||||
|
|
||||||
use crate::commands::project::resolve_names;
|
use crate::commands::project::resolve_names;
|
||||||
use crate::commands::{
|
use crate::commands::{
|
||||||
project, project::environment::CachedEnvironment, tool::common::matching_packages, tool_list,
|
project::environment::CachedEnvironment, tool::common::matching_packages, tool_list,
|
||||||
};
|
};
|
||||||
use crate::commands::{ExitStatus, SharedState};
|
use crate::commands::{ExitStatus, SharedState};
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
|
@ -59,6 +59,7 @@ pub(crate) async fn run(
|
||||||
command: Option<ExternalCommand>,
|
command: Option<ExternalCommand>,
|
||||||
from: Option<String>,
|
from: Option<String>,
|
||||||
with: &[RequirementsSource],
|
with: &[RequirementsSource],
|
||||||
|
show_resolution: bool,
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
settings: ResolverInstallerSettings,
|
settings: ResolverInstallerSettings,
|
||||||
invocation_source: ToolRunCommand,
|
invocation_source: ToolRunCommand,
|
||||||
|
|
@ -106,7 +107,7 @@ pub(crate) async fn run(
|
||||||
concurrency,
|
concurrency,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
printer,
|
printer.filter(show_resolution),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -315,7 +316,7 @@ async fn get_or_create_environment(
|
||||||
|
|
||||||
// Resolve the `from` requirement.
|
// Resolve the `from` requirement.
|
||||||
let from = {
|
let from = {
|
||||||
project::resolve_names(
|
resolve_names(
|
||||||
vec![RequirementsSpecification::parse_package(from)?],
|
vec![RequirementsSpecification::parse_package(from)?],
|
||||||
&interpreter,
|
&interpreter,
|
||||||
settings,
|
settings,
|
||||||
|
|
|
||||||
|
|
@ -650,6 +650,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
||||||
args.command,
|
args.command,
|
||||||
args.from,
|
args.from,
|
||||||
&requirements,
|
&requirements,
|
||||||
|
args.show_resolution || globals.verbose > 0,
|
||||||
args.python,
|
args.python,
|
||||||
args.settings,
|
args.settings,
|
||||||
invocation_source,
|
invocation_source,
|
||||||
|
|
@ -910,6 +911,7 @@ async fn run_project(
|
||||||
commands::run(
|
commands::run(
|
||||||
args.command,
|
args.command,
|
||||||
requirements,
|
requirements,
|
||||||
|
args.show_resolution || globals.verbose > 0,
|
||||||
args.locked,
|
args.locked,
|
||||||
args.frozen,
|
args.frozen,
|
||||||
args.package,
|
args.package,
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,16 @@ impl Printer {
|
||||||
Self::NoProgress => Stderr::Enabled,
|
Self::NoProgress => Stderr::Enabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Filter the [`Printer`], casting to [`Printer::Quiet`] if the condition is false.
|
||||||
|
#[must_use]
|
||||||
|
pub(crate) fn filter(self, condition: bool) -> Self {
|
||||||
|
if condition {
|
||||||
|
self
|
||||||
|
} else {
|
||||||
|
Self::Quiet
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ pub(crate) struct RunSettings {
|
||||||
pub(crate) command: ExternalCommand,
|
pub(crate) command: ExternalCommand,
|
||||||
pub(crate) with: Vec<String>,
|
pub(crate) with: Vec<String>,
|
||||||
pub(crate) with_requirements: Vec<PathBuf>,
|
pub(crate) with_requirements: Vec<PathBuf>,
|
||||||
|
pub(crate) show_resolution: bool,
|
||||||
pub(crate) package: Option<PackageName>,
|
pub(crate) package: Option<PackageName>,
|
||||||
pub(crate) no_project: bool,
|
pub(crate) no_project: bool,
|
||||||
pub(crate) python: Option<String>,
|
pub(crate) python: Option<String>,
|
||||||
|
|
@ -206,8 +207,6 @@ impl RunSettings {
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub(crate) fn resolve(args: RunArgs, filesystem: Option<FilesystemOptions>) -> Self {
|
pub(crate) fn resolve(args: RunArgs, filesystem: Option<FilesystemOptions>) -> Self {
|
||||||
let RunArgs {
|
let RunArgs {
|
||||||
locked,
|
|
||||||
frozen,
|
|
||||||
extra,
|
extra,
|
||||||
all_extras,
|
all_extras,
|
||||||
no_all_extras,
|
no_all_extras,
|
||||||
|
|
@ -216,6 +215,9 @@ impl RunSettings {
|
||||||
command,
|
command,
|
||||||
with,
|
with,
|
||||||
with_requirements,
|
with_requirements,
|
||||||
|
show_resolution,
|
||||||
|
locked,
|
||||||
|
frozen,
|
||||||
installer,
|
installer,
|
||||||
build,
|
build,
|
||||||
refresh,
|
refresh,
|
||||||
|
|
@ -238,6 +240,7 @@ impl RunSettings {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(Maybe::into_option)
|
.filter_map(Maybe::into_option)
|
||||||
.collect(),
|
.collect(),
|
||||||
|
show_resolution,
|
||||||
package,
|
package,
|
||||||
no_project,
|
no_project,
|
||||||
python,
|
python,
|
||||||
|
|
@ -258,6 +261,7 @@ pub(crate) struct ToolRunSettings {
|
||||||
pub(crate) from: Option<String>,
|
pub(crate) from: Option<String>,
|
||||||
pub(crate) with: Vec<String>,
|
pub(crate) with: Vec<String>,
|
||||||
pub(crate) with_requirements: Vec<PathBuf>,
|
pub(crate) with_requirements: Vec<PathBuf>,
|
||||||
|
pub(crate) show_resolution: bool,
|
||||||
pub(crate) python: Option<String>,
|
pub(crate) python: Option<String>,
|
||||||
pub(crate) refresh: Refresh,
|
pub(crate) refresh: Refresh,
|
||||||
pub(crate) settings: ResolverInstallerSettings,
|
pub(crate) settings: ResolverInstallerSettings,
|
||||||
|
|
@ -272,6 +276,7 @@ impl ToolRunSettings {
|
||||||
from,
|
from,
|
||||||
with,
|
with,
|
||||||
with_requirements,
|
with_requirements,
|
||||||
|
show_resolution,
|
||||||
installer,
|
installer,
|
||||||
build,
|
build,
|
||||||
refresh,
|
refresh,
|
||||||
|
|
@ -286,6 +291,7 @@ impl ToolRunSettings {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(Maybe::into_option)
|
.filter_map(Maybe::into_option)
|
||||||
.collect(),
|
.collect(),
|
||||||
|
show_resolution,
|
||||||
python,
|
python,
|
||||||
refresh: Refresh::from(refresh),
|
refresh: Refresh::from(refresh),
|
||||||
settings: ResolverInstallerSettings::combine(
|
settings: ResolverInstallerSettings::combine(
|
||||||
|
|
|
||||||
|
|
@ -481,7 +481,7 @@ impl TestContext {
|
||||||
/// Create a `uv run` command with options shared across scenarios.
|
/// Create a `uv run` command with options shared across scenarios.
|
||||||
pub fn run(&self) -> Command {
|
pub fn run(&self) -> Command {
|
||||||
let mut command = Command::new(get_bin());
|
let mut command = Command::new(get_bin());
|
||||||
command.arg("run");
|
command.arg("run").env("UV_SHOW_RESOLUTION", "1");
|
||||||
self.add_shared_args(&mut command);
|
self.add_shared_args(&mut command);
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
@ -489,13 +489,16 @@ impl TestContext {
|
||||||
/// Create a `uv tool run` command with options shared across scenarios.
|
/// Create a `uv tool run` command with options shared across scenarios.
|
||||||
pub fn tool_run(&self) -> Command {
|
pub fn tool_run(&self) -> Command {
|
||||||
let mut command = Command::new(get_bin());
|
let mut command = Command::new(get_bin());
|
||||||
command.arg("tool").arg("run");
|
command
|
||||||
|
.arg("tool")
|
||||||
|
.arg("run")
|
||||||
|
.env("UV_SHOW_RESOLUTION", "1");
|
||||||
self.add_shared_args(&mut command);
|
self.add_shared_args(&mut command);
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `uv tool install` command with options shared across scenarios.
|
/// Create a `uv tool install` command with options shared across scenarios.
|
||||||
pub fn tool_install(&self) -> std::process::Command {
|
pub fn tool_install(&self) -> Command {
|
||||||
let mut command = self.tool_install_without_exclude_newer();
|
let mut command = self.tool_install_without_exclude_newer();
|
||||||
command.arg("--exclude-newer").arg(EXCLUDE_NEWER);
|
command.arg("--exclude-newer").arg(EXCLUDE_NEWER);
|
||||||
command
|
command
|
||||||
|
|
@ -507,16 +510,16 @@ impl TestContext {
|
||||||
/// it can result in tests failing when the index state changes. Therefore,
|
/// it can result in tests failing when the index state changes. Therefore,
|
||||||
/// if you use this, there should be some other kind of mitigation in place.
|
/// if you use this, there should be some other kind of mitigation in place.
|
||||||
/// For example, pinning package versions.
|
/// For example, pinning package versions.
|
||||||
pub fn tool_install_without_exclude_newer(&self) -> std::process::Command {
|
pub fn tool_install_without_exclude_newer(&self) -> Command {
|
||||||
let mut command = std::process::Command::new(get_bin());
|
let mut command = Command::new(get_bin());
|
||||||
command.arg("tool").arg("install");
|
command.arg("tool").arg("install");
|
||||||
self.add_shared_args(&mut command);
|
self.add_shared_args(&mut command);
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `uv tool list` command with options shared across scenarios.
|
/// Create a `uv tool list` command with options shared across scenarios.
|
||||||
pub fn tool_list(&self) -> std::process::Command {
|
pub fn tool_list(&self) -> Command {
|
||||||
let mut command = std::process::Command::new(get_bin());
|
let mut command = Command::new(get_bin());
|
||||||
command.arg("tool").arg("list");
|
command.arg("tool").arg("list");
|
||||||
self.add_shared_args(&mut command);
|
self.add_shared_args(&mut command);
|
||||||
command
|
command
|
||||||
|
|
@ -531,8 +534,8 @@ impl TestContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `uv tool uninstall` command with options shared across scenarios.
|
/// Create a `uv tool uninstall` command with options shared across scenarios.
|
||||||
pub fn tool_uninstall(&self) -> std::process::Command {
|
pub fn tool_uninstall(&self) -> Command {
|
||||||
let mut command = std::process::Command::new(get_bin());
|
let mut command = Command::new(get_bin());
|
||||||
command.arg("tool").arg("uninstall");
|
command.arg("tool").arg("uninstall");
|
||||||
self.add_shared_args(&mut command);
|
self.add_shared_args(&mut command);
|
||||||
command
|
command
|
||||||
|
|
|
||||||
|
|
@ -882,3 +882,36 @@ fn run_from_directory() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// By default, omit resolver and installer output.
|
||||||
|
#[test]
|
||||||
|
fn run_without_output() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(indoc! { r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "1.0.0"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
dependencies = ["anyio", "sniffio==1.3.1"]
|
||||||
|
"#
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let test_script = context.temp_dir.child("main.py");
|
||||||
|
test_script.write_str(indoc! { r"
|
||||||
|
import sniffio
|
||||||
|
"
|
||||||
|
})?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.run().env_remove("UV_SHOW_RESOLUTION").arg("--with").arg("iniconfig").arg("main.py"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv run` is experimental and may change without warning
|
||||||
|
"###);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -811,3 +811,27 @@ fn tool_run_list_installed() {
|
||||||
warning: `uv tool run` is experimental and may change without warning
|
warning: `uv tool run` is experimental and may change without warning
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// By default, omit resolver and installer output.
|
||||||
|
#[test]
|
||||||
|
fn tool_run_without_output() {
|
||||||
|
let context = TestContext::new("3.12").with_filtered_counts();
|
||||||
|
let tool_dir = context.temp_dir.child("tools");
|
||||||
|
let bin_dir = context.temp_dir.child("bin");
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.tool_run()
|
||||||
|
.env_remove("UV_SHOW_RESOLUTION")
|
||||||
|
.arg("--")
|
||||||
|
.arg("pytest")
|
||||||
|
.arg("--version")
|
||||||
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
|
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
pytest 8.1.1
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv tool run` is experimental and may change without warning
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue