from __future__ import annotations import sys from typing import TYPE_CHECKING, Any, override from .App import App as Base if TYPE_CHECKING: from argparse import ArgumentParser from .ExecContext import ExecContext class ExecApp(Base): # export def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) self.__opt_interactive: bool | None = None self.__opt_verbose: bool | None = None self.__exec_context: ExecContext | None = None @override async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None: if self.__exec_context is not None: await self.__exec_context.close() self.__exec_context = None # -- Close the app (async runner, event loop) after the exec context, # which may still need them. await super().__aexit__(exc_type, exc, tb) @override def _add_arguments(self, parser: ArgumentParser) -> None: super()._add_arguments(parser) parser.add_argument( '--interactive', choices = ['true', 'false', 'auto'], default = 'true', help = 'Wait for user input or try to proceed unattended', ) parser.add_argument( '--verbose', action = 'store_true', default = False, help = "Be verbose on stderr about what's being done on the distro level", ) parser.add_argument( '--target', default = 'local', help = 'Run commands on this host' ) @property def interactive(self) -> bool: if self.__opt_interactive is None: match self.args.interactive: case 'true': self.__opt_interactive = True case 'false': self.__opt_interactive = False case 'auto': self.__opt_interactive = sys.stdin.isatty() case _: raise ValueError( f'Unknown --interactive value: {self.args.interactive}' ) # Not logically possible to fail, but this keeps pyright happy assert self.__opt_interactive is not None return self.__opt_interactive @property def verbose(self) -> bool: if self.__opt_verbose is None: self.__opt_verbose = self.args.verbose # Not logically possible to fail, but this keeps pyright happy assert self.__opt_verbose is not None return self.__opt_verbose @property def exec_context(self) -> ExecContext: if self.__exec_context is None: from .ExecContext import ExecContext self.__exec_context = ExecContext.create( self.args.target, interactive = self.interactive, verbose_default = self.verbose, ) return self.__exec_context