From 026a40d2a4e0472c954fcbef6ede969711aa230b Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Tue, 17 Dec 2024 14:23:29 -0600 Subject: [PATCH] Improve styling of `uv remove` dependency hints (#9960) Instead of using a warning, which is pretty aggressive feeling, use a hint. --- crates/uv/src/commands/project/remove.rs | 74 ++++++++++++++---------- crates/uv/tests/it/edit.rs | 6 +- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/crates/uv/src/commands/project/remove.rs b/crates/uv/src/commands/project/remove.rs index 02b2510a71e9..effa0752e205 100644 --- a/crates/uv/src/commands/project/remove.rs +++ b/crates/uv/src/commands/project/remove.rs @@ -17,7 +17,7 @@ use uv_pep508::PackageName; use uv_python::{PythonDownloads, PythonPreference, PythonRequest}; use uv_resolver::InstallTarget; use uv_scripts::Pep723Script; -use uv_warnings::{warn_user, warn_user_once}; +use uv_warnings::warn_user_once; use uv_workspace::pyproject::DependencyType; use uv_workspace::pyproject_mut::{DependencyTarget, PyProjectTomlMut}; use uv_workspace::{DiscoveryOptions, VirtualProject, Workspace}; @@ -110,10 +110,10 @@ pub(crate) async fn remove( DependencyType::Production => { let deps = toml.remove_dependency(&package)?; if deps.is_empty() { - warn_if_present(&package, &toml); + show_other_dependency_type_hint(printer, &package, &toml)?; anyhow::bail!( "The dependency `{package}` could not be found in `project.dependencies`" - ); + ) } } DependencyType::Dev => { @@ -121,7 +121,7 @@ pub(crate) async fn remove( let group_deps = toml.remove_dependency_group_requirement(&package, &DEV_DEPENDENCIES)?; if dev_deps.is_empty() && group_deps.is_empty() { - warn_if_present(&package, &toml); + show_other_dependency_type_hint(printer, &package, &toml)?; anyhow::bail!( "The dependency `{package}` could not be found in `tool.uv.dev-dependencies` or `tool.uv.dependency-groups.dev`" ); @@ -130,7 +130,7 @@ pub(crate) async fn remove( DependencyType::Optional(ref extra) => { let deps = toml.remove_optional_dependency(&package, extra)?; if deps.is_empty() { - warn_if_present(&package, &toml); + show_other_dependency_type_hint(printer, &package, &toml)?; anyhow::bail!( "The dependency `{package}` could not be found in `project.optional-dependencies.{extra}`" ); @@ -142,7 +142,7 @@ pub(crate) async fn remove( let group_deps = toml.remove_dependency_group_requirement(&package, &DEV_DEPENDENCIES)?; if dev_deps.is_empty() && group_deps.is_empty() { - warn_if_present(&package, &toml); + show_other_dependency_type_hint(printer, &package, &toml)?; anyhow::bail!( "The dependency `{package}` could not be found in `tool.uv.dev-dependencies` or `tool.uv.dependency-groups.dev`" ); @@ -150,7 +150,7 @@ pub(crate) async fn remove( } else { let deps = toml.remove_dependency_group_requirement(&package, group)?; if deps.is_empty() { - warn_if_present(&package, &toml); + show_other_dependency_type_hint(printer, &package, &toml)?; anyhow::bail!( "The dependency `{package}` could not be found in `dependency-groups.{group}`" ); @@ -312,34 +312,48 @@ enum Target { Script(Pep723Script), } -/// Emit a warning if a dependency with the given name is present as any dependency type. +/// Show a hint if a dependency with the given name is present as any dependency type. /// /// This is useful when a dependency of the user-specified type was not found, but it may be present /// elsewhere. -fn warn_if_present(name: &PackageName, pyproject: &PyProjectTomlMut) { +fn show_other_dependency_type_hint( + printer: Printer, + name: &PackageName, + pyproject: &PyProjectTomlMut, +) -> Result<()> { + // TODO(zanieb): Attach these hints to the error so they render _after_ in accordance our + // typical styling for dep_ty in pyproject.find_dependency(name, None) { match dep_ty { - DependencyType::Production => { - warn_user!("`{name}` is a production dependency"); - } - DependencyType::Dev => { - warn_user!( - "`{name}` is a development dependency (try: `{}`)", - format!("uv remove {name} --dev`").bold() - ); - } - DependencyType::Optional(group) => { - warn_user!( - "`{name}` is an optional dependency (try: `{}`)", - format!("uv remove {name} --optional {group}").bold() - ); - } - DependencyType::Group(group) => { - warn_user!( - "`{name}` is in the `{group}` group (try: `{}`)", - format!("uv remove {name} --group {group}").bold() - ); - } + DependencyType::Production => writeln!( + printer.stderr(), + "{}{} `{name}` is a production dependency", + "hint".bold().cyan(), + ":".bold(), + )?, + DependencyType::Dev => writeln!( + printer.stderr(), + "{}{} `{name}` is a development dependency (try: `{}`)", + "hint".bold().cyan(), + ":".bold(), + format!("uv remove {name} --dev`").bold() + )?, + DependencyType::Optional(group) => writeln!( + printer.stderr(), + "{}{} `{name}` is an optional dependency (try: `{}`)", + "hint".bold().cyan(), + ":".bold(), + format!("uv remove {name} --optional {group}").bold() + )?, + DependencyType::Group(group) => writeln!( + printer.stderr(), + "{}{} `{name}` is in the `{group}` group (try: `{}`)", + "hint".bold().cyan(), + ":".bold(), + format!("uv remove {name} --group {group}").bold() + )?, } } + + Ok(()) } diff --git a/crates/uv/tests/it/edit.rs b/crates/uv/tests/it/edit.rs index 442b15fc2142..d0747e01c3aa 100644 --- a/crates/uv/tests/it/edit.rs +++ b/crates/uv/tests/it/edit.rs @@ -1113,7 +1113,7 @@ fn add_remove_dev() -> Result<()> { ----- stdout ----- ----- stderr ----- - warning: `anyio` is in the `dev` group (try: `uv remove anyio --group dev`) + hint: `anyio` is in the `dev` group (try: `uv remove anyio --group dev`) error: The dependency `anyio` could not be found in `project.dependencies` "###); @@ -1336,7 +1336,7 @@ fn add_remove_optional() -> Result<()> { ----- stdout ----- ----- stderr ----- - warning: `anyio` is an optional dependency (try: `uv remove anyio --optional io`) + hint: `anyio` is an optional dependency (try: `uv remove anyio --optional io`) error: The dependency `anyio` could not be found in `project.dependencies` "###); @@ -4863,7 +4863,7 @@ fn remove_group() -> Result<()> { ----- stdout ----- ----- stderr ----- - warning: `anyio` is a production dependency + hint: `anyio` is a production dependency error: The dependency `anyio` could not be found in `dependency-groups.test` "###);