Skip to content

Commit

Permalink
Improve styling of uv remove dependency hints (#9960)
Browse files Browse the repository at this point in the history
Instead of using a warning, which is pretty aggressive feeling, use a
hint.
  • Loading branch information
zanieb authored Dec 17, 2024
1 parent d70160a commit 026a40d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 33 deletions.
74 changes: 44 additions & 30 deletions crates/uv/src/commands/project/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -110,18 +110,18 @@ 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 => {
let dev_deps = toml.remove_dev_dependency(&package)?;
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`"
);
Expand All @@ -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}`"
);
Expand All @@ -142,15 +142,15 @@ 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`"
);
}
} 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}`"
);
Expand Down Expand Up @@ -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(())
}
6 changes: 3 additions & 3 deletions crates/uv/tests/it/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
"###);

Expand Down Expand Up @@ -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`
"###);

Expand Down Expand Up @@ -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`
"###);

Expand Down

0 comments on commit 026a40d

Please sign in to comment.