Skip to content

Commit

Permalink
Display Python executables on uninstall
Browse files Browse the repository at this point in the history
  • Loading branch information
zanieb committed Dec 3, 2024
1 parent 63443f1 commit 366ec72
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 24 deletions.
9 changes: 6 additions & 3 deletions crates/uv/src/commands/python/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ pub(crate) async fn install(
}

for event in changelog.events() {
let executables = format_executables(&event, &changelog);
let executables = format_executables(&event, &changelog.installed_executables);
match event.kind {
ChangeEventKind::Added => {
writeln!(
Expand Down Expand Up @@ -554,8 +554,11 @@ pub(crate) async fn install(
Ok(ExitStatus::Success)
}

fn format_executables(event: &ChangeEvent, changelog: &Changelog) -> String {
let Some(installed) = changelog.installed_executables.get(&event.key) else {
pub(crate) fn format_executables(
event: &ChangeEvent,
executables: &FxHashMap<PythonInstallationKey, FxHashSet<PathBuf>>,
) -> String {
let Some(installed) = executables.get(&event.key) else {
return String::new();
};

Expand Down
45 changes: 29 additions & 16 deletions crates/uv/src/commands/python/uninstall.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
use std::collections::BTreeSet;
use std::fmt::Write;
use std::path::PathBuf;

use anyhow::Result;
use futures::stream::FuturesUnordered;
use futures::StreamExt;
use itertools::Itertools;
use owo_colors::OwoColorize;

use rustc_hash::{FxHashMap, FxHashSet};
use tracing::{debug, warn};
use uv_fs::Simplified;
use uv_python::downloads::PythonDownloadRequest;
use uv_python::managed::{python_executable_dir, ManagedPythonInstallations};
use uv_python::PythonRequest;
use uv_python::{PythonInstallationKey, PythonRequest};

use crate::commands::python::install::format_executables;
use crate::commands::python::{ChangeEvent, ChangeEventKind};
use crate::commands::{elapsed, ExitStatus};
use crate::printer::Printer;
Expand Down Expand Up @@ -123,8 +126,10 @@ async fn do_uninstall(
return Ok(ExitStatus::Failure);
}

// Collect files in a directory
let executables = python_executable_dir()?
// Find and remove all relevant Python executables
let mut uninstalled_executables: FxHashMap<PythonInstallationKey, FxHashSet<PathBuf>> =
FxHashMap::default();
for executable in python_executable_dir()?
.read_dir()
.into_iter()
.flatten()
Expand All @@ -148,17 +153,25 @@ async fn do_uninstall(
|| name == Some(&installation.key().executable_name())
})
})
// Only include Python executables that match the installations
.filter(|path| {
matching_installations
.iter()
.any(|installation| installation.is_bin_link(path.as_path()))
})
.collect::<BTreeSet<_>>();
.sorted()
{
let Some(installation) = matching_installations
.iter()
.find(|installation| installation.is_bin_link(executable.as_path()))
else {
continue;
};

for executable in &executables {
fs_err::remove_file(executable)?;
debug!("Removed {}", executable.user_display());
fs_err::remove_file(&executable)?;
debug!(
"Removed `{}` for `{}`",
executable.simplified_display(),
installation.key()
);
uninstalled_executables
.entry(installation.key().clone())
.or_default()
.insert(executable);
}

let mut tasks = FuturesUnordered::new();
Expand Down Expand Up @@ -218,15 +231,15 @@ async fn do_uninstall(
})
.sorted_unstable_by(|a, b| a.key.cmp(&b.key).then_with(|| a.kind.cmp(&b.kind)))
{
let executables = format_executables(&event, &uninstalled_executables);
match event.kind {
// TODO(zanieb): Track removed executables and report them all here
ChangeEventKind::Removed => {
writeln!(
printer.stderr(),
" {} {} ({})",
" {} {}{}",
"-".red(),
event.key.bold(),
event.key.executable_name_minor()
executables,
)?;
}
_ => unreachable!(),
Expand Down
10 changes: 5 additions & 5 deletions crates/uv/tests/it/python_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ fn python_install() {
----- stderr -----
Searching for Python versions matching: Python 3.13
Uninstalled Python 3.13.0 in [TIME]
- cpython-3.13.0-[PLATFORM] (python3.13)
- cpython-3.13.0-[PLATFORM]
"###);
}

Expand Down Expand Up @@ -222,7 +222,7 @@ fn python_install_preview() {
----- stderr -----
Searching for Python versions matching: Python 3.13
Uninstalled Python 3.13.0 in [TIME]
- cpython-3.13.0-[PLATFORM] (python3.13)
- cpython-3.13.0-[PLATFORM] (python, python3, python3.13)
"###);

// The executable should be removed
Expand Down Expand Up @@ -437,7 +437,7 @@ fn python_install_freethreaded() {
----- stderr -----
Searching for Python installations
Uninstalled 2 versions in [TIME]
- cpython-3.13.0-[PLATFORM] (python3.13)
- cpython-3.13.0-[PLATFORM]
- cpython-3.13.0+freethreaded-[PLATFORM] (python3.13t)
"###);
}
Expand Down Expand Up @@ -551,7 +551,7 @@ fn python_install_default() {
----- stderr -----
Searching for Python installations
Uninstalled Python 3.13.0 in [TIME]
- cpython-3.13.0-[PLATFORM] (python3.13)
- cpython-3.13.0-[PLATFORM] (python, python3, python3.13)
"###);

// The executables should be removed
Expand Down Expand Up @@ -584,7 +584,7 @@ fn python_install_default() {
----- stderr -----
Searching for Python versions matching: Python 3.13
Uninstalled Python 3.13.0 in [TIME]
- cpython-3.13.0-[PLATFORM] (python3.13)
- cpython-3.13.0-[PLATFORM] (python, python3, python3.13)
"###);

// We should remove all the executables
Expand Down

0 comments on commit 366ec72

Please sign in to comment.