Skip to content

Commit 4a9a359

Browse files
[3.13] gh-61181: Fix support of choices with string value in argparse (GH-124578) (GH-124755)
Substrings of the specified string no longer considered valid values. (cherry picked from commit f1a2417) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 11d4b54 commit 4a9a359

File tree

4 files changed

+17
-11
lines changed

4 files changed

+17
-11
lines changed

Doc/library/argparse.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1804,7 +1804,7 @@ Sub-commands
18041804
>>>
18051805
>>> # create the parser for the "b" command
18061806
>>> parser_b = subparsers.add_parser('b', help='b help')
1807-
>>> parser_b.add_argument('--baz', choices='XYZ', help='baz help')
1807+
>>> parser_b.add_argument('--baz', choices=('X', 'Y', 'Z'), help='baz help')
18081808
>>>
18091809
>>> # parse some argument lists
18101810
>>> parser.parse_args(['a', '12'])

Lib/argparse.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,11 +2582,15 @@ def _get_value(self, action, arg_string):
25822582

25832583
def _check_value(self, action, value):
25842584
# converted value must be one of the choices (if specified)
2585-
if action.choices is not None and value not in action.choices:
2586-
args = {'value': value,
2587-
'choices': ', '.join(map(repr, action.choices))}
2588-
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
2589-
raise ArgumentError(action, msg % args)
2585+
choices = action.choices
2586+
if choices is not None:
2587+
if isinstance(choices, str):
2588+
choices = iter(choices)
2589+
if value not in choices:
2590+
args = {'value': value,
2591+
'choices': ', '.join(map(repr, action.choices))}
2592+
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
2593+
raise ArgumentError(action, msg % args)
25902594

25912595
# =======================
25922596
# Help-formatting methods

Lib/test/test_argparse.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ class TestOptionalsChoices(ParserTestCase):
686686
argument_signatures = [
687687
Sig('-f', choices='abc'),
688688
Sig('-g', type=int, choices=range(5))]
689-
failures = ['a', '-f d', '-fad', '-ga', '-g 6']
689+
failures = ['a', '-f d', '-f ab', '-fad', '-ga', '-g 6']
690690
successes = [
691691
('', NS(f=None, g=None)),
692692
('-f a', NS(f='a', g=None)),
@@ -2291,14 +2291,14 @@ def _get_parser(self, subparser_help=False, prefix_chars=None,
22912291
parser1_kwargs['aliases'] = ['1alias1', '1alias2']
22922292
parser1 = subparsers.add_parser('1', **parser1_kwargs)
22932293
parser1.add_argument('-w', type=int, help='w help')
2294-
parser1.add_argument('x', choices='abc', help='x help')
2294+
parser1.add_argument('x', choices=['a', 'b', 'c'], help='x help')
22952295

22962296
# add second sub-parser
22972297
parser2_kwargs = dict(description='2 description')
22982298
if subparser_help:
22992299
parser2_kwargs['help'] = '2 help'
23002300
parser2 = subparsers.add_parser('2', **parser2_kwargs)
2301-
parser2.add_argument('-y', choices='123', help='y help')
2301+
parser2.add_argument('-y', choices=['1', '2', '3'], help='y help')
23022302
parser2.add_argument('z', type=complex, nargs='*', help='z help')
23032303

23042304
# add third sub-parser
@@ -4628,7 +4628,7 @@ class TestHelpVariableExpansion(HelpTestCase):
46284628
help='x %(prog)s %(default)s %(type)s %%'),
46294629
Sig('-y', action='store_const', default=42, const='XXX',
46304630
help='y %(prog)s %(default)s %(const)s'),
4631-
Sig('--foo', choices='abc',
4631+
Sig('--foo', choices=['a', 'b', 'c'],
46324632
help='foo %(prog)s %(default)s %(choices)s'),
46334633
Sig('--bar', default='baz', choices=[1, 2], metavar='BBB',
46344634
help='bar %(prog)s %(default)s %(dest)s'),
@@ -5291,7 +5291,7 @@ def test_no_argument_actions(self):
52915291
for action in ['store_const', 'store_true', 'store_false',
52925292
'append_const', 'count']:
52935293
for attrs in [dict(type=int), dict(nargs='+'),
5294-
dict(choices='ab')]:
5294+
dict(choices=['a', 'b'])]:
52955295
self.assertTypeError('-x', action=action, **attrs)
52965296

52975297
def test_no_argument_no_const_actions(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix support of :ref:`choices` with string value in :mod:`argparse`. Substrings
2+
of the specified string no longer considered valid values.

0 commit comments

Comments
 (0)