aboutsummaryrefslogtreecommitdiff
path: root/app/backends/common.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/backends/common.py')
-rw-r--r--app/backends/common.py23
1 files changed, 18 insertions, 5 deletions
diff --git a/app/backends/common.py b/app/backends/common.py
index cb573c3..10b4ccf 100644
--- a/app/backends/common.py
+++ b/app/backends/common.py
@@ -71,6 +71,18 @@ def drain_post_tui_notices() -> List[str]:
return notices
+def cancel_requested(cancel) -> bool:
+ """True when CANCEL (a ``threading.Event``) is given and set.
+
+ Shared guard for the multi-phase uninstall actions: cancellation is
+ honored only between phases (stop servers / pip / delete files), so a
+ phase that already started always runs to completion and an uninstall
+ never tears halfway. Callers return 130 when this fires before a
+ pending phase.
+ """
+ return cancel is not None and cancel.is_set()
+
+
def normalize_dir_arg(value: str) -> Path:
"""Normalize a user-supplied path argument.
@@ -301,8 +313,7 @@ def run_console_subprocess(argv: List[str], cwd: Optional[Path] = None,
"""Run a subprocess, streaming output to the console or to EMIT.
With EMIT None the child inherits the real terminal and its output
- appears normally (used by the non-interactive CLI paths and the quick
- ``tui.suspend`` actions like uninstall). With EMIT given (a
+ appears normally (the non-interactive CLI paths). With EMIT given (a
``callable(str)``) the child's stdout/stderr are merged, read line by
line (splitting on both ``\\n`` and ``\\r`` so carriage-return progress
updates like git's or tqdm's surface as lines), and each line is passed
@@ -459,11 +470,13 @@ def pip_install(packages: List[str]) -> int:
return envs.pip_install(packages)
-def pip_uninstall(packages: List[str]) -> int:
+def pip_uninstall(packages: List[str], *, emit=None) -> int:
"""pip uninstall PACKAGES from the managed venv. Returns exit code.
Delegates to ``backends.envs.pip_uninstall`` (local import to avoid a
- circular import). Used by the backends' ``uninstall`` action.
+ circular import). Used by the backends' ``uninstall`` action. With EMIT
+ given (the in-TUI task view) pip runs piped, streaming into EMIT, so
+ its output never touches the terminal behind curses.
"""
from backends import envs
- return envs.pip_uninstall(packages)
+ return envs.pip_uninstall(packages, emit=emit)