From b7167dc4d829c88baf8dc599f7f8cfad98a7df1c Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Tue, 11 Mar 2025 18:53:28 -0500 Subject: [PATCH] Fix `uv python install --reinstall` when the version is not yet installed (#12124) I noticed this was failing to perform the install --- crates/uv/src/commands/python/install.rs | 13 ++++++---- crates/uv/tests/it/python_install.rs | 31 ++++++++++++++++-------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/crates/uv/src/commands/python/install.rs b/crates/uv/src/commands/python/install.rs index 799e3c6e5..477f38d7d 100644 --- a/crates/uv/src/commands/python/install.rs +++ b/crates/uv/src/commands/python/install.rs @@ -205,15 +205,17 @@ pub(crate) async fn install( Vec::with_capacity(existing_installations.len() + requests.len()); for request in &requests { - if existing_installations.is_empty() { + let mut matching_installations = existing_installations + .iter() + .filter(|installation| request.matches_installation(installation)) + .peekable(); + + if matching_installations.peek().is_none() { debug!("No installation found for request `{}`", request.cyan()); unsatisfied.push(Cow::Borrowed(request)); } - for installation in existing_installations - .iter() - .filter(|installation| request.matches_installation(installation)) - { + for installation in matching_installations { changelog.existing.insert(installation.key().clone()); if matches!(&request.request, &PythonRequest::Any) { // Construct a install request matching the existing installation @@ -300,6 +302,7 @@ pub(crate) async fn install( .build(); let reporter = PythonDownloadReporter::new(printer, downloads.len() as u64); let mut tasks = FuturesUnordered::new(); + for download in &downloads { tasks.push(async { ( diff --git a/crates/uv/tests/it/python_install.rs b/crates/uv/tests/it/python_install.rs index aedcc399f..fbc945e46 100644 --- a/crates/uv/tests/it/python_install.rs +++ b/crates/uv/tests/it/python_install.rs @@ -99,7 +99,7 @@ fn python_reinstall() { .with_managed_python_dirs(); // Install a couple versions - uv_snapshot!(context.filters(), context.python_install().arg("3.12").arg("3.13"), @r###" + uv_snapshot!(context.filters(), context.python_install().arg("3.12").arg("3.13"), @r" success: true exit_code: 0 ----- stdout ----- @@ -108,10 +108,10 @@ fn python_reinstall() { Installed 2 versions in [TIME] + cpython-3.12.9-[PLATFORM] + cpython-3.13.2-[PLATFORM] - "###); + "); // Reinstall a single version - uv_snapshot!(context.filters(), context.python_install().arg("3.13").arg("--reinstall"), @r###" + uv_snapshot!(context.filters(), context.python_install().arg("3.13").arg("--reinstall"), @r" success: true exit_code: 0 ----- stdout ----- @@ -119,10 +119,10 @@ fn python_reinstall() { ----- stderr ----- Installed Python 3.13.2 in [TIME] ~ cpython-3.13.2-[PLATFORM] - "###); + "); // Reinstall multiple versions - uv_snapshot!(context.filters(), context.python_install().arg("--reinstall"), @r###" + uv_snapshot!(context.filters(), context.python_install().arg("--reinstall"), @r" success: true exit_code: 0 ----- stdout ----- @@ -131,7 +131,18 @@ fn python_reinstall() { Installed 2 versions in [TIME] ~ cpython-3.12.9-[PLATFORM] ~ cpython-3.13.2-[PLATFORM] - "###); + "); + + // Reinstalling a version that is not installed should also work + uv_snapshot!(context.filters(), context.python_install().arg("3.11").arg("--reinstall"), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Installed Python 3.11.11 in [TIME] + + cpython-3.11.11-[PLATFORM] + "); } #[test] @@ -142,7 +153,7 @@ fn python_reinstall_patch() { .with_managed_python_dirs(); // Install a couple patch versions - uv_snapshot!(context.filters(), context.python_install().arg("3.12.6").arg("3.12.7"), @r###" + uv_snapshot!(context.filters(), context.python_install().arg("3.12.6").arg("3.12.7"), @r" success: true exit_code: 0 ----- stdout ----- @@ -151,12 +162,12 @@ fn python_reinstall_patch() { Installed 2 versions in [TIME] + cpython-3.12.6-[PLATFORM] + cpython-3.12.7-[PLATFORM] - "###); + "); // Reinstall all "3.12" versions // TODO(zanieb): This doesn't work today, because we need this to install the "latest" as there // is no workflow for `--upgrade` yet - uv_snapshot!(context.filters(), context.python_install().arg("3.12").arg("--reinstall"), @r###" + uv_snapshot!(context.filters(), context.python_install().arg("3.12").arg("--reinstall"), @r" success: true exit_code: 0 ----- stdout ----- @@ -164,7 +175,7 @@ fn python_reinstall_patch() { ----- stderr ----- Installed Python 3.12.9 in [TIME] + cpython-3.12.9-[PLATFORM] - "###); + "); } #[test]