feat: update version and dependencies in setup.py; add privilege management and process handling modules
- Updated version from 2026.05.31 to 2026.06.11 in setup.py - Replaced 'textual' with 'rich' in install_requires - Added privilege.py for managing sudo privileges with a keep-alive mechanism - Introduced process.py for handling subprocesses with enhanced control and output streaming - Created ui.py for unified console interactions and user prompts
This commit is contained in:
+28
-77
@@ -3,11 +3,10 @@ from __future__ import annotations
|
||||
import argparse
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
from typing import List
|
||||
|
||||
from textual.app import App
|
||||
|
||||
from cobot.tui import SCREEN_CSS, LogScreen, MultiPickScreen
|
||||
from cobot import ui
|
||||
from cobot.ui import header, done
|
||||
|
||||
_PROJECT_DIR = Path(__file__).parent.parent.parent
|
||||
|
||||
@@ -19,80 +18,21 @@ _DIR_MAP = {
|
||||
}
|
||||
|
||||
|
||||
def _task_clean(screen: LogScreen, dirs: List[str]) -> None:
|
||||
"""Delete the selected top-level directories.
|
||||
Удаляет выбранные директории верхнего уровня.
|
||||
def _clean(dirs: List[str]) -> None:
|
||||
"""Delete the selected top-level directories, printing the outcome of each.
|
||||
Удаляет выбранные директории верхнего уровня, печатая результат по каждой.
|
||||
"""
|
||||
try:
|
||||
screen.write("[bold]Cleaning build artifacts[/bold]\n")
|
||||
total = len(dirs)
|
||||
for i, label in enumerate(dirs):
|
||||
if screen.is_stopped():
|
||||
return
|
||||
screen.set_progress(i / total * 100, f"Removing {label}...")
|
||||
path = _DIR_MAP[label]
|
||||
if path.exists():
|
||||
shutil.rmtree(path)
|
||||
screen.write(f"[green][ok][/green] Removed {label}")
|
||||
else:
|
||||
screen.write(f"[dim]Not found: {label}[/dim]")
|
||||
|
||||
if not screen.is_stopped():
|
||||
screen.set_progress(100, "Done")
|
||||
screen.write("\n[green]Done.[/green]")
|
||||
screen.finish(True)
|
||||
|
||||
except Exception as exc:
|
||||
if not screen.is_stopped():
|
||||
screen.write(f"\n[red]Error:[/red] {exc}")
|
||||
screen.finish(False)
|
||||
|
||||
|
||||
class _CleanApp(App[None]):
|
||||
"""Clean wizard: lets the user pick which directories to delete, then removes them.
|
||||
Мастер очистки: позволяет выбрать директории для удаления, затем удаляет их.
|
||||
"""
|
||||
|
||||
CSS = SCREEN_CSS
|
||||
|
||||
def __init__(self, all_dirs: bool):
|
||||
super().__init__()
|
||||
# True = skip the question and delete everything right away.
|
||||
# True = пропустить вопрос и сразу удалить всё.
|
||||
self._all_dirs = all_dirs
|
||||
|
||||
def on_mount(self) -> None:
|
||||
if self._all_dirs:
|
||||
self._start(_DIR_OPTIONS)
|
||||
header("Очистка артефактов сборки")
|
||||
removed = False
|
||||
for label in dirs:
|
||||
path = _DIR_MAP[label]
|
||||
if path.exists():
|
||||
shutil.rmtree(path)
|
||||
ui.info(f" [green]✓[/green] Удалено {label}")
|
||||
removed = True
|
||||
else:
|
||||
self._ask_dirs()
|
||||
|
||||
def _ask_dirs(self) -> None:
|
||||
self.push_screen(
|
||||
MultiPickScreen(
|
||||
"clean",
|
||||
"Which directories to delete?",
|
||||
_DIR_OPTIONS,
|
||||
note="Space — toggle · Enter — confirm",
|
||||
),
|
||||
self._got_dirs,
|
||||
)
|
||||
|
||||
def _got_dirs(self, dirs: Optional[List[str]]) -> None:
|
||||
if not dirs:
|
||||
self.exit()
|
||||
return
|
||||
self._start(dirs)
|
||||
|
||||
def _start(self, dirs: List[str]) -> None:
|
||||
self.push_screen(
|
||||
LogScreen(
|
||||
"Cleaning",
|
||||
lambda s: _task_clean(s, dirs),
|
||||
show_progress=True,
|
||||
),
|
||||
lambda _: self.exit(),
|
||||
)
|
||||
ui.info(f" [dim]Нет:[/dim] {label}")
|
||||
done(True, "Очищено" if removed else "Нечего удалять")
|
||||
|
||||
|
||||
def register(subparsers: argparse._SubParsersAction) -> None:
|
||||
@@ -114,4 +54,15 @@ def run(args: argparse.Namespace) -> None:
|
||||
"""Entry point for the clean command.
|
||||
Точка входа для команды clean.
|
||||
"""
|
||||
_CleanApp(all_dirs=(getattr(args, "target", None) == "all")).run()
|
||||
if getattr(args, "target", None) == "all":
|
||||
_clean(_DIR_OPTIONS)
|
||||
return
|
||||
|
||||
dirs = ui.multiselect(
|
||||
"Какие директории удалить?",
|
||||
_DIR_OPTIONS,
|
||||
note="Space — отметить · Enter — подтвердить",
|
||||
)
|
||||
if not dirs:
|
||||
return
|
||||
_clean(dirs)
|
||||
|
||||
Reference in New Issue
Block a user