diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 34c2575b9d0e9..af04737ece040 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 3a2d5c1294733..5f2399219d723 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 ad26eeaa9e95e..f21ffdbb21c95 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 bf6d45e08998f..860b3395c6cfa 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 b378067fb94c3..10c9831eac1db 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)