diff -r 44f455e6163d Lib/argparse.py --- a/Lib/argparse.py Thu Jun 27 12:23:29 2013 +0200 +++ b/Lib/argparse.py Sun Jun 22 12:30:01 2014 -0700 @@ -1051,6 +1051,30 @@ sup = super(_SubParsersAction._ChoicesPseudoAction, self) sup.__init__(option_strings=[], dest=dest, help=help, metavar=metavar) + class _PseudoGroup(Action): + + def __init__(self, container, title): + sup = super(_SubParsersAction._PseudoGroup, self) + sup.__init__(option_strings=[], dest=title) + self.container = container + self._choices_actions = [] + + def add_parser(self, name, **kwargs): + # add the parser to the main Action, but move the pseudo action + # in the group's own list + parser = self.container.add_parser(name, **kwargs) + choice_action = self.container._choices_actions.pop() + self._choices_actions.append(choice_action) + return parser + + def _get_subactions(self): + return self._choices_actions + + def add_parser_group(self, title): + # the formatter can handle recursive subgroups + grp = _SubParsersAction._PseudoGroup(self, title) + self._choices_actions.append(grp) + return grp def __init__(self, option_strings, @@ -1073,6 +1097,12 @@ help=help, metavar=metavar) + def add_parser_group(self, title): + # + grp = _SubParsersAction._PseudoGroup(self, title) + self._choices_actions.append(grp) + return grp + def add_parser(self, name, **kwargs): # set prog from the existing prefix if kwargs.get('prog') is None: diff -r 44f455e6163d Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py Thu Jun 27 12:23:29 2013 +0200 +++ b/Lib/test/test_argparse.py Sun Jun 22 12:30:01 2014 -0700 @@ -4904,6 +4904,40 @@ ] self.assertEqual(sorted(items), sorted(argparse.__all__)) +# ===================== +# test subparser groups +# ===================== + + def test_simple_group(self): + # + parser = argparse.ArgumentParser(prog='PROG') + cmd = parser.add_subparsers(dest='cmd') + grp1 = cmd.add_parser_group('group1:') + grp1.add_parser('a', help='a subcommand help', aliases=['a1','a2']) + grp1.add_parser('b', help='b subcommand help') + grp1.add_parser('c', help='c subcommand help') + grp2 = cmd.add_parser_group('group2:') + grp2.add_parser('d', help='d subcommand help') + grp2.add_parser('e', help='e subcommand help', aliases=['e1']) + + self.assertEqual(parser.format_help(), textwrap.dedent('''\ + usage: PROG [-h] {a,a1,a2,b,c,d,e,e1} ... + + positional arguments: + {a,a1,a2,b,c,d,e,e1} + group1: + a (a1, a2) a subcommand help + b b subcommand help + c c subcommand help + group2: + d d subcommand help + e (e1) e subcommand help + + optional arguments: + -h, --help show this help message and exit + ''')) + + def test_main(): support.run_unittest(__name__) # Remove global references to avoid looking like we have refleaks.