Decouple non-UI CLI startup from config_ui
Stop aman.py from importing the GTK settings module at module load so version, init, bench, diagnostics, and top-level help can start without pulling in the UI stack.\n\nPromote PyGObject and python-xlib into main project dependencies, switch the documented source install surface to plain uv/pip commands, and teach the portable, deb, and Arch packaging flows to install filtered runtime requirements before the Aman wheel so they still rely on distro-provided GTK/X11 packages.\n\nAdd regression coverage for importing aman with config_ui blocked and for the portable bundle's new requirements payload, then rerun the focused CLI/diagnostics/portable tests plus py_compile.
This commit is contained in:
parent
b4a3d446fa
commit
721248ca26
15 changed files with 173 additions and 35 deletions
37
src/aman.py
37
src/aman.py
|
|
@ -21,7 +21,6 @@ from typing import Any
|
|||
from aiprocess import LlamaProcessor
|
||||
from config import Config, ConfigValidationError, load, redacted_dict, save, validate
|
||||
from constants import DEFAULT_CONFIG_PATH, MODEL_PATH, RECORD_TIMEOUT_SEC
|
||||
from config_ui import ConfigUiResult, run_config_ui, show_about_dialog, show_help_dialog
|
||||
from desktop import get_desktop_adapter
|
||||
from diagnostics import (
|
||||
doctor_command,
|
||||
|
|
@ -791,6 +790,30 @@ def _app_version() -> str:
|
|||
return "0.0.0-dev"
|
||||
|
||||
|
||||
def _load_config_ui_attr(attr_name: str) -> Any:
|
||||
try:
|
||||
from config_ui import __dict__ as config_ui_exports
|
||||
except ModuleNotFoundError as exc:
|
||||
missing_name = exc.name or "unknown"
|
||||
raise RuntimeError(
|
||||
"settings UI is unavailable because a required X11 Python dependency "
|
||||
f"is missing ({missing_name})"
|
||||
) from exc
|
||||
return config_ui_exports[attr_name]
|
||||
|
||||
|
||||
def _run_config_ui(*args, **kwargs):
|
||||
return _load_config_ui_attr("run_config_ui")(*args, **kwargs)
|
||||
|
||||
|
||||
def _show_help_dialog() -> None:
|
||||
_load_config_ui_attr("show_help_dialog")()
|
||||
|
||||
|
||||
def _show_about_dialog() -> None:
|
||||
_load_config_ui_attr("show_about_dialog")()
|
||||
|
||||
|
||||
def _read_json_file(path: Path) -> Any:
|
||||
if not path.exists():
|
||||
raise RuntimeError(f"file does not exist: {path}")
|
||||
|
|
@ -1446,8 +1469,8 @@ def _run_settings_required_tray(desktop, config_path: Path) -> bool:
|
|||
lambda: "settings_required",
|
||||
lambda: None,
|
||||
on_open_settings=open_settings_callback,
|
||||
on_show_help=show_help_dialog,
|
||||
on_show_about=show_about_dialog,
|
||||
on_show_help=_show_help_dialog,
|
||||
on_show_about=_show_about_dialog,
|
||||
on_open_config=lambda: logging.info("config path: %s", config_path),
|
||||
)
|
||||
return reopen_settings["value"]
|
||||
|
|
@ -1456,7 +1479,7 @@ def _run_settings_required_tray(desktop, config_path: Path) -> bool:
|
|||
def _run_settings_until_config_ready(desktop, config_path: Path, initial_cfg: Config) -> Config | None:
|
||||
draft_cfg = initial_cfg
|
||||
while True:
|
||||
result: ConfigUiResult = run_config_ui(
|
||||
result = _run_config_ui(
|
||||
draft_cfg,
|
||||
desktop,
|
||||
required=True,
|
||||
|
|
@ -1665,7 +1688,7 @@ def _run_command(args: argparse.Namespace) -> int:
|
|||
if daemon.get_state() != State.IDLE:
|
||||
logging.info("settings UI is available only while idle")
|
||||
return
|
||||
result = run_config_ui(
|
||||
result = _run_config_ui(
|
||||
cfg,
|
||||
desktop,
|
||||
required=False,
|
||||
|
|
@ -1740,8 +1763,8 @@ def _run_command(args: argparse.Namespace) -> int:
|
|||
daemon.get_state,
|
||||
lambda: shutdown("quit requested"),
|
||||
on_open_settings=open_settings_callback,
|
||||
on_show_help=show_help_dialog,
|
||||
on_show_about=show_about_dialog,
|
||||
on_show_help=_show_help_dialog,
|
||||
on_show_about=_show_about_dialog,
|
||||
is_paused_getter=daemon.is_paused,
|
||||
on_toggle_pause=daemon.toggle_paused,
|
||||
on_reload_config=reload_config_callback,
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ def _sounddevice():
|
|||
import sounddevice as sd # type: ignore[import-not-found]
|
||||
except ModuleNotFoundError as exc:
|
||||
raise RuntimeError(
|
||||
"sounddevice is not installed; install dependencies with `uv sync --extra x11`"
|
||||
"sounddevice is not installed; install dependencies with `uv sync`"
|
||||
) from exc
|
||||
return sd
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue