# [MODULE_PATH] superset_tool.utils.whiptail_fallback # [FILE] whiptail_fallback.py # [SEMANTICS] ui, fallback, console, utils, non‑interactive # -------------------------------------------------------------- # [IMPORTS] # -------------------------------------------------------------- import sys from typing import List, Tuple, Optional, Any # [END_IMPORTS] # -------------------------------------------------------------- # [ENTITY: Service('ConsoleUI')] # -------------------------------------------------------------- """ :purpose: Плотный консольный UI‑fallback для всех функций, которые в оригинальном проекте использовали ``whiptail``. Всё взаимодействие теперь **не‑интерактивно**: функции, выводящие сообщение, просто печатают его без ожидания ``Enter``. """ def menu( title: str, prompt: str, choices: List[str], backtitle: str = "Superset Migration Tool", ) -> Tuple[int, Optional[str]]: """Return (rc, selected item). rc == 0 → OK.""" print(f"\n=== {title} ===") print(prompt) for idx, item in enumerate(choices, 1): print(f"{idx}) {item}") try: raw = input("\nВведите номер (0 – отмена): ").strip() sel = int(raw) if sel == 0: return 1, None return 0, choices[sel - 1] except Exception: return 1, None def checklist( title: str, prompt: str, options: List[Tuple[str, str]], backtitle: str = "Superset Migration Tool", ) -> Tuple[int, List[str]]: """Return (rc, list of selected **values**).""" print(f"\n=== {title} ===") print(prompt) for idx, (val, label) in enumerate(options, 1): print(f"{idx}) [{val}] {label}") raw = input("\nВведите номера через запятую (пустой ввод → отказ): ").strip() if not raw: return 1, [] try: indices = {int(x) for x in raw.split(",") if x.strip()} selected = [options[i - 1][0] for i in indices if 0 < i <= len(options)] return 0, selected except Exception: return 1, [] def yesno( title: str, question: str, backtitle: str = "Superset Migration Tool", ) -> bool: """True → пользователь ответил «да». """ ans = input(f"\n=== {title} ===\n{question} (y/n): ").strip().lower() return ans in ("y", "yes", "да", "д") def msgbox( title: str, msg: str, width: int = 60, height: int = 15, backtitle: str = "Superset Migration Tool", ) -> None: """Простой вывод сообщения – без ожидания Enter.""" print(f"\n=== {title} ===\n{msg}\n") # **Убрано:** input("Нажмите для продолжения...") def inputbox( title: str, prompt: str, backtitle: str = "Superset Migration Tool", ) -> Tuple[int, Optional[str]]: """Return (rc, введённая строка). rc == 0 → успешно.""" print(f"\n=== {title} ===") val = input(f"{prompt}\n") if val == "": return 1, None return 0, val # -------------------------------------------------------------- # [ENTITY: Service('ConsoleGauge')] # -------------------------------------------------------------- """ :purpose: Минимальная имитация ``whiptail``‑gauge в консоли. """ class _ConsoleGauge: """Контекст‑менеджер для простого прогресс‑бара.""" def __init__(self, title: str, width: int = 60, height: int = 10): self.title = title self.width = width self.height = height self._percent = 0 def __enter__(self): print(f"\n=== {self.title} ===") return self def __exit__(self, exc_type, exc_val, exc_tb): sys.stdout.write("\n") sys.stdout.flush() def set_text(self, txt: str) -> None: sys.stdout.write(f"\r{txt} ") sys.stdout.flush() def set_percent(self, percent: int) -> None: self._percent = percent sys.stdout.write(f"{percent}%") sys.stdout.flush() # [END_ENTITY] def gauge( title: str, width: int = 60, height: int = 10, ) -> Any: """Always returns the console fallback gauge.""" return _ConsoleGauge(title, width, height) # [END_ENTITY] # -------------------------------------------------------------- # [END_FILE whiptail_fallback.py] # --------------------------------------------------------------