diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1894,6 +1894,13 @@ selected_pattern = arg_strings_pattern[start_index:] arg_counts = match_partial(positionals, selected_pattern) + # if we haven't hit the end of the command line strings, + # then don't consume any final zero-width arguments yet + # (we may need to parse some more optionals first) + if start_index + sum(arg_counts) != len(arg_strings_pattern): + while arg_counts and arg_counts[-1] == 0: + arg_counts.pop() + # slice off the appropriate arg strings for each Positional # and add the Positional and its args to the list for action, arg_count in zip(positionals, arg_counts): diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1254,6 +1254,56 @@ ] +class TestNargsOneOrMoreDeferred(ParserTestCase): + """Tests specifying a positional with nargs='*' that must be deferred""" + + argument_signatures = [ + Sig('-x', action='store_true'), + Sig('y'), + Sig('z', nargs='*'), + ] + failures = ['', '-x'] + successes = [ + ('Y', NS(x=False, y='Y', z=[])), + ('Y -x', NS(x=True, y='Y', z=[])), + ('Y -x Z Z', NS(x=True, y='Y', z=['Z', 'Z'])), + ] + + +class TestNargsZeroOrOneDeferred(ParserTestCase): + """Tests specifying a positional with nargs='?' that must be deferred""" + + argument_signatures = [ + Sig('-x', action='store_true'), + Sig('y'), + Sig('z', nargs='?'), + ] + failures = ['', '-x'] + successes = [ + ('Y', NS(x=False, y='Y', z=None)), + ('Y -x', NS(x=True, y='Y', z=None)), + ('Y -x Z', NS(x=True, y='Y', z='Z')), + ] + + +class TestNargsMultipleDeferred(ParserTestCase): + """Tests specifying a positional multiple nargs that must be deferred""" + + argument_signatures = [ + Sig('-w', action='store_true'), + Sig('x'), + Sig('y', nargs='?'), + Sig('z', nargs='*'), + ] + failures = ['', '-x'] + successes = [ + ('X', NS(w=False, x='X', y=None, z=[])), + ('X -w', NS(w=True, x='X', y=None, z=[])), + ('X -w Y', NS(w=True, x='X', y='Y', z=[])), + ('X -w Y Z', NS(w=True, x='X', y='Y', z=['Z'])), + ] + + class TestOptionLike(ParserTestCase): """Tests options that may or may not be arguments"""