diff -r a88310d86455 Lib/argparse.py --- a/Lib/argparse.py Sun Apr 14 19:22:47 2013 +0200 +++ b/Lib/argparse.py Mon Apr 15 23:41:40 2013 -0700 @@ -1903,6 +1903,19 @@ selected_pattern = arg_strings_pattern[start_index:] arg_counts = match_partial(positionals, selected_pattern) + #print([[x[0].dest,x[1]] for x in zip(positionals, arg_counts)]) + # if arg_count==0 and nargs '*' ('?'as well) make it tentative? + # or lop off the last match if count is 0 and there's an 'O' in + # remaining pattern + # e.g. 'AOAA',[1,0],[null,'*'] + if 'O' in arg_strings_pattern[start_index:]: + # if there is an optional after this, remove + # 'empty' positionals from the current match + while len(arg_counts)>1 and arg_counts[-1]==0: + print(arg_counts, arg_strings_pattern) + arg_counts = arg_counts[:-1] + print([[x[0].dest,x[1]] for x in zip(positionals, arg_counts)]) + # 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 -r a88310d86455 Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py Sun Apr 14 19:22:47 2013 +0200 +++ b/Lib/test/test_argparse.py Mon Apr 15 23:41:40 2013 -0700 @@ -1254,6 +1254,76 @@ ('X Y --foo', NS(x='X', y=['Y', '--foo'], z=None)), ] +class TestOptionalsBetween2PositionalsZeroOrMore(ParserTestCase): + """Tests optionals within positionals, '*' 2nd positional + 2nd positional is not consumed by the 1st argument set""" + + argument_signatures = [Sig('cmd'), + Sig('-f', '--foo'), + Sig('rest',nargs='*')] + failures = ['', # the following arguments are required: cmd, rest + 'cmd 1 -f1 2', # unrecognized arguments: 2 + 'cmd 1 --foo 1 2', + # optional cannot split arguments for 'rest' + ] + successes = [ + ('-f1 cmd 1 2', NS(cmd='cmd', foo='1', rest=['1', '2'])), + ('cmd -f1 1 2', NS(cmd='cmd', foo='1', rest=['1', '2'])), + ('cmd 1 2 --foo 1', NS(cmd='cmd', foo='1', rest=['1', '2'])), + ('cmd --foo 1 1 2',NS(cmd='cmd', foo='1', rest=['1', '2'])) + ] + +class TestOptionalsBetween2PositionalsOptional(ParserTestCase): + """Tests optionals within positionals, '?' 2nd positional + 2nd positional is not consumed by the 1st argument set""" + + argument_signatures = [ + Sig('cmd'), + Sig('-f', '--foo'), + Sig('rest',nargs='?') + ] + failures = [] + successes = [ + ('-f1 cmd 1', NS(cmd='cmd', foo='1', rest='1')), + ('cmd -f1 1', NS(cmd='cmd', foo='1', rest='1')), + ] + +class TestOptionalsBetween3PositionalsZeroOrMore(ParserTestCase): + """Tests optionals within positionals, '*' 2nd positional + 2 positionals that might not be consumed by the 1st argument""" + + argument_signatures = [ + Sig('cmd'), + Sig('-f', '--foo'), + Sig('resta',nargs='?'), + Sig('restb',nargs='*') + ] + failures = ['cmd 1 2 -f1 3'] + successes = [ + ('-f1 cmd 1 2 3', NS(cmd='cmd', foo='1', resta='1', restb=['2', '3'])), + ('cmd -f1 1 2 3', NS(cmd='cmd', foo='1', resta='1', restb=['2', '3'])), + ('cmd 1 -f1 2 3', NS(cmd='cmd', foo='1', resta='1', restb=['2', '3'])), + ('cmd 1 2 3 -f1', NS(cmd='cmd', foo='1', resta='1', restb=['2', '3'])), + ] + +class TestOptionalsBetween3PositionalsOptional(ParserTestCase): + """Tests optionals within positionals, '?' 2nd positional + 2 positionals that might not be consumed by the 1st argument set""" + + argument_signatures = [ + Sig('cmd'), + Sig('-f', '--foo'), + Sig('resta', nargs='?'), + Sig('restb', nargs='?') + ] + failures = [] + successes = [ + ('-f1 cmd 1 2', NS(cmd='cmd', foo='1', resta='1', restb='2')), + ('cmd -f1 1 2', NS(cmd='cmd', foo='1', resta='1', restb='2')), + ('cmd 1 -f1 2', NS(cmd='cmd', foo='1', resta='1', restb='2')), + ('cmd 1 2 -f1', NS(cmd='cmd', foo='1', resta='1', restb='2')), + ] + class TestOptionLike(ParserTestCase): """Tests options that may or may not be arguments"""