148 lines
4.6 KiB
Python
148 lines
4.6 KiB
Python
# [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("Нажмите <Enter> для продолжения...")
|
||
|
||
|
||
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]
|
||
# -------------------------------------------------------------- |