yang <[email protected]> added the comment:
I ran into the same issue and looked into the code, and found it more
complicated than I thought. The more I went on, more issues occur. I wonder if
I should open a new issue, but I will first comment here. If you feel like this
should be a new issue, I will open one then. And I apologize in advance for
possible vaguenesses in this comment because I modified it several times as I
explored the code and found more issues. (also because of my poor English):)
It seems the issue happens only on positional arguments but not optional ones.
Empty optional arguments will not call `take_action` and default values are
handled and converted after consuming all arguments.
It also leads to inconsistancy between positional and optional arguments
behaviour. Positional arguments always go through `take_action`, but optional
arguments don't if an argument doesn't appear.
This inconsistancy causes another I think is strange behaviour,
parser = ArgumentParser()
parser.add_argument('i', action='count')
parser.parse_args([])
got
Namespace(i=1)
On the other hand, in `_get_values` function, `_check_value` is called to
handle `choices=`, but there is no such guard for optional arguments, which
means,
parser = ArgumentParser()
parser.add_argument('-i', nargs='?', type=int, default='2', choices=[1])
parser.parse_args([])
doesn't raise an error.
Besides Paul's two instructive solutions, I think it better to make both sides
behave the same. However, I found things seem not that simple.
First, ZERO_OR_MORE, no default value, positional arguments have
`required=True` by default, but
parser.add_argument('foo', nargs='*')
parser.parse_args([])
got no problems. So it at least appears not required. (The document says
`required` is only for optionals, so I guess it's just a implementation level
but not a user level thing)
Second, the last case above gives
Namespace(foo=[])
which seems logically incorrect or at least controversial, because the default
is not set and you give no arguments, how does this list come? The document
says nothing about the case (it's true it's a very corner one) and it also
differs from the optional arguments case which gives
Namespace(foo=None)
A walk around which doesn't change it is possible and I've written a patch
fixing it.
And I'm not sure what we usually do if I propose to make them give the same
result, is a PEP needed or I just raise a discussion about it? The change might
break current code.
----------
nosy: +fhsxfhsx
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue36078>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com