classification
Title: argparse: nargs='*' positional argument doesn't accept any items if preceded by an option and another positional
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.4, Python 3.3, Python 3.2, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: bethard, chris.jerdonek, gfxmonk, tshepang, waltermundt
Priority: normal Keywords: patch

Created on 2012-06-20 04:15 by waltermundt, last changed 2012-12-29 08:50 by chris.jerdonek.

Files
File name Uploaded Description Edit
argparse_fix_empty_nargs_star.patch waltermundt, 2012-06-22 21:54 Proposed fix
15112.patch bethard, 2012-07-22 21:53 review
Messages (4)
msg163249 - (view) Author: Walter Mundt (waltermundt) Date: 2012-06-20 04:15
Test case:

    from argparse import *

    parser = ArgumentParser()
    parser.add_argument('-x', action='store_true')
    parser.add_argument('y')
    parser.add_argument('z', nargs='*')

    print parser.parse_args('yy -x zz'.split(' '))

The result of this is that the "z" option is unfilled, and the "zz" argument is unrecognized, resulting in an error.  Changing the 'nargs' to '+' works in this case, but results in errors if the 'zz' is left off.
msg163497 - (view) Author: Walter Mundt (waltermundt) Date: 2012-06-22 21:54
Attached is a patch to fix this bug by deferring matching of nargs='*' argument against a zero-length pattern until the end of the arguments list.

I believe that it ought to be maximally conservative in that it should not change the behavior of any existing parsers except in cases where it allows them to accept arguments they would previously have left unrecognized in cases like the test in the initial report.
msg166173 - (view) Author: Steven Bethard (bethard) * (Python committer) Date: 2012-07-22 21:53
Your patch is a good start, but it needs to handle all the related situations, e.g. nargs='?' and the possibility of having more than one zero-length argument at the end.

I believe the following patch achieves this. Please test it out.
msg178481 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-12-29 08:50
Was argparse ever supposed to support inputs of the form given in the example (i.e. different positional arguments straddling optional arguments): 'yy -x zz'?

The usage string shows up as: "usage: test.py [-h] [-x] y [z [z ...]]"  The original example seems to work with the current code if given as: '-x yy zz'.

Also, substituting argparse.REMAINDER for '*' in the original example gives the following both with and without the patch:

Namespace(x=False, y='yy', z=['-x', 'zz'])

That doesn't seem consistent with straddling being supported.

Lastly, passing just '-x' gives the following error with and without the patch (z should be optional):

error: the following arguments are required: y, z
History
Date User Action Args
2012-12-29 08:50:41chris.jerdoneksetnosy: + chris.jerdonek
messages: + msg178481
2012-12-19 10:17:10gfxmonksetnosy: + gfxmonk
2012-07-22 21:53:46bethardsetfiles: + 15112.patch

messages: + msg166173
versions: + Python 3.2, Python 3.3, Python 3.4
2012-06-23 03:58:39waltermundtsettype: behavior
components: + Library (Lib)
versions: + Python 2.7
2012-06-22 21:54:43waltermundtsetfiles: + argparse_fix_empty_nargs_star.patch
keywords: + patch
messages: + msg163497
2012-06-22 18:19:07tshepangsetnosy: + tshepang
2012-06-20 12:30:54r.david.murraysetnosy: + bethard
2012-06-20 04:15:47waltermundtcreate