From e95217a55a6bdd52f48e14c06ef29df5fc5e6ca2 Mon Sep 17 00:00:00 2001 From: Cyker Way Date: Sat, 1 Dec 2018 07:53:53 -0500 Subject: [PATCH] bpo-14074: argparse doesn't allow metavar to be a tuple Currently argparse allows nargs>1 for positional arguments but doesn't allow metavar to be a tuple: import argparse parser = argparse.ArgumentParser() parser.add_argument('foo', nargs=2, metavar=('bar', 'baz')) args = parser.parse_args() The above code will raise exception both with and without '--help'. This patch fixed some functions about metavar processing so the above code will pass. --- Lib/argparse.py | 5 +++++ Lib/test/test_argparse.py | 22 +++++++++++++++++++ .../2018-12-04-07-36-27.bpo-14074.fMLKCu.rst | 2 ++ 3 files changed, 29 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2018-12-04-07-36-27.bpo-14074.fMLKCu.rst diff --git a/Lib/argparse.py b/Lib/argparse.py index de95eedbee0ee6..87ed14b1ef2207 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -553,6 +553,8 @@ def _format_action(self, action): def _format_action_invocation(self, action): if not action.option_strings: default = self._get_default_metavar_for_positional(action) + if isinstance(action.nargs, int): + return ' '.join(self._metavar_formatter(action, default)(1)) metavar, = self._metavar_formatter(action, default)(1) return metavar @@ -730,6 +732,9 @@ def _get_action_name(argument): elif argument.option_strings: return '/'.join(argument.option_strings) elif argument.metavar not in (None, SUPPRESS): + if isinstance( + argument.nargs, int) and isinstance(argument.metavar, tuple): + return ' '.join(argument.metavar) return argument.metavar elif argument.dest not in (None, SUPPRESS): return argument.dest diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 4c23610b9e961c..e3d374e872750b 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4226,6 +4226,28 @@ class TestHelpTupleMetavar(HelpTestCase): version = '' +class TestHelpTupleMetavarPositional(HelpTestCase): + """Test specifying metavar on a Positional as a tuple""" + + parser_signature = Sig(prog='PROG') + argument_signatures = [ + Sig('foo', help='foo help', nargs=2, metavar=('bar', 'baz')) + ] + argument_group_signatures = [] + usage = '''\ + usage: PROG [-h] bar baz + ''' + help = usage + '''\ + + positional arguments: + bar baz foo help + + options: + -h, --help show this help message and exit + ''' + version = '' + + class TestHelpRawText(HelpTestCase): """Test the RawTextHelpFormatter""" diff --git a/Misc/NEWS.d/next/Library/2018-12-04-07-36-27.bpo-14074.fMLKCu.rst b/Misc/NEWS.d/next/Library/2018-12-04-07-36-27.bpo-14074.fMLKCu.rst new file mode 100644 index 00000000000000..221c8e05fa98aa --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-04-07-36-27.bpo-14074.fMLKCu.rst @@ -0,0 +1,2 @@ +Fix :mod:`argparse` metavar processing to allow positional arguments to have a +tuple metavar.