diff --git a/src/python/jw/pkg/lib/App.py b/src/python/jw/pkg/lib/App.py index 263938c2..b106b216 100644 --- a/src/python/jw/pkg/lib/App.py +++ b/src/python/jw/pkg/lib/App.py @@ -105,6 +105,47 @@ class App: # export eloop: asyncio.AbstractEventLoop | None = None, ) -> None: + from .Cmd import AbstractCmd + + self.__args: Namespace | None = None + self.__cmdline: str | None = None + self.__description = description + + self.__default_log_flags = self._default_log_flags( + LogFlag.STDERR | LogFlag.POSITION | LogFlag.PRIO | LogFlag.COLOR + ) + if (env := os.getenv(self._default_log_flags_env(), None)) is not None: + self.__default_log_flags = parse_log_flags(env) + + self.__default_log_level = self._default_log_level(NOTICE) + if (env := os.getenv(self._default_log_level_env(), None)) is not None: + self.__default_log_level = parse_log_level(env) + + self.__default_log_file = self._default_log_file(None) + if (env := os.getenv(self._default_log_file_env(), None)) is not None: + self.__default_log_file = env + + self.__back_trace = self._default_show_backtrace(False) + if (env := os.getenv(self._default_show_backtrace_env())) is not None: + self.__back_trace = env.lower() in ['1', 'true'] + + set_log_flags(self.__default_log_flags) + set_log_level(self.__default_log_level) + + self.__async_runner: AsyncRunner | None = None + self.__eloop = eloop + self.__own_eloop = False + + cmd_classes: LoadTypes[AbstractCmd] = LoadTypes( + modules if modules else ['__main__'], + type_name_filter = name_filter, + type_filter = [AbstractCmd], + ) + self.__cmds: list[AbstractCmd] = [cmd_class(self) for cmd_class in cmd_classes] + self._build_parser() + + def _build_parser(self, argv: list[str] | None = None) -> None: + def add_cmd_to_parser(cmd: AbstractCmd, parsers: Any) -> ArgumentParser: parser = cast( 'ArgumentParser', @@ -157,7 +198,7 @@ class App: # export sc.cmd, sc.parser, sc.cmd.children, all = all ) return - args, _ = self.__parser.parse_known_args() + args, _ = self.__parser.parse_known_args(argv) cmd_name = getattr(args, 'command', None) if cmd_name in scs: sc = scs[cmd_name] @@ -165,61 +206,27 @@ class App: # export from .Cmd import AbstractCmd - self.__args: Namespace | None = None - self.__cmdline: str | None = None - - self.__default_log_flags = self._default_log_flags( - LogFlag.STDERR | LogFlag.POSITION | LogFlag.PRIO | LogFlag.COLOR + cmdline = sys.argv if argv is None else argv + if argv is None: + argv = sys.argv[1:] + add_all_parsers = ( + '-h' in argv or '--help' in argv or '_ARGCOMPLETE' in os.environ ) - if (env := os.getenv(self._default_log_flags_env(), None)) is not None: - self.__default_log_flags = parse_log_flags(env) - - self.__default_log_level = self._default_log_level(NOTICE) - if (env := os.getenv(self._default_log_level_env(), None)) is not None: - self.__default_log_level = parse_log_level(env) - - self.__default_log_file = self._default_log_file(None) - if (env := os.getenv(self._default_log_file_env(), None)) is not None: - self.__default_log_file = env - - self.__back_trace = self._default_show_backtrace(False) - if (env := os.getenv(self._default_show_backtrace_env())) is not None: - self.__back_trace = env.lower() in ['1', 'true'] - - set_log_flags(self.__default_log_flags) - set_log_level(self.__default_log_level) - - self.__async_runner: AsyncRunner | None = None - self.__eloop = eloop - self.__own_eloop = False self.__parser = ArgumentParser( formatter_class = ArgumentDefaultsHelpFormatter, - description = description, + description = self.__description, add_help = False, ) self._add_arguments(self.__parser) - args, _ = self.__parser.parse_known_args() + args, _ = self.__parser.parse_known_args(argv) set_log_flags(args.log_flags) set_log_level(args.log_level) - log(DEBUG, f'-------------- Running: >{pretty_cmd(sys.argv)}<') + log(DEBUG, f'-------------- Running: >{pretty_cmd(cmdline)}<') - cmd_classes: LoadTypes[AbstractCmd] = LoadTypes( - modules if modules else ['__main__'], - type_name_filter = name_filter, - type_filter = [AbstractCmd], - ) - add_all_parsers = ( - '-h' in sys.argv or '--help' in sys.argv or '_ARGCOMPLETE' in os.environ - ) - add_cmds_to_parser( - self, - self.__parser, - [cmd_class(self) for cmd_class in cmd_classes], - all = add_all_parsers, - ) + add_cmds_to_parser(self, self.__parser, self.__cmds, all = add_all_parsers) # -- Add help only now, wouldn't want to have parse_known_args() exit # on --help with subcommands missing @@ -361,6 +368,8 @@ class App: # export self.__eloop = eloop self.__own_eloop = True try: + if argv is not None: + self._build_parser(argv) ret = self.eloop.run_until_complete(self.__run(argv)) finally: self.close()