mirror of
https://github.com/python/cpython.git
synced 2025-08-13 13:29:13 +00:00
[3.12] gh-61181: Fix support of choices with string value in argparse (GH-124578) (GH-124756)
Substrings of the specified string no longer considered valid values.
(cherry picked from commit f1a2417b9e
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
71a2b8d185
commit
7677be5ee6
4 changed files with 17 additions and 11 deletions
|
@ -1774,7 +1774,7 @@ Sub-commands
|
||||||
>>>
|
>>>
|
||||||
>>> # create the parser for the "b" command
|
>>> # create the parser for the "b" command
|
||||||
>>> parser_b = subparsers.add_parser('b', help='b help')
|
>>> 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
|
>>> # parse some argument lists
|
||||||
>>> parser.parse_args(['a', '12'])
|
>>> parser.parse_args(['a', '12'])
|
||||||
|
|
|
@ -2589,11 +2589,15 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
||||||
|
|
||||||
def _check_value(self, action, value):
|
def _check_value(self, action, value):
|
||||||
# converted value must be one of the choices (if specified)
|
# converted value must be one of the choices (if specified)
|
||||||
if action.choices is not None and value not in action.choices:
|
choices = action.choices
|
||||||
args = {'value': value,
|
if choices is not None:
|
||||||
'choices': ', '.join(map(repr, action.choices))}
|
if isinstance(choices, str):
|
||||||
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
|
choices = iter(choices)
|
||||||
raise ArgumentError(action, msg % args)
|
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
|
# Help-formatting methods
|
||||||
|
|
|
@ -686,7 +686,7 @@ class TestOptionalsChoices(ParserTestCase):
|
||||||
argument_signatures = [
|
argument_signatures = [
|
||||||
Sig('-f', choices='abc'),
|
Sig('-f', choices='abc'),
|
||||||
Sig('-g', type=int, choices=range(5))]
|
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 = [
|
successes = [
|
||||||
('', NS(f=None, g=None)),
|
('', NS(f=None, g=None)),
|
||||||
('-f a', NS(f='a', g=None)),
|
('-f a', NS(f='a', g=None)),
|
||||||
|
@ -2227,14 +2227,14 @@ class TestAddSubparsers(TestCase):
|
||||||
parser1_kwargs['aliases'] = ['1alias1', '1alias2']
|
parser1_kwargs['aliases'] = ['1alias1', '1alias2']
|
||||||
parser1 = subparsers.add_parser('1', **parser1_kwargs)
|
parser1 = subparsers.add_parser('1', **parser1_kwargs)
|
||||||
parser1.add_argument('-w', type=int, help='w help')
|
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
|
# add second sub-parser
|
||||||
parser2_kwargs = dict(description='2 description')
|
parser2_kwargs = dict(description='2 description')
|
||||||
if subparser_help:
|
if subparser_help:
|
||||||
parser2_kwargs['help'] = '2 help'
|
parser2_kwargs['help'] = '2 help'
|
||||||
parser2 = subparsers.add_parser('2', **parser2_kwargs)
|
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')
|
parser2.add_argument('z', type=complex, nargs='*', help='z help')
|
||||||
|
|
||||||
# add third sub-parser
|
# add third sub-parser
|
||||||
|
@ -4397,7 +4397,7 @@ class TestHelpVariableExpansion(HelpTestCase):
|
||||||
help='x %(prog)s %(default)s %(type)s %%'),
|
help='x %(prog)s %(default)s %(type)s %%'),
|
||||||
Sig('-y', action='store_const', default=42, const='XXX',
|
Sig('-y', action='store_const', default=42, const='XXX',
|
||||||
help='y %(prog)s %(default)s %(const)s'),
|
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'),
|
help='foo %(prog)s %(default)s %(choices)s'),
|
||||||
Sig('--bar', default='baz', choices=[1, 2], metavar='BBB',
|
Sig('--bar', default='baz', choices=[1, 2], metavar='BBB',
|
||||||
help='bar %(prog)s %(default)s %(dest)s'),
|
help='bar %(prog)s %(default)s %(dest)s'),
|
||||||
|
@ -5057,7 +5057,7 @@ class TestInvalidArgumentConstructors(TestCase):
|
||||||
for action in ['store_const', 'store_true', 'store_false',
|
for action in ['store_const', 'store_true', 'store_false',
|
||||||
'append_const', 'count']:
|
'append_const', 'count']:
|
||||||
for attrs in [dict(type=int), dict(nargs='+'),
|
for attrs in [dict(type=int), dict(nargs='+'),
|
||||||
dict(choices='ab')]:
|
dict(choices=['a', 'b'])]:
|
||||||
self.assertTypeError('-x', action=action, **attrs)
|
self.assertTypeError('-x', action=action, **attrs)
|
||||||
|
|
||||||
def test_no_argument_no_const_actions(self):
|
def test_no_argument_no_const_actions(self):
|
||||||
|
|
|
@ -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.
|
Loading…
Add table
Add a link
Reference in a new issue