From 9d8ff2ee106179db31444e0ac618c5d1dfcd141e Mon Sep 17 00:00:00 2001 From: jiangzhen Date: Wed, 12 Aug 2026 18:37:42 +0800 Subject: [PATCH 1/3] fix(build): forward verbosity to build backends --- .../src/backend/json_rpc.rs | 33 ++++++- crates/pixi_build_frontend/src/tool.rs | 92 ++++++++++++++++++- crates/pixi_build_python/src/build_script.j2 | 8 +- crates/pixi_build_python/src/build_script.rs | 61 ++++++++++++ crates/pixi_build_python/src/main.rs | 6 +- crates/pixi_cli/src/lib.rs | 9 +- .../src/command_dispatcher/builder.rs | 72 ++++++++++++++- .../src/injected_config.rs | 11 ++- .../src/instantiate_backend_key.rs | 11 ++- crates/pixi_command_dispatcher/src/lib.rs | 25 ++++- 10 files changed, 315 insertions(+), 13 deletions(-) diff --git a/crates/pixi_build_frontend/src/backend/json_rpc.rs b/crates/pixi_build_frontend/src/backend/json_rpc.rs index 2f354dc625..c30c8cc47e 100644 --- a/crates/pixi_build_frontend/src/backend/json_rpc.rs +++ b/crates/pixi_build_frontend/src/backend/json_rpc.rs @@ -153,13 +153,44 @@ impl JsonRpcBackend { cache_dir: Option, workspace_scratch_directory: Option, tool: Tool, + ) -> Result { + Self::setup_with_verbosity( + source_dir, + manifest_path, + workspace_root, + checkout_root, + package_manifest, + configuration, + target_configuration, + cache_dir, + workspace_scratch_directory, + tool, + crate::tool::BackendVerbosity::default(), + ) + .await + } + + /// Set up a new protocol instance with explicit backend verbosity. + #[allow(clippy::too_many_arguments)] + pub async fn setup_with_verbosity( + source_dir: PathBuf, + manifest_path: PathBuf, + workspace_root: PathBuf, + checkout_root: Option, + package_manifest: Option, + configuration: Option, + target_configuration: Option>, + cache_dir: Option, + workspace_scratch_directory: Option, + tool: Tool, + backend_verbosity: crate::tool::BackendVerbosity, ) -> Result { debug_assert!(source_dir.is_absolute()); debug_assert!(manifest_path.is_absolute()); debug_assert!(workspace_root.is_absolute()); debug_assert!(checkout_root.as_ref().is_none_or(|p| p.is_absolute())); // Spawn the tool and capture stdin/stdout. - let command = tool.command(); + let command = tool.command_with_verbosity(backend_verbosity); let program_name = command.get_program().to_string_lossy().into_owned(); let mut process = match tokio::process::Command::from(command) .stdout(std::process::Stdio::piped()) diff --git a/crates/pixi_build_frontend/src/tool.rs b/crates/pixi_build_frontend/src/tool.rs index 8ce75dcb3e..7c05f94826 100644 --- a/crates/pixi_build_frontend/src/tool.rs +++ b/crates/pixi_build_frontend/src/tool.rs @@ -1,6 +1,36 @@ use rattler_conda_types::VersionWithSource; use std::{collections::HashMap, path::PathBuf}; +/// Verbosity flags to pass to a build backend process. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] +pub struct BackendVerbosity { + quiet: u8, + verbose: u8, +} + +impl BackendVerbosity { + /// Construct backend verbosity from Pixi's CLI flag counts. + pub fn from_cli(quiet: u8, verbose: u8) -> Self { + Self { quiet, verbose } + } + + fn args(self) -> Vec<&'static str> { + if self.quiet > 0 { + return vec!["-q"; 3]; + } + + match self.verbose { + // Preserve the backend's environment/default when Pixi received no + // explicit verbosity option. + 0 => Vec::new(), + 1 => vec!["-q"], + 2 => Vec::new(), + 3 => vec!["-v"], + _ => vec!["-v"; 2], + } + } +} + /// A tool that can be invoked. #[derive(Debug)] pub enum Tool { @@ -110,7 +140,12 @@ impl Tool { /// Construct a new command that enables invocation of the tool. /// TODO: whether to inject proxy config pub fn command(&self) -> std::process::Command { - match self { + self.command_with_verbosity(BackendVerbosity::default()) + } + + /// Construct a new command with explicit backend verbosity. + pub fn command_with_verbosity(&self, verbosity: BackendVerbosity) -> std::process::Command { + let mut command = match self { Tool::Isolated(tool) => { let mut cmd = std::process::Command::new(&tool.command); cmd.envs(tool.activation_scripts.clone()); @@ -118,6 +153,59 @@ impl Tool { cmd } Tool::System(tool) => std::process::Command::new(&tool.command), - } + }; + + command.args(verbosity.args()); + command + } +} + +#[cfg(test)] +mod tests { + use std::{collections::HashMap, ffi::OsStr}; + + use super::{BackendVerbosity, IsolatedTool, SystemTool, Tool}; + + #[test] + fn backend_verbosity_matches_pixi_cli_levels() { + assert!(BackendVerbosity::from_cli(0, 0).args().is_empty()); + assert_eq!(BackendVerbosity::from_cli(0, 1).args(), ["-q"]); + assert!(BackendVerbosity::from_cli(0, 2).args().is_empty()); + assert_eq!(BackendVerbosity::from_cli(0, 3).args(), ["-v"]); + assert_eq!(BackendVerbosity::from_cli(0, 4).args(), ["-v", "-v"]); + assert_eq!(BackendVerbosity::from_cli(1, 4).args(), ["-q", "-q", "-q"]); + assert_eq!(BackendVerbosity::from_cli(4, 1).args(), ["-q", "-q", "-q"]); + } + + #[test] + fn tool_commands_include_verbosity() { + let tool = Tool::from(SystemTool::new("backend")); + assert_eq!( + tool.command_with_verbosity(BackendVerbosity::from_cli(0, 4)) + .get_args() + .collect::>(), + [OsStr::new("-v"), OsStr::new("-v")] + ); + + let tool = Tool::from(IsolatedTool::new( + "backend", + None, + "/prefix", + HashMap::new(), + )); + assert_eq!( + tool.command_with_verbosity(BackendVerbosity::from_cli(1, 4)) + .get_args() + .collect::>(), + [OsStr::new("-q"), OsStr::new("-q"), OsStr::new("-q")] + ); + + assert!( + Tool::from(SystemTool::new("backend")) + .command() + .get_args() + .next() + .is_none() + ); } } diff --git a/crates/pixi_build_python/src/build_script.j2 b/crates/pixi_build_python/src/build_script.j2 index ff1b1ec4c3..62a41bd8e5 100644 --- a/crates/pixi_build_python/src/build_script.j2 +++ b/crates/pixi_build_python/src/build_script.j2 @@ -1,11 +1,17 @@ {% set PYTHON="%PYTHON%" if build_platform == "windows" else "$PYTHON" -%} {%- set OPTIONS = [ - "-vv", "--no-deps", "--no-build-isolation", "--no-index" ] + extra_args + (["--editable"] if editable else []) -%} +{%- if installer == "uv" and uv_verbosity == 1 -%} +{% set OPTIONS = ["-v"] + OPTIONS -%} +{%- elif installer == "uv" and uv_verbosity >= 2 -%} +{% set OPTIONS = ["-vv"] + OPTIONS -%} +{%- elif installer == "pip" -%} +{% set OPTIONS = ["-vv"] + OPTIONS -%} +{%- endif -%} {% if build_platform == "windows" -%} {% set OPTIONS = OPTIONS | join(" ^\n ") -%} diff --git a/crates/pixi_build_python/src/build_script.rs b/crates/pixi_build_python/src/build_script.rs index 63de299f1b..e682430d0f 100644 --- a/crates/pixi_build_python/src/build_script.rs +++ b/crates/pixi_build_python/src/build_script.rs @@ -11,6 +11,17 @@ pub struct BuildScriptContext { pub editable: bool, pub extra_args: Vec, pub manifest_root: PathBuf, + pub uv_verbosity: u8, +} + +pub fn uv_verbosity(debug_enabled: bool, trace_enabled: bool) -> u8 { + if trace_enabled { + 2 + } else if debug_enabled { + 1 + } else { + 0 + } } /// The tool used to install the built wheel into the prefix. @@ -47,3 +58,53 @@ impl BuildScriptContext { template.render(self).unwrap().trim().to_string() } } + +#[cfg(test)] +mod tests { + use super::{BuildPlatform, BuildScriptContext, Installer, uv_verbosity}; + + fn context() -> BuildScriptContext { + BuildScriptContext { + installer: Installer::Uv, + build_platform: BuildPlatform::Unix, + editable: false, + extra_args: Vec::new(), + manifest_root: "/source".into(), + uv_verbosity: 0, + } + } + + #[test] + fn uv_is_quiet_without_explicit_verbosity() { + let script = context().render(); + assert!(!script.contains(" -v"), "unexpected verbose flag: {script}"); + } + + #[test] + fn uv_verbosity_follows_backend_logging() { + let mut context = context(); + context.uv_verbosity = 1; + assert!(context.render().contains("--reinstall -v ")); + + context.uv_verbosity = 2; + assert!(context.render().contains("--reinstall -vv ")); + } + + #[test] + fn uv_verbosity_is_derived_from_backend_logging() { + assert_eq!(uv_verbosity(false, false), 0); + assert_eq!(uv_verbosity(true, false), 1); + assert_eq!(uv_verbosity(true, true), 2); + } + + #[test] + fn pip_keeps_its_existing_verbosity() { + let mut context = context(); + context.installer = Installer::Pip; + assert!( + context + .render() + .contains("pip install --force-reinstall -vv ") + ); + } +} diff --git a/crates/pixi_build_python/src/main.rs b/crates/pixi_build_python/src/main.rs index cce27d422a..43a4557f9f 100644 --- a/crates/pixi_build_python/src/main.rs +++ b/crates/pixi_build_python/src/main.rs @@ -3,7 +3,7 @@ mod config; mod metadata; mod pypi_mapping; -use build_script::{BuildPlatform, BuildScriptContext, Installer}; +use build_script::{BuildPlatform, BuildScriptContext, Installer, uv_verbosity}; use config::PythonBackendConfig; use fs_err as fs; use miette::IntoDiagnostic; @@ -426,6 +426,10 @@ impl GenerateRecipe for PythonGenerator { editable, extra_args: config.extra_args.clone(), manifest_root: manifest_root.clone(), + uv_verbosity: uv_verbosity( + tracing::enabled!(target: "rattler_build", tracing::Level::DEBUG), + tracing::enabled!(target: "rattler_build", tracing::Level::TRACE), + ), } .render(); diff --git a/crates/pixi_cli/src/lib.rs b/crates/pixi_cli/src/lib.rs index f10531d20d..9ca1e0487e 100644 --- a/crates/pixi_cli/src/lib.rs +++ b/crates/pixi_cli/src/lib.rs @@ -278,7 +278,14 @@ pub async fn execute() -> miette::Result<()> { }; // Execute the command - execute_command(command, &global_options).await + pixi_command_dispatcher::scope_backend_verbosity( + pixi_build_frontend::tool::BackendVerbosity::from_cli( + global_options.quiet, + global_options.verbose, + ), + execute_command(command, &global_options), + ) + .await } #[cfg(feature = "console-subscriber")] diff --git a/crates/pixi_command_dispatcher/src/command_dispatcher/builder.rs b/crates/pixi_command_dispatcher/src/command_dispatcher/builder.rs index 7da1ca1f81..bf4e00a3e7 100644 --- a/crates/pixi_command_dispatcher/src/command_dispatcher/builder.rs +++ b/crates/pixi_command_dispatcher/src/command_dispatcher/builder.rs @@ -11,7 +11,8 @@ use crate::compute_data::{ }; use crate::environment::WorkspaceEnvRegistry; use crate::injected_config::{ - BackendOverrideKey, ChannelConfigKey, EnabledProtocolsKey, ToolBuildEnvironmentKey, + BackendOverrideKey, BackendVerbosityKey, ChannelConfigKey, EnabledProtocolsKey, + ToolBuildEnvironmentKey, }; use crate::reporter::{ BackendSourceBuildReporter, BuildBackendMetadataReporter, CondaSolveReporter, GatewayReporter, @@ -24,7 +25,7 @@ use crate::{ command_dispatcher::{CommandDispatcherData, DepGraphDumpGuard}, }; use pixi_build_discovery::EnabledProtocols; -use pixi_build_frontend::BackendOverride; +use pixi_build_frontend::{BackendOverride, tool::BackendVerbosity}; use pixi_compute_cache_dirs::CacheDirsKey; use pixi_compute_engine::ComputeEngine; use pixi_compute_env_vars::EnvVarsKey; @@ -54,6 +55,7 @@ pub struct CommandDispatcherBuilder { download_client: Option, cache_dirs: Option, build_backend_overrides: BackendOverride, + backend_verbosity: Option, max_download_concurrency: MaxConcurrency, limits: Limits, executor: Executor, @@ -87,6 +89,14 @@ pub struct CommandDispatcherBuilder { } impl CommandDispatcherBuilder { + /// Sets the verbosity passed to spawned build backend processes. + pub fn with_backend_verbosity(self, backend_verbosity: BackendVerbosity) -> Self { + Self { + backend_verbosity: Some(backend_verbosity), + ..self + } + } + /// Sets the cache directories to use. pub fn with_cache_dirs(self, cache_dirs: CacheDirs) -> Self { Self { @@ -356,6 +366,9 @@ impl CommandDispatcherBuilder { /// Completes the builder and returns a new [`CommandDispatcher`]. pub fn finish(self) -> CommandDispatcher { + let backend_verbosity = self + .backend_verbosity + .unwrap_or_else(crate::current_backend_verbosity); let root_dir = self.root_dir.unwrap_or_else(|| { let current_dir = std::env::current_dir().expect("failed to determine current directory"); @@ -565,6 +578,7 @@ impl CommandDispatcherBuilder { BackendOverrideKey, Arc::new(data.build_backend_overrides.clone()), ); + engine.inject(BackendVerbosityKey, Arc::new(backend_verbosity)); CommandDispatcher { _dump_guard: Arc::new(DepGraphDumpGuard { @@ -575,3 +589,57 @@ impl CommandDispatcherBuilder { } } } + +#[cfg(test)] +mod tests { + use pixi_build_frontend::tool::BackendVerbosity; + + use super::CommandDispatcherBuilder; + use crate::{BackendVerbosityKey, scope_backend_verbosity}; + + #[tokio::test] + async fn dispatcher_snapshots_scoped_backend_verbosity_per_instance() { + let trace = BackendVerbosity::from_cli(0, 4); + let quiet = BackendVerbosity::from_cli(1, 4); + + let (trace_dispatcher, quiet_dispatcher) = tokio::join!( + scope_backend_verbosity(trace, async { + CommandDispatcherBuilder::default().finish() + }), + scope_backend_verbosity(quiet, async { + CommandDispatcherBuilder::default().finish() + }), + ); + + assert_eq!( + *trace_dispatcher + .engine() + .read(&BackendVerbosityKey) + .expect("verbosity is injected"), + trace + ); + assert_eq!( + *quiet_dispatcher + .engine() + .read(&BackendVerbosityKey) + .expect("verbosity is injected"), + quiet + ); + } + + #[test] + fn explicit_backend_verbosity_overrides_the_execution_context_default() { + let verbosity = BackendVerbosity::from_cli(0, 3); + let dispatcher = CommandDispatcherBuilder::default() + .with_backend_verbosity(verbosity) + .finish(); + + assert_eq!( + *dispatcher + .engine() + .read(&BackendVerbosityKey) + .expect("verbosity is injected"), + verbosity + ); + } +} diff --git a/crates/pixi_command_dispatcher/src/injected_config.rs b/crates/pixi_command_dispatcher/src/injected_config.rs index d502eed3a8..d38e8633ca 100644 --- a/crates/pixi_command_dispatcher/src/injected_config.rs +++ b/crates/pixi_command_dispatcher/src/injected_config.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use derive_more::Display; use pixi_build_discovery::EnabledProtocols; -use pixi_build_frontend::BackendOverride; +use pixi_build_frontend::{BackendOverride, tool::BackendVerbosity}; use pixi_compute_engine::InjectedKey; use rattler_conda_types::ChannelConfig; @@ -52,3 +52,12 @@ pub struct BackendOverrideKey; impl InjectedKey for BackendOverrideKey { type Value = Arc; } + +/// Injected backend verbosity for processes spawned by this dispatcher. +#[derive(Clone, Debug, Display, Hash, PartialEq, Eq)] +#[display("BackendVerbosity")] +pub struct BackendVerbosityKey; + +impl InjectedKey for BackendVerbosityKey { + type Value = Arc; +} diff --git a/crates/pixi_command_dispatcher/src/instantiate_backend_key.rs b/crates/pixi_command_dispatcher/src/instantiate_backend_key.rs index cba17aee4c..34741ab559 100644 --- a/crates/pixi_command_dispatcher/src/instantiate_backend_key.rs +++ b/crates/pixi_command_dispatcher/src/instantiate_backend_key.rs @@ -18,7 +18,7 @@ use pixi_build_frontend::{ in_memory::BoxedInMemoryBackend, json_rpc, json_rpc::{CommunicationError, JsonRpcBackend}, - tool::{IsolatedTool, SystemTool, Tool}, + tool::{BackendVerbosity, IsolatedTool, SystemTool, Tool}, }; use pixi_build_types::{ PIXI_BUILD_API_VERSION_NAME, PIXI_BUILD_API_VERSION_SPEC, PixiBuildApiVersion, ProjectModel, @@ -40,7 +40,7 @@ use tokio::sync::Mutex; use crate::InlinePackage; use crate::compute_data::HasInstantiateBackendReporter; use crate::ephemeral_env::{EphemeralEnvError, EphemeralEnvKey, EphemeralEnvSpec}; -use crate::injected_config::ToolBuildEnvironmentKey; +use crate::injected_config::{BackendVerbosityKey, ToolBuildEnvironmentKey}; use crate::inline_package::discover_backend; use crate::reporter::InstantiateBackendReporter; use crate::resolved_backend_command::{ResolvedBackendCommand, ResolvedBackendCommandKey}; @@ -354,6 +354,8 @@ impl InstantiateBackendKey { check_project_model_invariant(api_version, &discovered.init_params)?; + let backend_verbosity = *ctx.compute(&BackendVerbosityKey).await; + spawn_json_rpc( source_dir, self.checkout_root.clone(), @@ -363,6 +365,7 @@ impl InstantiateBackendKey { api_version, cache_dir_root, workspace_scratch_directory, + backend_verbosity, ) .await } @@ -634,9 +637,10 @@ async fn spawn_json_rpc( api_version: PixiBuildApiVersion, cache_dir_root: PathBuf, workspace_scratch_directory: Option, + backend_verbosity: BackendVerbosity, ) -> Result> { let project_model = project_model_overrides.apply(init_params.project_model.clone()); - let backend = JsonRpcBackend::setup( + let backend = JsonRpcBackend::setup_with_verbosity( source_dir, init_params.manifest_path.clone(), init_params.workspace_root.clone(), @@ -647,6 +651,7 @@ async fn spawn_json_rpc( Some(cache_dir_root), workspace_scratch_directory, tool, + backend_verbosity, ) .await .map_err(|e| Arc::new(InstantiateBackendError::JsonRpc(Arc::new(e))))?; diff --git a/crates/pixi_command_dispatcher/src/lib.rs b/crates/pixi_command_dispatcher/src/lib.rs index cbd747102f..9ba18cd4b2 100644 --- a/crates/pixi_command_dispatcher/src/lib.rs +++ b/crates/pixi_command_dispatcher/src/lib.rs @@ -69,6 +69,28 @@ mod solve_binary; mod solve_conda; mod util; +use std::future::Future; + +use pixi_build_frontend::tool::BackendVerbosity; + +tokio::task_local! { + static SCOPED_BACKEND_VERBOSITY: BackendVerbosity; +} + +/// Run a CLI command with backend verbosity inherited by dispatchers it creates. +pub async fn scope_backend_verbosity( + verbosity: BackendVerbosity, + future: impl Future, +) -> T { + SCOPED_BACKEND_VERBOSITY.scope(verbosity, future).await +} + +fn current_backend_verbosity() -> BackendVerbosity { + SCOPED_BACKEND_VERBOSITY + .try_with(|verbosity| *verbosity) + .unwrap_or_default() +} + pub use backend_source_build::{ BackendBuiltSource, BackendSourceBuildError, BackendSourceBuildExt, BackendSourceBuildMethod, BackendSourceBuildPrefix, BackendSourceBuildSpec, BackendSourceBuildV1Method, @@ -109,7 +131,8 @@ pub use errors::{ SourceRecordError, }; pub use injected_config::{ - BackendOverrideKey, ChannelConfigKey, EnabledProtocolsKey, ToolBuildEnvironmentKey, + BackendOverrideKey, BackendVerbosityKey, ChannelConfigKey, EnabledProtocolsKey, + ToolBuildEnvironmentKey, }; pub use inline_package::InlinePackage; pub use install_pixi::{ From dc3c58b52e323add4ac3412e726f04ee2d2fedfb Mon Sep 17 00:00:00 2001 From: jiangzhen Date: Wed, 12 Aug 2026 18:57:15 +0800 Subject: [PATCH 2/3] fix(build): align backend and pixi log levels --- crates/pixi_build_frontend/src/tool.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/pixi_build_frontend/src/tool.rs b/crates/pixi_build_frontend/src/tool.rs index 7c05f94826..f1861f3593 100644 --- a/crates/pixi_build_frontend/src/tool.rs +++ b/crates/pixi_build_frontend/src/tool.rs @@ -23,9 +23,8 @@ impl BackendVerbosity { // Preserve the backend's environment/default when Pixi received no // explicit verbosity option. 0 => Vec::new(), - 1 => vec!["-q"], - 2 => Vec::new(), - 3 => vec!["-v"], + 1 => Vec::new(), + 2 => vec!["-v"], _ => vec!["-v"; 2], } } @@ -169,9 +168,9 @@ mod tests { #[test] fn backend_verbosity_matches_pixi_cli_levels() { assert!(BackendVerbosity::from_cli(0, 0).args().is_empty()); - assert_eq!(BackendVerbosity::from_cli(0, 1).args(), ["-q"]); - assert!(BackendVerbosity::from_cli(0, 2).args().is_empty()); - assert_eq!(BackendVerbosity::from_cli(0, 3).args(), ["-v"]); + assert!(BackendVerbosity::from_cli(0, 1).args().is_empty()); + assert_eq!(BackendVerbosity::from_cli(0, 2).args(), ["-v"]); + assert_eq!(BackendVerbosity::from_cli(0, 3).args(), ["-v", "-v"]); assert_eq!(BackendVerbosity::from_cli(0, 4).args(), ["-v", "-v"]); assert_eq!(BackendVerbosity::from_cli(1, 4).args(), ["-q", "-q", "-q"]); assert_eq!(BackendVerbosity::from_cli(4, 1).args(), ["-q", "-q", "-q"]); @@ -181,7 +180,7 @@ mod tests { fn tool_commands_include_verbosity() { let tool = Tool::from(SystemTool::new("backend")); assert_eq!( - tool.command_with_verbosity(BackendVerbosity::from_cli(0, 4)) + tool.command_with_verbosity(BackendVerbosity::from_cli(0, 3)) .get_args() .collect::>(), [OsStr::new("-v"), OsStr::new("-v")] From 08cd4e3a6e6cabb430f18e977677fbebbf0f9fe9 Mon Sep 17 00:00:00 2001 From: jiangzhen Date: Mon, 24 Aug 2026 09:39:37 +0800 Subject: [PATCH 3/3] fix(build): make python installer verbosity generic --- crates/pixi_build_python/src/build_script.j2 | 6 +-- crates/pixi_build_python/src/build_script.rs | 55 +++++++++++++++----- crates/pixi_build_python/src/main.rs | 4 +- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/crates/pixi_build_python/src/build_script.j2 b/crates/pixi_build_python/src/build_script.j2 index 62a41bd8e5..e7657ed715 100644 --- a/crates/pixi_build_python/src/build_script.j2 +++ b/crates/pixi_build_python/src/build_script.j2 @@ -5,11 +5,9 @@ "--no-index" ] + extra_args + (["--editable"] if editable else []) -%} -{%- if installer == "uv" and uv_verbosity == 1 -%} +{%- if verbosity == 1 -%} {% set OPTIONS = ["-v"] + OPTIONS -%} -{%- elif installer == "uv" and uv_verbosity >= 2 -%} -{% set OPTIONS = ["-vv"] + OPTIONS -%} -{%- elif installer == "pip" -%} +{%- elif verbosity >= 2 -%} {% set OPTIONS = ["-vv"] + OPTIONS -%} {%- endif -%} diff --git a/crates/pixi_build_python/src/build_script.rs b/crates/pixi_build_python/src/build_script.rs index e682430d0f..53ffd9aecd 100644 --- a/crates/pixi_build_python/src/build_script.rs +++ b/crates/pixi_build_python/src/build_script.rs @@ -11,10 +11,10 @@ pub struct BuildScriptContext { pub editable: bool, pub extra_args: Vec, pub manifest_root: PathBuf, - pub uv_verbosity: u8, + pub verbosity: u8, } -pub fn uv_verbosity(debug_enabled: bool, trace_enabled: bool) -> u8 { +pub fn verbosity(debug_enabled: bool, trace_enabled: bool) -> u8 { if trace_enabled { 2 } else if debug_enabled { @@ -61,7 +61,7 @@ impl BuildScriptContext { #[cfg(test)] mod tests { - use super::{BuildPlatform, BuildScriptContext, Installer, uv_verbosity}; + use super::{BuildPlatform, BuildScriptContext, Installer, verbosity}; fn context() -> BuildScriptContext { BuildScriptContext { @@ -70,41 +70,68 @@ mod tests { editable: false, extra_args: Vec::new(), manifest_root: "/source".into(), - uv_verbosity: 0, + verbosity: 0, } } #[test] - fn uv_is_quiet_without_explicit_verbosity() { + fn installer_is_quiet_without_explicit_verbosity() { let script = context().render(); assert!(!script.contains(" -v"), "unexpected verbose flag: {script}"); } #[test] - fn uv_verbosity_follows_backend_logging() { + fn uv_installer_verbosity_follows_backend_logging() { let mut context = context(); - context.uv_verbosity = 1; + context.verbosity = 1; assert!(context.render().contains("--reinstall -v ")); - context.uv_verbosity = 2; + context.verbosity = 2; assert!(context.render().contains("--reinstall -vv ")); } #[test] - fn uv_verbosity_is_derived_from_backend_logging() { - assert_eq!(uv_verbosity(false, false), 0); - assert_eq!(uv_verbosity(true, false), 1); - assert_eq!(uv_verbosity(true, true), 2); + fn pip_installer_verbosity_follows_backend_logging() { + let mut context = context(); + context.installer = Installer::Pip; + assert!( + !context.render().contains(" -v"), + "unexpected default verbose flag: {}", + context.render() + ); + + context.verbosity = 1; + assert!( + context + .render() + .contains("pip install --force-reinstall -v ") + ); + + context.verbosity = 2; + assert!( + context + .render() + .contains("pip install --force-reinstall -vv ") + ); } #[test] - fn pip_keeps_its_existing_verbosity() { + fn verbosity_is_derived_from_backend_logging() { + assert_eq!(verbosity(false, false), 0); + assert_eq!(verbosity(true, false), 1); + assert_eq!(verbosity(true, true), 2); + } + + #[test] + fn pip_extra_args_are_preserved() { let mut context = context(); context.installer = Installer::Pip; + context.extra_args.push("--config-settings=foo=bar".into()); assert!( context .render() - .contains("pip install --force-reinstall -vv ") + .contains("pip install --force-reinstall --no-deps") ); + assert!(context.render().contains("--config-settings=foo=bar")); } } diff --git a/crates/pixi_build_python/src/main.rs b/crates/pixi_build_python/src/main.rs index 43a4557f9f..c44db9c7ad 100644 --- a/crates/pixi_build_python/src/main.rs +++ b/crates/pixi_build_python/src/main.rs @@ -3,7 +3,7 @@ mod config; mod metadata; mod pypi_mapping; -use build_script::{BuildPlatform, BuildScriptContext, Installer, uv_verbosity}; +use build_script::{BuildPlatform, BuildScriptContext, Installer, verbosity}; use config::PythonBackendConfig; use fs_err as fs; use miette::IntoDiagnostic; @@ -426,7 +426,7 @@ impl GenerateRecipe for PythonGenerator { editable, extra_args: config.extra_args.clone(), manifest_root: manifest_root.clone(), - uv_verbosity: uv_verbosity( + verbosity: verbosity( tracing::enabled!(target: "rattler_build", tracing::Level::DEBUG), tracing::enabled!(target: "rattler_build", tracing::Level::TRACE), ),