GeezerVison is showing github.com — [3.13] gh-86357: argparse: use str() consistently and explicitly to p… · python/cpython@d3d306a
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: Lib/argparse.py +5-7Lines changed: 5 additions & 7 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -547,8 +547,7 @@ def _metavar_formatter(self, action, default_metavar): | 547 | 547 | if action.metavar is not None: | 548 | 548 | result = action.metavar | 549 | 549 | elif action.choices is not None: | 550 | | - choice_strs = [str(choice) for choice in action.choices] | 551 | | - result = '{%s}' % ','.join(choice_strs) | | 550 | + result = '{%s}' % ','.join(map(str, action.choices)) | 552 | 551 | else: | 553 | 552 | result = default_metavar | 554 | 553 |
| @@ -596,8 +595,7 @@ def _expand_help(self, action): | 596 | 595 | if hasattr(params[name], '__name__'): | 597 | 596 | params[name] = params[name].__name__ | 598 | 597 | if params.get('choices') is not None: | 599 | | - choices_str = ', '.join([str(c) for c in params['choices']]) | 600 | | - params['choices'] = choices_str | | 598 | + params['choices'] = ', '.join(map(str, params['choices'])) | 601 | 599 | return self._get_help_string(action) % params | 602 | 600 |
| 603 | 601 | def _iter_indented_subactions(self, action): | @@ -714,7 +712,7 @@ def _get_action_name(argument): | 714 | 712 | elif argument.dest not in (None, SUPPRESS): | 715 | 713 | return argument.dest | 716 | 714 | elif argument.choices: | 717 | | - return '{' + ','.join(argument.choices) + '}' | | 715 | + return '{%s}' % ','.join(map(str, argument.choices)) | 718 | 716 | else: | 719 | 717 | return None | 720 | 718 |
| @@ -2595,8 +2593,8 @@ def _check_value(self, action, value): | 2595 | 2593 | if isinstance(choices, str): | 2596 | 2594 | choices = iter(choices) | 2597 | 2595 | if value not in choices: | 2598 | | - args = {'value': value, | 2599 | | - 'choices': ', '.join(map(repr, action.choices))} | | 2596 | + args = {'value': str(value), | | 2597 | + 'choices': ', '.join(map(str, action.choices))} | 2600 | 2598 | msg = _('invalid choice: %(value)r (choose from %(choices)s)') | 2601 | 2599 | raise ArgumentError(action, msg % args) | 2602 | 2600 |
| |
Collapse file Copy file name to clipboardExpand all lines: Lib/test/test_argparse.py +30-1Lines changed: 30 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 15 | 15 | import argparse | 16 | 16 | import warnings | 17 | 17 |
| | 18 | +from enum import StrEnum | 18 | 19 | from test.support import os_helper, captured_stderr | 19 | 20 | from unittest import mock | 20 | 21 |
| @@ -1021,6 +1022,34 @@ class TestDisallowLongAbbreviationAllowsShortGroupingPrefix(ParserTestCase): | 1021 | 1022 | ] | 1022 | 1023 |
| 1023 | 1024 |
| | 1025 | +class TestStrEnumChoices(TestCase): | | 1026 | + class Color(StrEnum): | | 1027 | + RED = "red" | | 1028 | + GREEN = "green" | | 1029 | + BLUE = "blue" | | 1030 | + | | 1031 | + def test_parse_enum_value(self): | | 1032 | + parser = argparse.ArgumentParser() | | 1033 | + parser.add_argument('--color', choices=self.Color) | | 1034 | + args = parser.parse_args(['--color', 'red']) | | 1035 | + self.assertEqual(args.color, self.Color.RED) | | 1036 | + | | 1037 | + def test_help_message_contains_enum_choices(self): | | 1038 | + parser = argparse.ArgumentParser() | | 1039 | + parser.add_argument('--color', choices=self.Color, help='Choose a color') | | 1040 | + self.assertIn('[--color {red,green,blue}]', parser.format_usage()) | | 1041 | + self.assertIn(' --color {red,green,blue}', parser.format_help()) | | 1042 | + | | 1043 | + def test_invalid_enum_value_raises_error(self): | | 1044 | + parser = argparse.ArgumentParser(exit_on_error=False) | | 1045 | + parser.add_argument('--color', choices=self.Color) | | 1046 | + self.assertRaisesRegex( | | 1047 | + argparse.ArgumentError, | | 1048 | + r"invalid choice: 'yellow' \(choose from red, green, blue\)", | | 1049 | + parser.parse_args, | | 1050 | + ['--color', 'yellow'], | | 1051 | + ) | | 1052 | + | 1024 | 1053 | # ================ | 1025 | 1054 | # Positional tests | 1026 | 1055 | # ================ | @@ -2486,7 +2515,7 @@ def test_wrong_argument_subparsers_no_destination_error(self): | 2486 | 2515 | parser.parse_args(('baz',)) | 2487 | 2516 | self.assertRegex( | 2488 | 2517 | excinfo.exception.stderr, | 2489 | | - r"error: argument {foo,bar}: invalid choice: 'baz' \(choose from 'foo', 'bar'\)\n$" | | 2518 | + r"error: argument {foo,bar}: invalid choice: 'baz' \(choose from foo, bar\)\n$" | 2490 | 2519 | ) | 2491 | 2520 |
| 2492 | 2521 | def test_optional_subparsers(self): | |
Collapse file Copy file name to clipboard +1Lines changed: 1 addition & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +Always use :func:`str` to print ``choices`` in :mod:`argparse`. |
|