Skip to content

Commit 0a04677

Browse files
[3.13] gh-72795: Make positional arguments with nargs='*' or REMAINDER non-required (GH-124306) (#124421)
This allows to use positional argument with nargs='*' and without default in mutually exclusive group and improves error message about required arguments. (cherry picked from commit 3c83f99) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent db3ccd8 commit 0a04677

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

Lib/argparse.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,9 +1561,8 @@ def _get_positional_kwargs(self, dest, **kwargs):
15611561

15621562
# mark positional arguments as required if at least one is
15631563
# always required
1564-
if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
1565-
kwargs['required'] = True
1566-
if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
1564+
nargs = kwargs.get('nargs')
1565+
if nargs not in [OPTIONAL, ZERO_OR_MORE, REMAINDER, SUPPRESS, 0]:
15671566
kwargs['required'] = True
15681567

15691568
# return the keyword arguments with no option strings

Lib/test/test_argparse.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3201,7 +3201,7 @@ def get_parser(self, required):
32013201
group = parser.add_mutually_exclusive_group(required=required)
32023202
group.add_argument('--foo', action='store_true', help='FOO')
32033203
group.add_argument('--spam', help='SPAM')
3204-
group.add_argument('badger', nargs='*', default='X', help='BADGER')
3204+
group.add_argument('badger', nargs='*', help='BADGER')
32053205
return parser
32063206

32073207
failures = [
@@ -3212,13 +3212,13 @@ def get_parser(self, required):
32123212
'--foo X Y',
32133213
]
32143214
successes = [
3215-
('--foo', NS(foo=True, spam=None, badger='X')),
3216-
('--spam S', NS(foo=False, spam='S', badger='X')),
3215+
('--foo', NS(foo=True, spam=None, badger=[])),
3216+
('--spam S', NS(foo=False, spam='S', badger=[])),
32173217
('X', NS(foo=False, spam=None, badger=['X'])),
32183218
('X Y Z', NS(foo=False, spam=None, badger=['X', 'Y', 'Z'])),
32193219
]
32203220
successes_when_not_required = [
3221-
('', NS(foo=False, spam=None, badger='X')),
3221+
('', NS(foo=False, spam=None, badger=[])),
32223222
]
32233223

32243224
usage_when_not_required = '''\
@@ -6491,7 +6491,28 @@ def test_required_args(self):
64916491
self.parser.add_argument('bar')
64926492
self.parser.add_argument('baz')
64936493
self.assertRaisesRegex(argparse.ArgumentError,
6494-
'the following arguments are required: bar, baz',
6494+
'the following arguments are required: bar, baz$',
6495+
self.parser.parse_args, [])
6496+
6497+
def test_required_args_optional(self):
6498+
self.parser.add_argument('bar')
6499+
self.parser.add_argument('baz', nargs='?')
6500+
self.assertRaisesRegex(argparse.ArgumentError,
6501+
'the following arguments are required: bar$',
6502+
self.parser.parse_args, [])
6503+
6504+
def test_required_args_zero_or_more(self):
6505+
self.parser.add_argument('bar')
6506+
self.parser.add_argument('baz', nargs='*')
6507+
self.assertRaisesRegex(argparse.ArgumentError,
6508+
'the following arguments are required: bar$',
6509+
self.parser.parse_args, [])
6510+
6511+
def test_required_args_remainder(self):
6512+
self.parser.add_argument('bar')
6513+
self.parser.add_argument('baz', nargs='...')
6514+
self.assertRaisesRegex(argparse.ArgumentError,
6515+
'the following arguments are required: bar$',
64956516
self.parser.parse_args, [])
64966517

64976518
def test_required_mutually_exclusive_args(self):
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Positional arguments with :ref:`nargs` equal to ``'*'`` or
2+
:data:`!argparse.REMAINDER` are no longer required. This allows to use
3+
positional argument with ``nargs='*'`` and without ``default`` in mutually
4+
exclusive group and improves error message about required arguments.

0 commit comments

Comments
 (0)