Remove --version from subcommands (#13108)

Supersedes https://github.com/astral-sh/uv/pull/12439 — does not use the
Clap macro so we retain control over the messages
Closes #12431

0077a67b34
pulls `uv run` and `uv tool run` test changes from
https://github.com/astral-sh/uv/pull/12439
This commit is contained in:
Zanie Blue 2025-04-28 10:43:29 -05:00
parent b6df755c9b
commit 60a164abbb
6 changed files with 66 additions and 145 deletions

View file

@ -76,7 +76,6 @@ const STYLES: Styles = Styles::styled()
#[derive(Parser)]
#[command(name = "uv", author, long_version = crate::version::uv_self_version())]
#[command(about = "An extremely fast Python package manager.")]
#[command(propagate_version = true)]
#[command(
after_help = "Use `uv help` for more details.",
after_long_help = "",
@ -127,7 +126,7 @@ pub struct TopLevelArgs {
help: Option<bool>,
/// Display the uv version.
#[arg(global = true, short = 'V', long, action = clap::ArgAction::Version, help_heading = "Global options")]
#[arg(short = 'V', long, action = clap::ArgAction::Version)]
version: Option<bool>,
}
@ -4063,9 +4062,10 @@ pub enum ToolCommand {
override_usage = "uvx [OPTIONS] [COMMAND]",
about = "Run a command provided by a Python package.",
after_help = "Use `uv help tool run` for more details.",
after_long_help = ""
after_long_help = "",
long_version = crate::version::uv_self_version()
)]
Uvx(ToolRunArgs),
Uvx(UvxArgs),
/// Install commands provided by a Python package.
///
/// Packages are installed into an isolated virtual environment in the uv tools directory. The
@ -4223,6 +4223,16 @@ pub struct ToolRunArgs {
pub generate_shell_completion: Option<clap_complete_command::Shell>,
}
#[derive(Args)]
pub struct UvxArgs {
#[command(flatten)]
pub tool_run: ToolRunArgs,
/// Display the uvx version.
#[arg(short = 'V', long, action = clap::ArgAction::Version)]
pub version: Option<bool>,
}
#[derive(Args)]
#[allow(clippy::struct_excessive_bools)]
pub struct ToolInstallArgs {

View file

@ -1067,7 +1067,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
command: run_variant @ (ToolCommand::Uvx(_) | ToolCommand::Run(_)),
}) => {
let (args, invocation_source) = match run_variant {
ToolCommand::Uvx(args) => (args, ToolRunCommand::Uvx),
ToolCommand::Uvx(args) => (args.tool_run, ToolRunCommand::Uvx),
ToolCommand::Run(args) => (args, ToolRunCommand::ToolRun),
// OK guarded by the outer match statement
_ => unreachable!(),
@ -1081,15 +1081,15 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
.find_subcommand("uvx")
.unwrap()
.clone()
// Avoid duplicating the `--help` and `--version` flags from the top-level arguments.
// Avoid duplicating the `--help` and `--version` flags from the top-level
// arguments.
.disable_help_flag(true)
.disable_version_flag(true)
.version(env!("CARGO_PKG_VERSION"));
.disable_version_flag(true);
// Copy the top-level arguments into the `uvx` command. (Like `Args::augment_args`, but
// expanded to skip collisions.)
// Copy the top-level arguments into the `uvx` command, as in `Args::augment_args`,
// but expanded to skip collisions.
for arg in TopLevelArgs::command().get_arguments() {
if arg.get_id() != "isolated" {
if arg.get_id() != "isolated" && arg.get_id() != "version" {
uvx = uvx.arg(arg);
}
}

View file

@ -438,9 +438,6 @@ fn help_subcommand() {
-h, --help
Display the concise help for this command
-V, --version
Display the uv version
Use `uv help python <command>` for more information on a specific command.
@ -691,9 +688,6 @@ fn help_subsubcommand() {
-h, --help
Display the concise help for this command
-V, --version
Display the uv version
----- stderr -----
"#);
@ -755,8 +749,6 @@ fn help_flag_subcommand() {
Avoid discovering configuration files (`pyproject.toml`, `uv.toml`) [env: UV_NO_CONFIG=]
-h, --help
Display the concise help for this command
-V, --version
Display the uv version
Use `uv help python` for more details.
@ -826,8 +818,6 @@ fn help_flag_subsubcommand() {
Avoid discovering configuration files (`pyproject.toml`, `uv.toml`) [env: UV_NO_CONFIG=]
-h, --help
Display the concise help for this command
-V, --version
Display the uv version
----- stderr -----
"#);
@ -896,7 +886,7 @@ fn help_unknown_subcommand() {
fn help_unknown_subsubcommand() {
let context = TestContext::new_with_versions(&[]);
uv_snapshot!(context.filters(), context.help().arg("python").arg("foobar"), @r###"
uv_snapshot!(context.filters(), context.help().arg("python").arg("foobar"), @r"
success: false
exit_code: 2
----- stdout -----
@ -909,7 +899,7 @@ fn help_unknown_subsubcommand() {
pin
dir
uninstall
"###);
");
}
#[test]
@ -1014,14 +1004,20 @@ fn help_with_help() {
fn help_with_version() {
let context = TestContext::new_with_versions(&[]);
uv_snapshot!(context.filters(), context.help().arg("--version"), @r###"
success: true
exit_code: 0
uv_snapshot!(context.filters(), context.help().arg("--version"), @r"
success: false
exit_code: 2
----- stdout -----
uv [VERSION] ([COMMIT] DATE)
----- stderr -----
"###);
error: unexpected argument '--version' found
tip: a similar argument exists: '--verbose'
Usage: uv help --verbose... [COMMAND]...
For more information, try '--help'.
");
}
#[test]

View file

@ -143,6 +143,10 @@ fn run_with_python_version() -> Result<()> {
fn run_args() -> Result<()> {
let context = TestContext::new("3.12");
let mut filters = context.filters();
filters.push((r"Usage: (uv|\.exe) run \[OPTIONS\] (?s).*", "[UV RUN HELP]"));
filters.push((r"usage: (\[VENV\]|\[PYTHON-3.12\])(?s).*", "[PYTHON HELP]"));
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(indoc! { r#"
[project]
@ -158,31 +162,25 @@ fn run_args() -> Result<()> {
})?;
// We treat arguments before the command as uv arguments
uv_snapshot!(context.filters(), context.run().arg("--version").arg("python"), @r###"
uv_snapshot!(filters, context.run().arg("--help").arg("python"), @r"
success: true
exit_code: 0
----- stdout -----
uv [VERSION] ([COMMIT] DATE)
Run a command or script
----- stderr -----
"###);
[UV RUN HELP]
");
// We don't treat arguments after the command as uv arguments
uv_snapshot!(context.filters(), context.run().arg("python").arg("--version"), @r###"
uv_snapshot!(filters, context.run().arg("python").arg("--help"), @r"
success: true
exit_code: 0
----- stdout -----
Python 3.12.[X]
----- stderr -----
Resolved 1 package in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ foo==1.0.0 (from file://[TEMP_DIR]/)
"###);
[PYTHON HELP]
");
// Can use `--` to separate uv arguments from the command arguments.
uv_snapshot!(context.filters(), context.run().arg("--").arg("python").arg("--version"), @r###"
uv_snapshot!(filters, context.run().arg("--").arg("python").arg("--version"), @r###"
success: true
exit_code: 0
----- stdout -----

View file

@ -9,46 +9,43 @@ use uv_static::EnvVars;
#[test]
fn tool_run_args() {
let context = TestContext::new("3.12").with_filtered_counts();
let mut filters = context.filters();
filters.push((
r"Usage: uv tool run \[OPTIONS\] (?s).*",
"[UV TOOL RUN HELP]",
));
filters.push((r"usage: pytest \[options\] (?s).*", "[PYTEST HELP]"));
let tool_dir = context.temp_dir.child("tools");
let bin_dir = context.temp_dir.child("bin");
// We treat arguments before the command as uv arguments
uv_snapshot!(context.filters(), context.tool_run()
.arg("--version")
// We treat arguments before the command as uv tool run arguments
uv_snapshot!(filters, context.tool_run()
.arg("--help")
.arg("pytest")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r###"
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----
uv [VERSION] ([COMMIT] DATE)
Run a command provided by a Python package
----- stderr -----
"###);
[UV TOOL RUN HELP]
");
// We don't treat arguments after the command as uv arguments
uv_snapshot!(context.filters(), context.tool_run()
// We don't treat arguments after the command as uv tool run arguments
uv_snapshot!(filters, context.tool_run()
.arg("pytest")
.arg("--version")
.arg("--help")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r###"
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----
pytest 8.1.1
----- stderr -----
Resolved [N] packages in [TIME]
Prepared [N] packages in [TIME]
Installed [N] packages in [TIME]
+ iniconfig==2.0.0
+ packaging==24.0
+ pluggy==1.4.0
+ pytest==8.1.1
"###);
[PYTEST HELP]
");
// Can use `--` to separate uv arguments from the command arguments.
uv_snapshot!(context.filters(), context.tool_run()
uv_snapshot!(filters, context.tool_run()
.arg("--")
.arg("pytest")
.arg("--version")