mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
GH-99749: Add optional feature to suggest correct names (ArgumentParser) (GH-124456)
This commit is contained in:
parent
a5a7f5e16d
commit
624be8699a
4 changed files with 144 additions and 23 deletions
|
@ -1773,6 +1773,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
|||
- allow_abbrev -- Allow long options to be abbreviated unambiguously
|
||||
- exit_on_error -- Determines whether or not ArgumentParser exits with
|
||||
error info when an error occurs
|
||||
- suggest_on_error - Enables suggestions for mistyped argument choices
|
||||
and subparser names. (default: ``False``)
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
|
@ -1788,7 +1790,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
|||
conflict_handler='error',
|
||||
add_help=True,
|
||||
allow_abbrev=True,
|
||||
exit_on_error=True):
|
||||
exit_on_error=True,
|
||||
suggest_on_error=False):
|
||||
|
||||
superinit = super(ArgumentParser, self).__init__
|
||||
superinit(description=description,
|
||||
|
@ -1804,6 +1807,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
|||
self.add_help = add_help
|
||||
self.allow_abbrev = allow_abbrev
|
||||
self.exit_on_error = exit_on_error
|
||||
self.suggest_on_error = suggest_on_error
|
||||
|
||||
add_group = self.add_argument_group
|
||||
self._positionals = add_group(_('positional arguments'))
|
||||
|
@ -2601,14 +2605,27 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
|||
def _check_value(self, action, value):
|
||||
# converted value must be one of the choices (if specified)
|
||||
choices = action.choices
|
||||
if choices is not None:
|
||||
if isinstance(choices, str):
|
||||
choices = iter(choices)
|
||||
if value not in choices:
|
||||
args = {'value': str(value),
|
||||
'choices': ', '.join(map(str, action.choices))}
|
||||
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
|
||||
raise ArgumentError(action, msg % args)
|
||||
if choices is None:
|
||||
return
|
||||
|
||||
if isinstance(choices, str):
|
||||
choices = iter(choices)
|
||||
|
||||
if value not in choices:
|
||||
args = {'value': str(value),
|
||||
'choices': ', '.join(map(str, action.choices))}
|
||||
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
|
||||
|
||||
if self.suggest_on_error and isinstance(value, str):
|
||||
if all(isinstance(choice, str) for choice in action.choices):
|
||||
import difflib
|
||||
suggestions = difflib.get_close_matches(value, action.choices, 1)
|
||||
if suggestions:
|
||||
args['closest'] = suggestions[0]
|
||||
msg = _('invalid choice: %(value)r, maybe you meant %(closest)r? '
|
||||
'(choose from %(choices)s)')
|
||||
|
||||
raise ArgumentError(action, msg % args)
|
||||
|
||||
# =======================
|
||||
# Help-formatting methods
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue