Index: Lib/argparse.py =================================================================== --- Lib/argparse.py (revision 82127) +++ Lib/argparse.py (working copy) @@ -82,6 +82,7 @@ import textwrap as _textwrap from gettext import gettext as _ +from collections import OrderedDict def _callable(obj): @@ -1023,7 +1024,7 @@ self._prog_prefix = prog self._parser_class = parser_class - self._name_parser_map = {} + self._name_parser_map = OrderedDict() self._choices_actions = [] super(_SubParsersAction, self).__init__( Index: Lib/test/test_argparse.py =================================================================== --- Lib/test/test_argparse.py (revision 82127) +++ Lib/test/test_argparse.py (working copy) @@ -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 # =====================================