diff --git a/crates/uv/src/commands/cache_clean.rs b/crates/uv/src/commands/cache_clean.rs index 99f5975fc..4fed9cab8 100644 --- a/crates/uv/src/commands/cache_clean.rs +++ b/crates/uv/src/commands/cache_clean.rs @@ -14,11 +14,11 @@ use crate::printer::Printer; pub(crate) fn cache_clean( packages: &[PackageName], cache: &Cache, - mut printer: Printer, + printer: Printer, ) -> Result { if !cache.root().exists() { writeln!( - printer, + printer.stderr(), "No cache found at: {}", cache.root().simplified_display().cyan() )?; @@ -27,7 +27,7 @@ pub(crate) fn cache_clean( if packages.is_empty() { writeln!( - printer, + printer.stderr(), "Clearing cache at: {}", cache.root().simplified_display().cyan() )?; @@ -42,19 +42,19 @@ pub(crate) fn cache_clean( // Write a summary of the number of files and directories removed. match (summary.num_files, summary.num_dirs) { (0, 0) => { - write!(printer, "No cache entries found")?; + write!(printer.stderr(), "No cache entries found")?; } (0, 1) => { - write!(printer, "Removed 1 directory")?; + write!(printer.stderr(), "Removed 1 directory")?; } (0, num_dirs_removed) => { - write!(printer, "Removed {num_dirs_removed} directories")?; + write!(printer.stderr(), "Removed {num_dirs_removed} directories")?; } (1, _) => { - write!(printer, "Removed 1 file")?; + write!(printer.stderr(), "Removed 1 file")?; } (num_files_removed, _) => { - write!(printer, "Removed {num_files_removed} files")?; + write!(printer.stderr(), "Removed {num_files_removed} files")?; } } @@ -66,10 +66,10 @@ pub(crate) fn cache_clean( let (bytes, unit) = human_readable_bytes(summary.total_bytes); format!("{bytes:.1}{unit}") }; - write!(printer, " ({})", bytes.green())?; + write!(printer.stderr(), " ({})", bytes.green())?; } - writeln!(printer)?; + writeln!(printer.stderr())?; } else { for package in packages { let summary = cache.remove(package)?; @@ -77,24 +77,32 @@ pub(crate) fn cache_clean( // Write a summary of the number of files and directories removed. match (summary.num_files, summary.num_dirs) { (0, 0) => { - write!(printer, "No cache entries found for {}", package.cyan())?; + write!( + printer.stderr(), + "No cache entries found for {}", + package.cyan() + )?; } (0, 1) => { - write!(printer, "Removed 1 directory for {}", package.cyan())?; + write!( + printer.stderr(), + "Removed 1 directory for {}", + package.cyan() + )?; } (0, num_dirs_removed) => { write!( - printer, + printer.stderr(), "Removed {num_dirs_removed} directories for {}", package.cyan() )?; } (1, _) => { - write!(printer, "Removed 1 file for {}", package.cyan())?; + write!(printer.stderr(), "Removed 1 file for {}", package.cyan())?; } (num_files_removed, _) => { write!( - printer, + printer.stderr(), "Removed {num_files_removed} files for {}", package.cyan() )?; @@ -109,10 +117,10 @@ pub(crate) fn cache_clean( let (bytes, unit) = human_readable_bytes(summary.total_bytes); format!("{bytes:.1}{unit}") }; - write!(printer, " ({})", bytes.green())?; + write!(printer.stderr(), " ({})", bytes.green())?; } - writeln!(printer)?; + writeln!(printer.stderr())?; } } diff --git a/crates/uv/src/commands/mod.rs b/crates/uv/src/commands/mod.rs index 9ade51a78..3330cc7e6 100644 --- a/crates/uv/src/commands/mod.rs +++ b/crates/uv/src/commands/mod.rs @@ -114,7 +114,7 @@ pub(crate) enum ListFormat { pub(super) async fn compile_bytecode( venv: &PythonEnvironment, cache: &Cache, - mut printer: Printer, + printer: Printer, ) -> anyhow::Result<()> { let start = std::time::Instant::now(); let files = compile_tree(venv.site_packages(), venv.python_executable(), cache.root()) @@ -127,7 +127,7 @@ pub(super) async fn compile_bytecode( })?; let s = if files == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Bytecode compiled {} in {}", diff --git a/crates/uv/src/commands/pip_compile.rs b/crates/uv/src/commands/pip_compile.rs index cfe777da0..5ba3b6db6 100644 --- a/crates/uv/src/commands/pip_compile.rs +++ b/crates/uv/src/commands/pip_compile.rs @@ -67,7 +67,7 @@ pub(crate) async fn pip_compile( annotation_style: AnnotationStyle, quiet: bool, cache: Cache, - mut printer: Printer, + printer: Printer, ) -> Result { let start = std::time::Instant::now(); @@ -271,7 +271,7 @@ pub(crate) async fn pip_compile( let s = if editables.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Built {} in {}", @@ -326,7 +326,7 @@ pub(crate) async fn pip_compile( let s = if resolution.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Resolved {} in {}", @@ -339,7 +339,7 @@ pub(crate) async fn pip_compile( // Notify the user of any diagnostics. for diagnostic in resolution.diagnostics() { writeln!( - printer, + printer.stderr(), "{}{} {}", "warning".yellow().bold(), ":".bold(), diff --git a/crates/uv/src/commands/pip_freeze.rs b/crates/uv/src/commands/pip_freeze.rs index 1c4f6848c..8e3e97353 100644 --- a/crates/uv/src/commands/pip_freeze.rs +++ b/crates/uv/src/commands/pip_freeze.rs @@ -1,6 +1,5 @@ use std::fmt::Write; -use anstream::println; use anyhow::Result; use itertools::Itertools; use owo_colors::OwoColorize; @@ -22,7 +21,7 @@ pub(crate) fn pip_freeze( python: Option<&str>, system: bool, cache: &Cache, - mut printer: Printer, + printer: Printer, ) -> Result { // Detect the current Python interpreter. let platform = Platform::current()?; @@ -54,13 +53,13 @@ pub(crate) fn pip_freeze( { match dist { InstalledDist::Registry(dist) => { - println!("{}=={}", dist.name().bold(), dist.version); + writeln!(printer.stdout(), "{}=={}", dist.name().bold(), dist.version)?; } InstalledDist::Url(dist) => { if dist.editable { - println!("-e {}", dist.url); + writeln!(printer.stdout(), "-e {}", dist.url)?; } else { - println!("{} @ {}", dist.name().bold(), dist.url); + writeln!(printer.stdout(), "{} @ {}", dist.name().bold(), dist.url)?; } } } @@ -70,7 +69,7 @@ pub(crate) fn pip_freeze( if strict { for diagnostic in site_packages.diagnostics()? { writeln!( - printer, + printer.stderr(), "{}{} {}", "warning".yellow().bold(), ":".bold(), diff --git a/crates/uv/src/commands/pip_install.rs b/crates/uv/src/commands/pip_install.rs index 7230be949..53b2c57ee 100644 --- a/crates/uv/src/commands/pip_install.rs +++ b/crates/uv/src/commands/pip_install.rs @@ -66,7 +66,7 @@ pub(crate) async fn pip_install( python: Option, system: bool, cache: Cache, - mut printer: Printer, + printer: Printer, ) -> Result { let start = std::time::Instant::now(); @@ -152,7 +152,7 @@ pub(crate) async fn pip_install( let num_requirements = requirements.len() + editables.len(); let s = if num_requirements == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Audited {} in {}", @@ -366,7 +366,7 @@ async fn build_editables( tags: &Tags, client: &RegistryClient, build_dispatch: &BuildDispatch<'_>, - mut printer: Printer, + printer: Printer, ) -> Result, Error> { let start = std::time::Instant::now(); @@ -409,7 +409,7 @@ async fn build_editables( let s = if editables.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Built {} in {}", @@ -441,7 +441,7 @@ async fn resolve( index: &InMemoryIndex, build_dispatch: &BuildDispatch<'_>, options: Options, - mut printer: Printer, + printer: Printer, ) -> Result { let start = std::time::Instant::now(); @@ -504,7 +504,7 @@ async fn resolve( let s = if resolution.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Resolved {} in {}", @@ -534,7 +534,7 @@ async fn install( build_dispatch: &BuildDispatch<'_>, cache: &Cache, venv: &PythonEnvironment, - mut printer: Printer, + printer: Printer, ) -> Result<(), Error> { let start = std::time::Instant::now(); @@ -570,7 +570,7 @@ async fn install( if remote.is_empty() && local.is_empty() && reinstalls.is_empty() { let s = if resolution.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Audited {} in {}", @@ -610,7 +610,7 @@ async fn install( let s = if wheels.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Downloaded {} in {}", @@ -649,7 +649,7 @@ async fn install( let s = if wheels.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Installed {} in {}", @@ -685,7 +685,7 @@ async fn install( match event.kind { ChangeEventKind::Added => { writeln!( - printer, + printer.stderr(), " {} {}{}", "+".green(), event.dist.name().as_ref().bold(), @@ -694,7 +694,7 @@ async fn install( } ChangeEventKind::Removed => { writeln!( - printer, + printer.stderr(), " {} {}{}", "-".red(), event.dist.name().as_ref().bold(), @@ -714,7 +714,7 @@ async fn install( None | Some(Yanked::Bool(false)) => {} Some(Yanked::Bool(true)) => { writeln!( - printer, + printer.stderr(), "{}{} {dist} is yanked.", "warning".yellow().bold(), ":".bold(), @@ -722,7 +722,7 @@ async fn install( } Some(Yanked::Reason(reason)) => { writeln!( - printer, + printer.stderr(), "{}{} {dist} is yanked (reason: \"{reason}\").", "warning".yellow().bold(), ":".bold(), @@ -738,7 +738,7 @@ async fn install( fn validate( resolution: &Resolution, venv: &PythonEnvironment, - mut printer: Printer, + printer: Printer, ) -> Result<(), Error> { let site_packages = SitePackages::from_executable(venv)?; let diagnostics = site_packages.diagnostics()?; @@ -749,7 +749,7 @@ fn validate( .any(|package| diagnostic.includes(package)) { writeln!( - printer, + printer.stderr(), "{}{} {}", "warning".yellow().bold(), ":".bold(), diff --git a/crates/uv/src/commands/pip_list.rs b/crates/uv/src/commands/pip_list.rs index a11ec359b..534689c48 100644 --- a/crates/uv/src/commands/pip_list.rs +++ b/crates/uv/src/commands/pip_list.rs @@ -1,7 +1,6 @@ use std::cmp::max; use std::fmt::Write; -use anstream::println; use anyhow::Result; use itertools::Itertools; use owo_colors::OwoColorize; @@ -33,7 +32,7 @@ pub(crate) fn pip_list( python: Option<&str>, system: bool, cache: &Cache, - mut printer: Printer, + printer: Printer, ) -> Result { // Detect the current Python interpreter. let platform = Platform::current()?; @@ -112,17 +111,22 @@ pub(crate) fn pip_list( } for elems in MultiZip(columns.iter().map(Column::fmt).collect_vec()) { - println!("{}", elems.join(" ")); + writeln!(printer.stdout(), "{}", elems.join(" "))?; } } ListFormat::Json => { let rows = results.iter().copied().map(Entry::from).collect_vec(); let output = serde_json::to_string(&rows)?; - println!("{output}"); + writeln!(printer.stdout(), "{output}")?; } ListFormat::Freeze => { for dist in &results { - println!("{}=={}", dist.name().bold(), dist.version()); + writeln!( + printer.stdout(), + "{}=={}", + dist.name().bold(), + dist.version() + )?; } } } @@ -131,7 +135,7 @@ pub(crate) fn pip_list( if strict { for diagnostic in site_packages.diagnostics()? { writeln!( - printer, + printer.stderr(), "{}{} {}", "warning".yellow().bold(), ":".bold(), diff --git a/crates/uv/src/commands/pip_show.rs b/crates/uv/src/commands/pip_show.rs index efeda1254..2ed27248b 100644 --- a/crates/uv/src/commands/pip_show.rs +++ b/crates/uv/src/commands/pip_show.rs @@ -4,7 +4,6 @@ use anyhow::Result; use owo_colors::OwoColorize; use tracing::debug; -use anstream::{eprintln, println}; use distribution_types::Name; use platform_host::Platform; use uv_cache::Cache; @@ -22,18 +21,18 @@ pub(crate) fn pip_show( strict: bool, python: Option<&str>, system: bool, - quiet: bool, cache: &Cache, - mut printer: Printer, + printer: Printer, ) -> Result { if packages.is_empty() { #[allow(clippy::print_stderr)] { - eprintln!( + writeln!( + printer.stderr(), "{}{} Please provide a package name or names.", "warning".yellow().bold(), ":".bold(), - ); + )?; } return Ok(ExitStatus::Failure); } @@ -76,7 +75,7 @@ pub(crate) fn pip_show( let installed = site_packages.get_packages(package); if installed.is_empty() { writeln!( - printer, + printer.stderr(), "{}{} Package(s) not found for: {}", "warning".yellow().bold(), ":".bold(), @@ -95,47 +94,40 @@ pub(crate) fn pip_show( return Ok(ExitStatus::Failure); } - if !quiet { - // Print the information for each package. - let mut first = true; - for distribution in &distributions { - if first { - first = false; - } else { - // Print a separator between packages. - #[allow(clippy::print_stdout)] - { - println!("---"); - } - } - - // Print the name, version, and location (e.g., the `site-packages` directory). - #[allow(clippy::print_stdout)] - { - println!("Name: {}", distribution.name()); - println!("Version: {}", distribution.version()); - println!( - "Location: {}", - distribution - .path() - .parent() - .expect("package path is not root") - .simplified_display() - ); - } + // Print the information for each package. + let mut first = true; + for distribution in &distributions { + if first { + first = false; + } else { + // Print a separator between packages. + writeln!(printer.stdout(), "---")?; } - // Validate that the environment is consistent. - if strict { - for diagnostic in site_packages.diagnostics()? { - writeln!( - printer, - "{}{} {}", - "warning".yellow().bold(), - ":".bold(), - diagnostic.message().bold() - )?; - } + // Print the name, version, and location (e.g., the `site-packages` directory). + writeln!(printer.stdout(), "Name: {}", distribution.name())?; + writeln!(printer.stdout(), "Version: {}", distribution.version())?; + writeln!( + printer.stdout(), + "Location: {}", + distribution + .path() + .parent() + .expect("package path is not root") + .simplified_display() + )?; + } + + // Validate that the environment is consistent. + if strict { + for diagnostic in site_packages.diagnostics()? { + writeln!( + printer.stderr(), + "{}{} {}", + "warning".yellow().bold(), + ":".bold(), + diagnostic.message().bold() + )?; } } diff --git a/crates/uv/src/commands/pip_sync.rs b/crates/uv/src/commands/pip_sync.rs index 4c824286e..565869328 100644 --- a/crates/uv/src/commands/pip_sync.rs +++ b/crates/uv/src/commands/pip_sync.rs @@ -44,7 +44,7 @@ pub(crate) async fn pip_sync( python: Option, system: bool, cache: Cache, - mut printer: Printer, + printer: Printer, ) -> Result { let start = std::time::Instant::now(); @@ -64,7 +64,7 @@ pub(crate) async fn pip_sync( let num_requirements = requirements.len() + editables.len(); if num_requirements == 0 { - writeln!(printer, "No requirements found")?; + writeln!(printer.stderr(), "No requirements found")?; return Ok(ExitStatus::Success); } @@ -184,7 +184,7 @@ pub(crate) async fn pip_sync( if remote.is_empty() && local.is_empty() && reinstalls.is_empty() && extraneous.is_empty() { let s = if num_requirements == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Audited {} in {}", @@ -210,7 +210,7 @@ pub(crate) async fn pip_sync( let s = if resolution.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Resolved {} in {}", @@ -239,7 +239,7 @@ pub(crate) async fn pip_sync( let s = if wheels.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Downloaded {} in {}", @@ -274,7 +274,7 @@ pub(crate) async fn pip_sync( "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Uninstalled {} in {}", @@ -296,7 +296,7 @@ pub(crate) async fn pip_sync( let s = if wheels.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Installed {} in {}", @@ -334,7 +334,7 @@ pub(crate) async fn pip_sync( match event.kind { ChangeEventKind::Added => { writeln!( - printer, + printer.stderr(), " {} {}{}", "+".green(), event.dist.name().as_ref().bold(), @@ -343,7 +343,7 @@ pub(crate) async fn pip_sync( } ChangeEventKind::Removed => { writeln!( - printer, + printer.stderr(), " {} {}{}", "-".red(), event.dist.name().as_ref().bold(), @@ -358,7 +358,7 @@ pub(crate) async fn pip_sync( let site_packages = SitePackages::from_executable(&venv)?; for diagnostic in site_packages.diagnostics()? { writeln!( - printer, + printer.stderr(), "{}{} {}", "warning".yellow().bold(), ":".bold(), @@ -377,7 +377,7 @@ pub(crate) async fn pip_sync( None | Some(Yanked::Bool(false)) => {} Some(Yanked::Bool(true)) => { writeln!( - printer, + printer.stderr(), "{}{} {dist} is yanked. Refresh your lockfile to pin an un-yanked version.", "warning".yellow().bold(), ":".bold(), @@ -385,7 +385,7 @@ pub(crate) async fn pip_sync( } Some(Yanked::Reason(reason)) => { writeln!( - printer, + printer.stderr(), "{}{} {dist} is yanked (reason: \"{reason}\"). Refresh your lockfile to pin an un-yanked version.", "warning".yellow().bold(), ":".bold(), @@ -418,7 +418,7 @@ async fn resolve_editables( cache: &Cache, client: &RegistryClient, build_dispatch: &BuildDispatch<'_>, - mut printer: Printer, + printer: Printer, ) -> Result { // Partition the editables into those that are already installed, and those that must be built. let mut installed = Vec::with_capacity(editables.len()); @@ -519,7 +519,7 @@ async fn resolve_editables( let s = if built_editables.len() == 1 { "" } else { "s" }; writeln!( - printer, + printer.stderr(), "{}", format!( "Built {} in {}", diff --git a/crates/uv/src/commands/pip_uninstall.rs b/crates/uv/src/commands/pip_uninstall.rs index 96be3d62b..63715c06e 100644 --- a/crates/uv/src/commands/pip_uninstall.rs +++ b/crates/uv/src/commands/pip_uninstall.rs @@ -20,7 +20,7 @@ pub(crate) async fn pip_uninstall( python: Option, system: bool, cache: Cache, - mut printer: Printer, + printer: Printer, ) -> Result { let start = std::time::Instant::now(); @@ -105,7 +105,7 @@ pub(crate) async fn pip_uninstall( let installed = site_packages.get_packages(package); if installed.is_empty() { writeln!( - printer, + printer.stderr(), "{}{} Skipping {} as it is not installed.", "warning".yellow().bold(), ":".bold(), @@ -121,7 +121,7 @@ pub(crate) async fn pip_uninstall( let installed = site_packages.get_editables(editable); if installed.is_empty() { writeln!( - printer, + printer.stderr(), "{}{} Skipping {} as it is not installed.", "warning".yellow().bold(), ":".bold(), @@ -140,7 +140,7 @@ pub(crate) async fn pip_uninstall( if distributions.is_empty() { writeln!( - printer, + printer.stderr(), "{}{} No packages to uninstall.", "warning".yellow().bold(), ":".bold(), @@ -162,7 +162,7 @@ pub(crate) async fn pip_uninstall( } writeln!( - printer, + printer.stderr(), "{}", format!( "Uninstalled {} in {}", @@ -179,7 +179,7 @@ pub(crate) async fn pip_uninstall( for distribution in distributions { writeln!( - printer, + printer.stderr(), " {} {}{}", "-".red(), distribution.name().as_ref().bold(), diff --git a/crates/uv/src/commands/venv.rs b/crates/uv/src/commands/venv.rs index ca3b5e361..015465d95 100644 --- a/crates/uv/src/commands/venv.rs +++ b/crates/uv/src/commands/venv.rs @@ -94,7 +94,7 @@ async fn venv_impl( seed: bool, exclude_newer: Option>, cache: &Cache, - mut printer: Printer, + printer: Printer, ) -> miette::Result { // Locate the Python interpreter. let platform = Platform::current().into_diagnostic()?; @@ -108,7 +108,7 @@ async fn venv_impl( }; writeln!( - printer, + printer.stderr(), "Using Python {} interpreter at: {}", interpreter.python_version(), interpreter.sys_executable().simplified_display().cyan() @@ -116,7 +116,7 @@ async fn venv_impl( .into_diagnostic()?; writeln!( - printer, + printer.stderr(), "Creating virtualenv at: {}", path.simplified_display().cyan() ) @@ -201,7 +201,7 @@ async fn venv_impl( .sorted_unstable_by(|a, b| a.name().cmp(b.name()).then(a.version().cmp(&b.version()))) { writeln!( - printer, + printer.stderr(), " {} {}{}", "+".green(), distribution.name().as_ref().bold(), @@ -233,7 +233,7 @@ async fn venv_impl( Some(Shell::Powershell) => Some(shlex_windows(path.join("Scripts").join("activate"))), }; if let Some(act) = activation { - writeln!(printer, "Activate with: {}", act.green()).into_diagnostic()?; + writeln!(printer.stderr(), "Activate with: {}", act.green()).into_diagnostic()?; } Ok(ExitStatus::Success) diff --git a/crates/uv/src/main.rs b/crates/uv/src/main.rs index c1e184eb9..92e0c1084 100644 --- a/crates/uv/src/main.rs +++ b/crates/uv/src/main.rs @@ -1486,7 +1486,6 @@ async fn run() -> Result { args.strict, args.python.as_deref(), args.system, - cli.quiet, &cache, printer, ), diff --git a/crates/uv/src/printer.rs b/crates/uv/src/printer.rs index 358287241..fac8a2356 100644 --- a/crates/uv/src/printer.rs +++ b/crates/uv/src/printer.rs @@ -1,4 +1,4 @@ -use anstream::eprint; +use anstream::{eprint, print}; use indicatif::ProgressDrawTarget; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -22,18 +22,64 @@ impl Printer { Self::Verbose => ProgressDrawTarget::hidden(), } } + + /// Return the [`Stdout`] for this printer. + pub(crate) fn stdout(self) -> Stdout { + match self { + Self::Default => Stdout::Enabled, + Self::Quiet => Stdout::Disabled, + Self::Verbose => Stdout::Enabled, + } + } + + /// Return the [`Stderr`] for this printer. + pub(crate) fn stderr(self) -> Stderr { + match self { + Self::Default => Stderr::Enabled, + Self::Quiet => Stderr::Disabled, + Self::Verbose => Stderr::Enabled, + } + } } -impl std::fmt::Write for Printer { +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum Stdout { + Enabled, + Disabled, +} + +impl std::fmt::Write for Stdout { fn write_str(&mut self, s: &str) -> std::fmt::Result { match self { - Self::Default | Self::Verbose => { - #[allow(clippy::print_stderr, clippy::ignored_unit_patterns)] + Self::Enabled => { + #[allow(clippy::print_stdout, clippy::ignored_unit_patterns)] { - eprint!("{s}"); + print!("{s}"); } } - Self::Quiet => {} + Self::Disabled => {} + } + + Ok(()) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum Stderr { + Enabled, + Disabled, +} + +impl std::fmt::Write for Stderr { + fn write_str(&mut self, s: &str) -> std::fmt::Result { + match self { + Self::Enabled => { + #[allow(clippy::print_stderr, clippy::ignored_unit_patterns)] + { + eprint!("{s}"); + } + } + Self::Disabled => {} } Ok(())