diff --git a/tiramisu_cmdline_parser.py b/tiramisu_cmdline_parser.py index e4f8787..b4394ac 100644 --- a/tiramisu_cmdline_parser.py +++ b/tiramisu_cmdline_parser.py @@ -15,7 +15,7 @@ from typing import Union, List, Optional -from argparse import ArgumentParser, Namespace, SUPPRESS +from argparse import ArgumentParser, Namespace, SUPPRESS, _HelpAction from tiramisu.error import PropertiesOptionError try: from tiramisu import Config @@ -60,12 +60,30 @@ class TiramisuNamespace(Namespace): return super().__getattribute__(key) +class _TiramisuHelpAction(_HelpAction): + needs = False + def __call__(self, *args, **kwargs): + _TiramisuHelpAction.needs = True + + def display(self, parser): + _HelpAction.__call__(self, parser, None, None) + + class TiramisuCmdlineParser(ArgumentParser): def __init__(self, *args, + fullpath: bool=True, **kwargs): + self.fullpath = fullpath self.config = None super().__init__(*args, **kwargs) + self.register('action', 'help', _TiramisuHelpAction) + + def _pop_action_class(self, kwargs, default=None): + ret = super()._pop_action_class(kwargs, default) + if kwargs.get('action') != 'help' and kwargs.get('dest') != 'help': + return ret + return _TiramisuHelpAction def _match_arguments_partial(self, actions, @@ -83,6 +101,24 @@ class TiramisuCmdlineParser(ArgumentParser): actions.pop(0) return super()._match_arguments_partial(actions, arg_string_pattern) + def _parse_known_args(self, args=None, namespace=None): + + namespace_, args_ = super()._parse_known_args(args, namespace) + if args != args_ and args_ and args_[0].startswith(self.prefix_chars): + # option that was disabled are no more disable + # so create a new parser + new_parser = TiramisuCmdlineParser(self.prog, fullpath=self.fullpath) + new_parser._registries = self._registries + new_parser.add_arguments(self.config) + namespace_, args_ = new_parser._parse_known_args(args_, namespace) + else: + if self._registries['action']['help'].needs: + # display help only when all variables assignemnt are done + self._registries['action']['help'].needs = False + helper = self._registries['action']['help'](None) + helper.display(self) + return namespace_, args_ + def add_argument(self, *args, **kwargs): if args == ('-h', '--help'): super().add_argument(*args, **kwargs) @@ -118,7 +154,8 @@ class TiramisuCmdlineParser(ArgumentParser): raise ValueError('name cannot startswith "{}"'.format(self.prefix_chars)) properties = obj.property.get() kwargs = {'help': option.doc().replace('%', '%%'), - 'default': SUPPRESS} + 'default': SUPPRESS, + 'dest': option.path()} if 'positional' in properties: #if not 'mandatory' in properties: # raise ValueError('"positional" argument must be "mandatory" too') @@ -126,7 +163,7 @@ class TiramisuCmdlineParser(ArgumentParser): #if option.requires(): kwargs['nargs'] = '?' else: - if prefix: + if self.fullpath and prefix: name = prefix + '.' + name if len(name) == 1 and 'longargument' not in properties: args = [self.prefix_chars + name] @@ -199,20 +236,15 @@ class TiramisuCmdlineParser(ArgumentParser): def format_usage(self, *args, - _forhelp=False, **kwargs): - if _forhelp: - return super().format_usage(*args, **kwargs) - help_formatter = TiramisuCmdlineParser(self.prog) + help_formatter = TiramisuCmdlineParser(self.prog, fullpath=self.fullpath) help_formatter.add_arguments(self.config, _forhelp=True) - return help_formatter.format_usage(*args, **kwargs, _forhelp=True) + return super(TiramisuCmdlineParser, help_formatter).format_usage(*args, **kwargs) - def format_help(self, *args, _forhelp=False, **kwargs): - if _forhelp: - return super().format_help(*args, **kwargs) - help_formatter = TiramisuCmdlineParser(self.prog) + def format_help(self, *args, **kwargs): + help_formatter = TiramisuCmdlineParser(self.prog, fullpath=self.fullpath) help_formatter.add_arguments(self.config, _forhelp=True) - return help_formatter.format_help(*args, **kwargs, _forhelp=True) + return super(TiramisuCmdlineParser, help_formatter).format_help(*args, **kwargs) def get_config(self): return self.config