Source code for nexusLIMS.tui.apps.config.app

"""
NexusLIMS Configuration TUI Application.

Provides an interactive terminal UI for editing the NexusLIMS ``.env``
configuration file.  Launched via ``nexuslims config edit``.
"""

from pathlib import Path
from typing import ClassVar

from nexusLIMS.tui.common.base_app import BaseNexusApp, HelpScreen


[docs] class ConfiguratorApp(BaseNexusApp): """ TUI application for interactively editing NexusLIMS configuration. Reads the current ``.env`` file, presents all settings in a tabbed form, validates input, and writes a new ``.env`` on save. No database connection is required, so ``on_mount`` skips the DB session setup from :class:`~nexusLIMS.tui.common.base_app.BaseNexusApp`. Parameters ---------- env_path : pathlib.Path | str Path to the ``.env`` file to edit. The file is created (empty) if it does not yet exist. Defaults to ``".env"`` in the current directory. """ CSS_PATH: ClassVar = [ *BaseNexusApp.CSS_PATH, ] def __init__(self, env_path: Path | str = ".env", **kwargs): """Initialize the configurator app.""" self._env_path = Path(env_path) super().__init__(**kwargs) # Prevent BaseNexusApp.on_mount from creating a DB session. # Textual dispatches on_mount to every handler in the MRO; setting a # non-None falsy sentinel makes the base-class guard (`if self.db_session # is None`) evaluate to False while `on_unmount`'s `if self.db_session:` # check also stays False, so no .close() is called on a non-Session. self.db_session = False # type: ignore[assignment] @property def env_path(self) -> Path: """Return the path to the .env file being edited.""" return self._env_path
[docs] def on_mount(self) -> None: """Push the config screen (no database session needed).""" # Intentionally skip super().on_mount() to avoid creating a DB session self.title = f"NexusLIMS Configurator — {self._env_path}" from nexusLIMS.tui.apps.config.screens import ConfigScreen # noqa: PLC0415 self.push_screen(ConfigScreen(self._env_path))
[docs] def get_app_name(self) -> str: """Return application name for the help screen.""" return "NexusLIMS Configurator"
_HELP_DESCRIPTION = ( "The NexusLIMS Configurator reads and writes a `.env` file that controls " "all NexusLIMS settings. On launch it loads the existing file (if present) " "and pre-populates every field. Pressing **Save (Ctrl+S)** writes a new " "`.env` at the same path, overwriting the previous contents. Pressing " "**Cancel (Esc)** exits without saving — you will be warned if there are " "unsaved changes.\n\n" "Settings are grouped into tabs: **Core Paths**, **CDCS**, " "**File Processing**, **NEMO Harvesters**, **eLabFTW**, **Email**, and " "**SSL / Certs**. Focus any input field and press **F1** to read extended " "documentation for that field." )
[docs] def action_help(self) -> None: """Show the configurator help screen with app description.""" self.push_screen( HelpScreen( app_name=self.get_app_name(), keybindings=self.get_keybindings(), description=self._HELP_DESCRIPTION, ) )
[docs] def get_keybindings(self) -> list[tuple[str, str]]: """Return app-specific keybindings for the help screen.""" app_bindings: list[tuple[str, str]] = [ ("f1", "Show extended help for the focused field"), ("ctrl+s", "Save configuration to .env file"), ("escape", "Cancel / go back"), ("tab / shift+tab", "Move between fields"), ("< / >", "Navigate to previous / next tab"), ] return app_bindings + super().get_keybindings()