Skip to content

Commit

Permalink
pythongh-61181: Fix support of choices with string value in argparse (p…
Browse files Browse the repository at this point in the history
…ythonGH-124578)

Substrings of the specified string no longer considered valid values.
(cherry picked from commit f1a2417)

Co-authored-by: Serhiy Storchaka <[email protected]>
  • Loading branch information
serhiy-storchaka authored and miss-islington committed Sep 29, 2024
1 parent 65103ad commit 9438ae2
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Doc/library/argparse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,7 @@ Sub-commands
>>>
>>> # create the parser for the "b" command
>>> parser_b = subparsers.add_parser('b', help='b help')
>>> parser_b.add_argument('--baz', choices='XYZ', help='baz help')
>>> parser_b.add_argument('--baz', choices=('X', 'Y', 'Z'), help='baz help')
>>>
>>> # parse some argument lists
>>> parser.parse_args(['a', '12'])
Expand Down
14 changes: 9 additions & 5 deletions Lib/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2587,11 +2587,15 @@ def _get_value(self, action, arg_string):

def _check_value(self, action, value):
# converted value must be one of the choices (if specified)
if action.choices is not None and value not in action.choices:
args = {'value': value,
'choices': ', '.join(map(repr, action.choices))}
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
raise ArgumentError(action, msg % args)
choices = action.choices
if choices is not None:
if isinstance(choices, str):
choices = iter(choices)
if value not in choices:
args = {'value': value,
'choices': ', '.join(map(repr, action.choices))}
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
raise ArgumentError(action, msg % args)

# =======================
# Help-formatting methods
Expand Down
10 changes: 5 additions & 5 deletions Lib/test/test_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ class TestOptionalsChoices(ParserTestCase):
argument_signatures = [
Sig('-f', choices='abc'),
Sig('-g', type=int, choices=range(5))]
failures = ['a', '-f d', '-fad', '-ga', '-g 6']
failures = ['a', '-f d', '-f ab', '-fad', '-ga', '-g 6']
successes = [
('', NS(f=None, g=None)),
('-f a', NS(f='a', g=None)),
Expand Down Expand Up @@ -2195,14 +2195,14 @@ def _get_parser(self, subparser_help=False, prefix_chars=None,
parser1_kwargs['aliases'] = ['1alias1', '1alias2']
parser1 = subparsers.add_parser('1', **parser1_kwargs)
parser1.add_argument('-w', type=int, help='w help')
parser1.add_argument('x', choices='abc', help='x help')
parser1.add_argument('x', choices=['a', 'b', 'c'], help='x help')

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

# add third sub-parser
Expand Down Expand Up @@ -4365,7 +4365,7 @@ class TestHelpVariableExpansion(HelpTestCase):
help='x %(prog)s %(default)s %(type)s %%'),
Sig('-y', action='store_const', default=42, const='XXX',
help='y %(prog)s %(default)s %(const)s'),
Sig('--foo', choices='abc',
Sig('--foo', choices=['a', 'b', 'c'],
help='foo %(prog)s %(default)s %(choices)s'),
Sig('--bar', default='baz', choices=[1, 2], metavar='BBB',
help='bar %(prog)s %(default)s %(dest)s'),
Expand Down Expand Up @@ -5025,7 +5025,7 @@ def test_no_argument_actions(self):
for action in ['store_const', 'store_true', 'store_false',
'append_const', 'count']:
for attrs in [dict(type=int), dict(nargs='+'),
dict(choices='ab')]:
dict(choices=['a', 'b'])]:
self.assertTypeError('-x', action=action, **attrs)

def test_no_argument_no_const_actions(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix support of :ref:`choices` with string value in :mod:`argparse`. Substrings
of the specified string no longer considered valid values.

0 comments on commit 9438ae2

Please sign in to comment.