diff --git a/crates/uv/src/commands/python/install.rs b/crates/uv/src/commands/python/install.rs index 5dd1d09e1c71..dd9cf2471b9b 100644 --- a/crates/uv/src/commands/python/install.rs +++ b/crates/uv/src/commands/python/install.rs @@ -5,6 +5,7 @@ use anyhow::Result; use fs_err as fs; use futures::StreamExt; use itertools::Itertools; +use owo_colors::OwoColorize; use uv_cache::Cache; use uv_client::Connectivity; use uv_configuration::PreviewMode; @@ -15,7 +16,7 @@ use uv_python::{requests_from_version_file, PythonRequest}; use uv_warnings::warn_user_once; use crate::commands::reporters::PythonDownloadReporter; -use crate::commands::ExitStatus; +use crate::commands::{elapsed, ExitStatus}; use crate::printer::Printer; /// Download and install Python versions. @@ -62,7 +63,8 @@ pub(crate) async fn install( for (request, download_request) in requests.iter().zip(download_requests) { writeln!( printer.stderr(), - "Looking for installation {request} ({download_request})" + "Searching for Python versions matching: {}", + request.cyan() )?; if let Some(installation) = installed_installations .iter() @@ -70,14 +72,15 @@ pub(crate) async fn install( { writeln!( printer.stderr(), - "Found existing installation `{}` that satisfies {request}", - installation.key() + "Found existing installation for {}: {}", + request.cyan(), + installation.key().green(), )?; if force { writeln!( printer.stderr(), - "Removing existing installation `{}`", - installation.key() + "Uninstalling {}", + installation.key().green() )?; fs::remove_dir_all(installation.path())?; unfilled_requests.push(download_request); @@ -94,12 +97,7 @@ pub(crate) async fn install( "Python is already available. Use `uv python install ` to install a specific version.", )?; } else if requests.len() > 1 { - writeln!( - printer.stderr(), - "All requested versions already installed." - )?; - } else { - writeln!(printer.stderr(), "Requested versions already installed.")?; + writeln!(printer.stderr(), "All requested versions already installed")?; } return Ok(ExitStatus::Success); } @@ -117,13 +115,6 @@ pub(crate) async fn install( .unique_by(|download| download.key()) .collect::>(); - let s = if downloads.len() == 1 { "" } else { "s" }; - writeln!( - printer.stderr(), - "Found {} version{s} requiring installation", - downloads.len() - )?; - // Construct a client let client = uv_client::BaseClientBuilder::new() .connectivity(connectivity) @@ -150,8 +141,9 @@ pub(crate) async fn install( DownloadResult::Fetched(path) => { writeln!( printer.stderr(), - "Installed Python {version} to {}", - path.user_display() + "Installed {} to: {}", + format!("Python {version}").cyan(), + path.user_display().cyan() )?; path } @@ -165,9 +157,13 @@ pub(crate) async fn install( let s = if downloads.len() == 1 { "" } else { "s" }; writeln!( printer.stderr(), - "Installed {} version{s} in {}s", - downloads.len(), - start.elapsed().as_secs() + "{}", + format!( + "Installed {} {}", + format!("{} version{s}", downloads.len()).bold(), + format!("in {}", elapsed(start.elapsed())).dimmed() + ) + .dimmed() )?; Ok(ExitStatus::Success) diff --git a/crates/uv/src/commands/python/list.rs b/crates/uv/src/commands/python/list.rs index a621285f6a30..69baf30b69bf 100644 --- a/crates/uv/src/commands/python/list.rs +++ b/crates/uv/src/commands/python/list.rs @@ -79,7 +79,7 @@ pub(crate) async fn list( .collect::>, DiscoveryError>>()? .into_iter() // Drop any "missing" installations - .filter_map(std::result::Result::ok); + .filter_map(Result::ok); let mut output = BTreeSet::new(); for installation in installed { diff --git a/crates/uv/src/commands/python/uninstall.rs b/crates/uv/src/commands/python/uninstall.rs index 67fbe8ea88dd..bdd4c7e82e3f 100644 --- a/crates/uv/src/commands/python/uninstall.rs +++ b/crates/uv/src/commands/python/uninstall.rs @@ -4,6 +4,7 @@ use std::fmt::Write; use anyhow::Result; use futures::StreamExt; use itertools::Itertools; +use owo_colors::OwoColorize; use uv_configuration::PreviewMode; use uv_python::downloads::{self, PythonDownloadRequest}; @@ -11,7 +12,7 @@ use uv_python::managed::ManagedPythonInstallations; use uv_python::PythonRequest; use uv_warnings::warn_user_once; -use crate::commands::ExitStatus; +use crate::commands::{elapsed, ExitStatus}; use crate::printer::Printer; /// Uninstall managed Python versions. @@ -24,6 +25,8 @@ pub(crate) async fn uninstall( warn_user_once!("`uv python uninstall` is experimental and may change without warning."); } + let start = std::time::Instant::now(); + let installations = ManagedPythonInstallations::from_settings()?.init()?; let _lock = installations.acquire_lock()?; @@ -43,7 +46,8 @@ pub(crate) async fn uninstall( for (request, download_request) in requests.iter().zip(download_requests) { writeln!( printer.stderr(), - "Looking for Python installations matching {request} ({download_request})" + "Searching for Python versions matching: {}", + request.cyan() )?; let mut found = false; for installation in installed_installations @@ -54,31 +58,28 @@ pub(crate) async fn uninstall( if matching_installations.insert(installation.clone()) { writeln!( printer.stderr(), - "Found installation `{}` that matches {request}", - installation.key() + "Found existing installation for {}: {}", + request.cyan(), + installation.key().green(), )?; } } if !found { writeln!( printer.stderr(), - "No installations found matching {request}" + "No existing installations found for: {}", + request.cyan() )?; } } if matching_installations.is_empty() { if matches!(requests.as_slice(), [PythonRequest::Any]) { - writeln!(printer.stderr(), "No installed installations found")?; + writeln!(printer.stderr(), "No Python installations found")?; } else if requests.len() > 1 { writeln!( printer.stderr(), - "No installations found matching the requests" - )?; - } else { - writeln!( - printer.stderr(), - "No installations found matching the request" + "No Python installations found matching the requests" )?; } return Ok(ExitStatus::Failure); @@ -98,18 +99,19 @@ pub(crate) async fn uninstall( for (key, result) in results.iter().sorted_by_key(|(key, _)| key) { if let Err(err) = result { failed = true; - writeln!(printer.stderr(), "Failed to uninstall `{key}`: {err}")?; + writeln!( + printer.stderr(), + "Failed to uninstall {}: {err}", + key.green() + )?; } else { - writeln!(printer.stderr(), "Uninstalled `{key}`")?; + writeln!(printer.stderr(), "Uninstalled {}", key.green())?; } } if failed { if matching_installations.len() > 1 { - writeln!( - printer.stderr(), - "Failed to remove some Python installations" - )?; + writeln!(printer.stderr(), "Failed to uninstall some Python versions")?; } return Ok(ExitStatus::Failure); } @@ -119,11 +121,15 @@ pub(crate) async fn uninstall( } else { "s" }; - writeln!( printer.stderr(), - "Removed {} Python installation{s}", - matching_installations.len() + "{}", + format!( + "Uninstalled {} {}", + format!("{} version{s}", matching_installations.len()).bold(), + format!("in {}", elapsed(start.elapsed())).dimmed() + ) + .dimmed() )?; Ok(ExitStatus::Success)