Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve styling of uv remove dependency hints #9960

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading