From 7fdaaedf4c63c8d019f03f84e22f9b838ef19aa6 Mon Sep 17 00:00:00 2001 From: Christopher Larson Date: Wed, 27 Apr 2016 16:23:59 -0700 Subject: scripts/lib/argparse_oe: show subparser help for unrecognized args As an example, `recipetool create foo bar baz` shows `recipetool: error: unrecognized arguments: bar baz` and then displays the main help, not the help for the create command. Fix by saving the subparser name and using it in parse_args() to look up the subparser. Signed-off-by: Christopher Larson Signed-off-by: Richard Purdie --- scripts/lib/argparse_oe.py | 49 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/scripts/lib/argparse_oe.py b/scripts/lib/argparse_oe.py index 95b42e75ea..75002d02af 100644 --- a/scripts/lib/argparse_oe.py +++ b/scripts/lib/argparse_oe.py @@ -27,15 +27,20 @@ class ArgumentParser(argparse.ArgumentParser): def error_subcommand(self, message, subcommand): if subcommand: - for action in self._actions: - if isinstance(action, argparse._SubParsersAction): - for choice, subparser in action.choices.items(): - if choice == subcommand: - subparser.error(message) - return + action = self._get_subparser_action() + try: + subparser = action._name_parser_map[subcommand] + except KeyError: + self.error('no subparser for name "%s"' % subcommand) + else: + subparser.error(message) + self.error(message) def add_subparsers(self, *args, **kwargs): + if 'dest' not in kwargs: + kwargs['dest'] = '_subparser_name' + ret = super(ArgumentParser, self).add_subparsers(*args, **kwargs) # Need a way of accessing the parent parser ret._parent_parser = self @@ -48,6 +53,38 @@ class ArgumentParser(argparse.ArgumentParser): def add_subparser_group(self, groupname, groupdesc, order=0): self._subparser_groups[groupname] = (groupdesc, order) + def parse_args(self, args=None, namespace=None): + """Parse arguments, using the correct subparser to show the error.""" + args, argv = self.parse_known_args(args, namespace) + if argv: + message = 'unrecognized arguments: %s' % ' '.join(argv) + if self._subparsers: + subparser = self._get_subparser(args) + subparser.error(message) + else: + self.error(message) + sys.exit(2) + return args + + def _get_subparser(self, args): + action = self._get_subparser_action() + if action.dest == argparse.SUPPRESS: + self.error('cannot get subparser, the subparser action dest is suppressed') + + name = getattr(args, action.dest) + try: + return action._name_parser_map[name] + except KeyError: + self.error('no subparser for name "%s"' % name) + + def _get_subparser_action(self): + if not self._subparsers: + self.error('cannot return the subparser action, no subparsers added') + + for action in self._subparsers._group_actions: + if isinstance(action, argparse._SubParsersAction): + return action + class ArgumentSubParser(ArgumentParser): def __init__(self, *args, **kwargs): -- cgit 1.2.3-korg