8000 gh-85935: Check for nargs=0 for positional arguments in argparse (GH-… · python/cpython@9944ad3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9944ad3

Browse files
gh-85935: Check for nargs=0 for positional arguments in argparse (GH-124839)
Raise ValueError in add_argument() if either explicit nargs=0 or action that does not consume arguments (like 'store_const' or 'store_true') is specified for positional argument.
1 parent 63cf4e9 commit 9944ad3

File tree

3 files changed

+18
-3
lines changed

3 files changed

+18
-3
lines changed

Lib/argparse.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1441,11 +1441,17 @@ def add_argument(self, *args, **kwargs):
14411441
kwargs['default'] = self.argument_default
14421442

14431443
# create the action object, and add it to the parser
1444+
action_name = kwargs.get('action')
14441445
action_class = self._pop_action_class(kwargs)
14451446
if not callable(action_class):
14461447
raise ValueError('unknown action "%s"' % (action_class,))
14471448
action = action_class(**kwargs)
14481449

1450+
# raise an error if action for positional argument does not
1451+
# consume arguments
1452+
if not action.option_strings and action.nargs == 0:
1453+
raise ValueError(f'action {action_name!r} is not valid for positional arguments')
1454+
14491455
# raise an error if the action type is not callable
14501456
type_func = self._registry_get('type', action.type, action.type)
14511457
if not callable(type_func):
@@ -1554,7 +1560,9 @@ def _get_positional_kwargs(self, dest, **kwargs):
15541560
# mark positional arguments as required if at least one is
15551561
# always required
15561562
nargs = kwargs.get('nargs')
1557-
if nargs not in [OPTIONAL, ZERO_OR_MORE, REMAINDER, SUPPRESS, 0]:
1563+
if nargs == 0:
1564+
raise ValueError('nargs for positionals must be != 0')
1565+
if nargs not in [OPTIONAL, ZERO_OR_MORE, REMAINDER, SUPPRESS]:
15581566
kwargs['required'] = True
15591567

15601568
# return the keyword arguments with no option strings

Lib/test/test_argparse.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5424,8 +5424,11 @@ def test_no_argument_actions(self):
54245424
with self.subTest(attrs=attrs):
54255425
self.assertTypeError('-x', action=action, **attrs)
54265426
self.assertTypeError('x', action=action, **attrs)
5427+
self.assertValueError('x', action=action,
5428+
errmsg=f"action '{action}' is not valid for positional arguments")
54275429
self.assertTypeError('-x', action=action, nargs=0)
5428-
self.assertTypeError('x', action=action, nargs=0)
5430+
self.assertValueError('x', action=action, nargs=0,
5431+
errmsg='nargs for positionals must be != 0')
54295432

54305433
def test_no_argument_no_const_actions(self):
54315434
# options with zero arguments
@@ -5445,7 +5448,7 @@ def test_more_than_one_argument_actions(self):
54455448
self.assertValueError('-x', nargs=0, action=action,
54465449
errmsg=f'nargs for {action_name} actions must be != 0')
54475450
self.assertValueError('spam', nargs=0, action=action,
5448-
errmsg=f'nargs for {action_name} actions must be != 0')
5451+
errmsg='nargs for positionals must be != 0')
54495452

54505453
# const is disallowed with non-optional arguments
54515454
for nargs in [1, '*', '+']:
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:meth:`argparse.ArgumentParser.add_argument` now raises an exception if
2+
an :ref:`action` that does not consume arguments (like 'store_const' or
3+
'store_true') or explicit ``nargs=0`` are specified for positional
4+
arguments.

0 commit comments

Comments
 (0)
0