From 23245c63e9d63c4916328060aed3f45c03a11a9b Mon Sep 17 00:00:00 2001 From: John Mumm Date: Mon, 11 Aug 2025 22:20:04 +0200 Subject: [PATCH] Add `--reinstall` flag to `uv python upgrade` (#15194) As described in #15179, there are cases where it can be useful to reinstall the latest patch on upgrade if it is already installed. Using this flag, you don't need to know ahead of time if you have the latest patch already. Closes #15179. --- crates/uv-cli/src/lib.rs | 7 +++++++ crates/uv/src/lib.rs | 3 +-- crates/uv/src/settings.rs | 3 +++ crates/uv/tests/it/python_upgrade.rs | 11 +++++++++++ docs/reference/cli.md | 2 ++ 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 34c2575b9..af04737ec 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -5196,6 +5196,13 @@ pub struct PythonUpgradeArgs { #[arg(long, env = EnvVars::UV_PYPY_INSTALL_MIRROR)] pub pypy_mirror: Option, + /// Reinstall the latest Python patch, if it's already installed. + /// + /// By default, uv will exit successfully if the latest patch is already + /// installed. + #[arg(long, short)] + pub reinstall: bool, + /// URL pointing to JSON of custom Python installations. /// /// Note that currently, only local paths are supported. diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index 3a2d5c129..5f2399219 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -1437,14 +1437,13 @@ async fn run(mut cli: Cli) -> Result { // Resolve the settings from the command-line arguments and workspace configuration. let args = settings::PythonUpgradeSettings::resolve(args, filesystem); show_settings!(args); - let reinstall = false; let upgrade = true; commands::python_install( &project_dir, args.install_dir, args.targets, - reinstall, + args.reinstall, upgrade, args.bin, args.registry, diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index ad26eeaa9..f21ffdbb2 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -1019,6 +1019,7 @@ pub(crate) struct PythonUpgradeSettings { pub(crate) registry: Option, pub(crate) python_install_mirror: Option, pub(crate) pypy_install_mirror: Option, + pub(crate) reinstall: bool, pub(crate) python_downloads_json_url: Option, pub(crate) default: bool, pub(crate) bin: Option, @@ -1051,6 +1052,7 @@ impl PythonUpgradeSettings { targets, mirror: _, pypy_mirror: _, + reinstall, python_downloads_json_url: _, } = args; @@ -1061,6 +1063,7 @@ impl PythonUpgradeSettings { registry, python_install_mirror: python_mirror, pypy_install_mirror: pypy_mirror, + reinstall, python_downloads_json_url, default, bin, diff --git a/crates/uv/tests/it/python_upgrade.rs b/crates/uv/tests/it/python_upgrade.rs index bf6d45e08..860b3395c 100644 --- a/crates/uv/tests/it/python_upgrade.rs +++ b/crates/uv/tests/it/python_upgrade.rs @@ -52,6 +52,17 @@ fn python_upgrade() { ----- stderr ----- "); + + // Should reinstall on `--reinstall` + uv_snapshot!(context.filters(), context.python_upgrade().arg("--preview").arg("3.10").arg("--reinstall"), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Installed Python 3.10.18 in [TIME] + ~ cpython-3.10.18-[PLATFORM] (python3.10) + "); } #[test] diff --git a/docs/reference/cli.md b/docs/reference/cli.md index b378067fb..10c9831ea 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -2970,6 +2970,8 @@ uv python upgrade [OPTIONS] [TARGETS]...

Note that currently, only local paths are supported.

May also be set with the UV_PYTHON_DOWNLOADS_JSON_URL environment variable.

--quiet, -q

Use quiet output.

Repeating this option, e.g., -qq, will enable a silent mode in which uv will write no output to stdout.

+
--reinstall, -r

Reinstall the latest Python patch, if it's already installed.

+

By default, uv will exit successfully if the latest patch is already installed.

--verbose, -v

Use verbose output.

You can configure fine-grained logging using the RUST_LOG environment variable. (https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives)