Index: Lib/argparse.py =================================================================== --- Lib/argparse.py (revision 82127) +++ Lib/argparse.py (working copy) @@ -541,7 +541,11 @@ if action.metavar is not None: result = action.metavar elif action.choices is not None: - choice_strs = [str(choice) for choice in action.choices] + if isinstance(action, _SubParsersAction): + choice_strs = [choice_action.dest + for choice_action in action._choices_actions] + else: + choice_strs = [str(choice) for choice in action.choices] result = '{%s}' % ','.join(choice_strs) else: result = default_metavar @@ -1042,8 +1046,10 @@ # create a pseudo-action to hold the choice help if 'help' in kwargs: help = kwargs.pop('help') - choice_action = self._ChoicesPseudoAction(name, help) - self._choices_actions.append(choice_action) + else: + help = '' + choice_action = self._ChoicesPseudoAction(name, help) + self._choices_actions.append(choice_action) # create the parser and add it to the map parser = self._parser_class(**kwargs) @@ -1051,7 +1057,9 @@ return parser def _get_subactions(self): - return self._choices_actions + return [choice_action + for choice_action in self._choices_actions + if choice_action.help] def __call__(self, parser, namespace, values, option_string=None): parser_name = values[0] Index: Lib/test/test_argparse.py =================================================================== --- Lib/test/test_argparse.py (revision 82127) +++ Lib/test/test_argparse.py (working copy) @@ -1782,7 +1782,7 @@ parser2 = subparsers.add_parser('2') self.assertEqual(parser.format_usage(), 'usage: PROG [-h] [--foo] bar {1,2} ...\n') - self.assertEqual(parser.format_help(), textwrap.dedent('''\ + self.assertMultiLineEqual(parser.format_help(), textwrap.dedent('''\ usage: PROG [-h] [--foo] bar {1,2} ... main description @@ -2615,16 +2615,28 @@ parser = argparse.ArgumentParser( *tester.parser_signature.args, **tester.parser_signature.kwargs) - for argument_sig in tester.argument_signatures: - parser.add_argument(*argument_sig.args, - **argument_sig.kwargs) - group_signatures = tester.argument_group_signatures - for group_sig, argument_sigs in group_signatures: - group = parser.add_argument_group(*group_sig.args, - **group_sig.kwargs) - for argument_sig in argument_sigs: - group.add_argument(*argument_sig.args, - **argument_sig.kwargs) + + if hasattr(tester, 'argument_signatures'): + for argument_sig in tester.argument_signatures: + parser.add_argument(*argument_sig.args, + **argument_sig.kwargs) + + if hasattr(tester, 'argument_group_signatures'): + group_signatures = tester.argument_group_signatures + for group_sig, argument_sigs in group_signatures: + group = parser.add_argument_group(*group_sig.args, + **group_sig.kwargs) + for argument_sig in argument_sigs: + group.add_argument(*argument_sig.args, + **argument_sig.kwargs) + + if hasattr(tester, 'subparsers_signatures'): + subparsers = parser.add_subparsers() + subparsers_signatures = tester.subparsers_signatures + for subparser_sig in subparsers_signatures: + subparsers.add_parser(*subparser_sig.args, + **subparser_sig.kwargs) + return parser def _test(self, tester, parser_text): @@ -2637,7 +2649,7 @@ if char1 != char2: print('first diff: %r %r' % (char1, char2)) break - tester.assertEqual(expected_text, parser_text) + tester.assertMultiLineEqual(expected_text, parser_text) def test_format(self, tester): parser = self._get_parser(tester) @@ -3718,6 +3730,78 @@ ''' version = '' + +class TestHelpSubparsersOrdering(HelpTestCase): + """Test ordering of subcommands in help matches the code""" + parser_signature = Sig(prog='PROG', + description='display some subcommands', + version='0.1') + + subparsers_signatures = [Sig(name=name) + for name in ('a', 'b', 'c', 'd', 'e')] + + usage = '''\ + usage: PROG [-h] [-v] {a,b,c,d,e} ... + ''' + + help = usage + '''\ + + display some subcommands + + positional arguments: + {a,b,c,d,e} + + optional arguments: + -h, --help show this help message and exit + -v, --version show program's version number and exit + ''' + + version = '''\ + 0.1 + ''' + +class TestHelpSubparsersWithHelpOrdering(HelpTestCase): + """Test ordering of subcommands in help matches the code""" + parser_signature = Sig(prog='PROG', + description='display some subcommands', + version='0.1') + + subcommand_data = (('a', 'a subcommand help'), + ('b', 'b subcommand help'), + ('c', 'c subcommand help'), + ('d', 'd subcommand help'), + ('e', 'e subcommand help'), + ) + + subparsers_signatures = [Sig(name=name, help=help) + for name, help in subcommand_data] + + usage = '''\ + usage: PROG [-h] [-v] {a,b,c,d,e} ... + ''' + + help = usage + '''\ + + display some subcommands + + positional arguments: + {a,b,c,d,e} + a a subcommand help + b b subcommand help + c c subcommand help + d d subcommand help + e e subcommand help + + optional arguments: + -h, --help show this help message and exit + -v, --version show program's version number and exit + ''' + + version = '''\ + 0.1 + ''' + + # ===================================== # Optional/Positional constructor tests # =====================================