mirror of https://github.com/astral-sh/uv
Offer tip when users omits pip prefix (#1257)
## Summary Open to other opinions here. We could just continue (and warn), prompt the user with a confirmation, etc. (The weird thing about those two options is we might need to validate the command-line arguments _before_ we do that -- so you could get errors for bad arguments, and then get a warning that your subcommand is wrong. I can probably avoid that with more work if it feels like a better out come though.) Closes https://github.com/astral-sh/puffin/issues/1256.
This commit is contained in:
parent
62416286e2
commit
91118a962a
|
|
@ -6,6 +6,7 @@ use std::str::FromStr;
|
||||||
use anstream::eprintln;
|
use anstream::eprintln;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use chrono::{DateTime, Days, NaiveDate, NaiveTime, Utc};
|
use chrono::{DateTime, Days, NaiveDate, NaiveTime, Utc};
|
||||||
|
use clap::error::{ContextKind, ContextValue};
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
@ -614,7 +615,48 @@ struct RemoveArgs {
|
||||||
|
|
||||||
#[instrument] // Anchor span to check for overhead
|
#[instrument] // Anchor span to check for overhead
|
||||||
async fn run() -> Result<ExitStatus> {
|
async fn run() -> Result<ExitStatus> {
|
||||||
let cli = Cli::parse();
|
let cli = match Cli::try_parse() {
|
||||||
|
Ok(cli) => cli,
|
||||||
|
Err(mut err) => {
|
||||||
|
if let Some(ContextValue::String(subcommand)) = err.get(ContextKind::InvalidSubcommand)
|
||||||
|
{
|
||||||
|
match subcommand.as_str() {
|
||||||
|
"compile" | "lock" => {
|
||||||
|
err.insert(
|
||||||
|
ContextKind::SuggestedSubcommand,
|
||||||
|
ContextValue::String("puffin pip compile".to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"sync" => {
|
||||||
|
err.insert(
|
||||||
|
ContextKind::SuggestedSubcommand,
|
||||||
|
ContextValue::String("puffin pip sync".to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"install" | "add" => {
|
||||||
|
err.insert(
|
||||||
|
ContextKind::SuggestedSubcommand,
|
||||||
|
ContextValue::String("puffin pip install".to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"uninstall" | "remove" => {
|
||||||
|
err.insert(
|
||||||
|
ContextKind::SuggestedSubcommand,
|
||||||
|
ContextValue::String("puffin pip uninstall".to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"freeze" => {
|
||||||
|
err.insert(
|
||||||
|
ContextKind::SuggestedSubcommand,
|
||||||
|
ContextValue::String("puffin pip freeze".to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err.exit()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Configure the `tracing` crate, which controls internal logging.
|
// Configure the `tracing` crate, which controls internal logging.
|
||||||
#[cfg(feature = "tracing-durations-export")]
|
#[cfg(feature = "tracing-durations-export")]
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,24 @@ fn uninstall_command(context: &TestContext) -> Command {
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missing_pip() {
|
||||||
|
puffin_snapshot!(Command::new(get_bin()).arg("sync"), @r###"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: unrecognized subcommand 'sync'
|
||||||
|
|
||||||
|
tip: a similar subcommand exists: 'puffin pip sync'
|
||||||
|
|
||||||
|
Usage: puffin [OPTIONS] <COMMAND>
|
||||||
|
|
||||||
|
For more information, try '--help'.
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn missing_requirements_txt() {
|
fn missing_requirements_txt() {
|
||||||
let context = TestContext::new("3.12");
|
let context = TestContext::new("3.12");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue