refactor, add db search

This commit is contained in:
2025-12-15 19:18:17 +03:00
parent e6346612c4
commit d3395d55c3
24 changed files with 1582 additions and 32542 deletions

View File

@@ -1,20 +1,21 @@
# <GRACE_MODULE id="superset_tool.utils.whiptail_fallback" name="whiptail_fallback.py">
# @SEMANTICS: ui, fallback, console, utility, interactive
# @PURPOSE: Предоставляет плотный консольный UI-fallback для интерактивных диалогов, имитируя `whiptail` для систем, где он недоступен.
# [DEF:superset_tool.utils.whiptail_fallback:Module]
#
# @SEMANTICS: ui, fallback, console, utility, interactive
# @PURPOSE: Предоставляет плотный консольный UI-fallback для интерактивных диалогов, имитируя `whiptail` для систем, где он недоступен.
# @LAYER: UI
# @PUBLIC_API: menu, checklist, yesno, msgbox, inputbox, gauge
# <IMPORTS>
# [SECTION: IMPORTS]
import sys
from typing import List, Tuple, Optional, Any
# </IMPORTS>
# [/SECTION]
# --- Начало кода модуля ---
# <ANCHOR id="menu" type="Function">
# @PURPOSE: Отображает меню выбора и возвращает выбранный элемент.
# @PARAM: title: str - Заголовок меню.
# @PARAM: prompt: str - Приглашение к вводу.
# @PARAM: choices: List[str] - Список вариантов для выбора.
# @RETURN: Tuple[int, Optional[str]] - Кортеж (код возврата, выбранный элемент). rc=0 - успех.
# [DEF:menu:Function]
# @PURPOSE: Отображает меню выбора и возвращает выбранный элемент.
# @PARAM: title (str) - Заголовок меню.
# @PARAM: prompt (str) - Приглашение к вводу.
# @PARAM: choices (List[str]) - Список вариантов для выбора.
# @RETURN: Tuple[int, Optional[str]] - Кортеж (код возврата, выбранный элемент). rc=0 - успех.
def menu(title: str, prompt: str, choices: List[str], **kwargs) -> Tuple[int, Optional[str]]:
print(f"\n=== {title} ===\n{prompt}")
for idx, item in enumerate(choices, 1):
@@ -25,14 +26,14 @@ def menu(title: str, prompt: str, choices: List[str], **kwargs) -> Tuple[int, Op
return (0, choices[sel - 1]) if 0 < sel <= len(choices) else (1, None)
except (ValueError, IndexError):
return 1, None
# </ANCHOR id="menu">
# [/DEF:menu]
# <ANCHOR id="checklist" type="Function">
# @PURPOSE: Отображает список с возможностью множественного выбора.
# @PARAM: title: str - Заголовок.
# @PARAM: prompt: str - Приглашение к вводу.
# @PARAM: options: List[Tuple[str, str]] - Список кортежей (значение, метка).
# @RETURN: Tuple[int, List[str]] - Кортеж (код возврата, список выбранных значений).
# [DEF:checklist:Function]
# @PURPOSE: Отображает список с возможностью множественного выбора.
# @PARAM: title (str) - Заголовок.
# @PARAM: prompt (str) - Приглашение к вводу.
# @PARAM: options (List[Tuple[str, str]]) - Список кортежей (значение, метка).
# @RETURN: Tuple[int, List[str]] - Кортеж (код возврата, список выбранных значений).
def checklist(title: str, prompt: str, options: List[Tuple[str, str]], **kwargs) -> Tuple[int, List[str]]:
print(f"\n=== {title} ===\n{prompt}")
for idx, (val, label) in enumerate(options, 1):
@@ -45,40 +46,39 @@ def checklist(title: str, prompt: str, options: List[Tuple[str, str]], **kwargs)
return 0, selected_values
except (ValueError, IndexError):
return 1, []
# </ANCHOR id="checklist">
# [/DEF:checklist]
# <ANCHOR id="yesno" type="Function">
# @PURPOSE: Задает вопрос с ответом да/нет.
# @PARAM: title: str - Заголовок.
# @PARAM: question: str - Вопрос для пользователя.
# @RETURN: bool - `True`, если пользователь ответил "да".
# [DEF:yesno:Function]
# @PURPOSE: Задает вопрос с ответом да/нет.
# @PARAM: title (str) - Заголовок.
# @PARAM: question (str) - Вопрос для пользователя.
# @RETURN: bool - `True`, если пользователь ответил "да".
def yesno(title: str, question: str, **kwargs) -> bool:
ans = input(f"\n=== {title} ===\n{question} (y/n): ").strip().lower()
return ans in ("y", "yes", "да", "д")
# </ANCHOR id="yesno">
# [/DEF:yesno]
# <ANCHOR id="msgbox" type="Function">
# @PURPOSE: Отображает информационное сообщение.
# @PARAM: title: str - Заголовок.
# @PARAM: msg: str - Текст сообщения.
# [DEF:msgbox:Function]
# @PURPOSE: Отображает информационное сообщение.
# @PARAM: title (str) - Заголовок.
# @PARAM: msg (str) - Текст сообщения.
def msgbox(title: str, msg: str, **kwargs) -> None:
print(f"\n=== {title} ===\n{msg}\n")
# </ANCHOR id="msgbox">
# [/DEF:msgbox]
# <ANCHOR id="inputbox" type="Function">
# @PURPOSE: Запрашивает у пользователя текстовый ввод.
# @PARAM: title: str - Заголовок.
# @PARAM: prompt: str - Приглашение к вводу.
# @RETURN: Tuple[int, Optional[str]] - Кортеж (код возврата, введенная строка).
# [DEF:inputbox:Function]
# @PURPOSE: Запрашивает у пользователя текстовый ввод.
# @PARAM: title (str) - Заголовок.
# @PARAM: prompt (str) - Приглашение к вводу.
# @RETURN: Tuple[int, Optional[str]] - Кортеж (код возврата, введенная строка).
def inputbox(title: str, prompt: str, **kwargs) -> Tuple[int, Optional[str]]:
print(f"\n=== {title} ===")
val = input(f"{prompt}\n")
return (0, val) if val else (1, None)
# </ANCHOR id="inputbox">
# [/DEF:inputbox]
# <ANCHOR id="_ConsoleGauge" type="Class">
# @PURPOSE: Контекстный менеджер для имитации `whiptail gauge` в консоли.
# @INTERNAL
# [DEF:_ConsoleGauge:Class]
# @PURPOSE: Контекстный менеджер для имитации `whiptail gauge` в консоли.
class _ConsoleGauge:
def __init__(self, title: str, **kwargs):
self.title = title
@@ -91,16 +91,14 @@ class _ConsoleGauge:
sys.stdout.write(f"\r{txt} "); sys.stdout.flush()
def set_percent(self, percent: int) -> None:
sys.stdout.write(f"{percent}%"); sys.stdout.flush()
# </ANCHOR id="_ConsoleGauge">
# [/DEF:_ConsoleGauge]
# <ANCHOR id="gauge" type="Function">
# @PURPOSE: Создает и возвращает экземпляр `_ConsoleGauge`.
# @PARAM: title: str - Заголовок для индикатора прогресса.
# @RETURN: _ConsoleGauge - Экземпляр контекстного менеджера.
# [DEF:gauge:Function]
# @PURPOSE: Создает и возвращает экземпляр `_ConsoleGauge`.
# @PARAM: title (str) - Заголовок для индикатора прогресса.
# @RETURN: _ConsoleGauge - Экземпляр контекстного менеджера.
def gauge(title: str, **kwargs) -> _ConsoleGauge:
return _ConsoleGauge(title, **kwargs)
# </ANCHOR id="gauge">
# [/DEF:gauge]
# --- Конец кода модуля ---
# </GRACE_MODULE id="superset_tool.utils.whiptail_fallback">
# [/DEF:superset_tool.utils.whiptail_fallback]