Update argparse to 1.4.0

This commit is contained in:
JonnyWong16 2019-11-23 18:50:16 -08:00
parent e19938b05e
commit 2a9d0ea7d2

View file

@ -1,4 +1,5 @@
# Author: Steven J. Bethard <steven.bethard@gmail.com>. # Author: Steven J. Bethard <steven.bethard@gmail.com>.
# Maintainer: Thomas Waldmann <tw@waldmann-edv.de>
"""Command-line parsing library """Command-line parsing library
@ -61,7 +62,12 @@ considered public as object names -- the API of the formatter objects is
still considered an implementation detail.) still considered an implementation detail.)
""" """
__version__ = '1.1' __version__ = '1.4.0' # we use our own version number independant of the
# one in stdlib and we release this on pypi.
__external_lib__ = True # to make sure the tests really test THIS lib,
# not the builtin one in Python stdlib
__all__ = [ __all__ = [
'ArgumentParser', 'ArgumentParser',
'ArgumentError', 'ArgumentError',
@ -71,7 +77,6 @@ __all__ = [
'ArgumentDefaultsHelpFormatter', 'ArgumentDefaultsHelpFormatter',
'RawDescriptionHelpFormatter', 'RawDescriptionHelpFormatter',
'RawTextHelpFormatter', 'RawTextHelpFormatter',
'MetavarTypeHelpFormatter',
'Namespace', 'Namespace',
'Action', 'Action',
'ONE_OR_MORE', 'ONE_OR_MORE',
@ -83,14 +88,35 @@ __all__ = [
] ]
import collections as _collections
import copy as _copy import copy as _copy
import os as _os import os as _os
import re as _re import re as _re
import sys as _sys import sys as _sys
import textwrap as _textwrap import textwrap as _textwrap
from gettext import gettext as _, ngettext from gettext import gettext as _
try:
set
except NameError:
# for python < 2.4 compatibility (sets module is there since 2.3):
from sets import Set as set
try:
basestring
except NameError:
basestring = str
try:
sorted
except NameError:
# for python < 2.4 compatibility:
def sorted(iterable, reverse=False):
result = list(iterable)
result.sort()
if reverse:
result.reverse()
return result
def _callable(obj): def _callable(obj):
@ -424,8 +450,7 @@ class HelpFormatter(object):
# produce all arg strings # produce all arg strings
elif not action.option_strings: elif not action.option_strings:
default = self._get_default_metavar_for_positional(action) part = self._format_args(action, action.dest)
part = self._format_args(action, default)
# if it's in a group, strip the outer [] # if it's in a group, strip the outer []
if action in group_actions: if action in group_actions:
@ -447,7 +472,7 @@ class HelpFormatter(object):
# if the Optional takes a value, format is: # if the Optional takes a value, format is:
# -s ARGS or --long ARGS # -s ARGS or --long ARGS
else: else:
default = self._get_default_metavar_for_optional(action) default = action.dest.upper()
args_string = self._format_args(action, default) args_string = self._format_args(action, default)
part = '%s %s' % (option_string, args_string) part = '%s %s' % (option_string, args_string)
@ -533,8 +558,7 @@ class HelpFormatter(object):
def _format_action_invocation(self, action): def _format_action_invocation(self, action):
if not action.option_strings: if not action.option_strings:
default = self._get_default_metavar_for_positional(action) metavar, = self._metavar_formatter(action, action.dest)(1)
metavar, = self._metavar_formatter(action, default)(1)
return metavar return metavar
else: else:
@ -548,7 +572,7 @@ class HelpFormatter(object):
# if the Optional takes a value, format is: # if the Optional takes a value, format is:
# -s ARGS, --long ARGS # -s ARGS, --long ARGS
else: else:
default = self._get_default_metavar_for_optional(action) default = action.dest.upper()
args_string = self._format_args(action, default) args_string = self._format_args(action, default)
for option_string in action.option_strings: for option_string in action.option_strings:
parts.append('%s %s' % (option_string, args_string)) parts.append('%s %s' % (option_string, args_string))
@ -626,12 +650,6 @@ class HelpFormatter(object):
def _get_help_string(self, action): def _get_help_string(self, action):
return action.help return action.help
def _get_default_metavar_for_optional(self, action):
return action.dest.upper()
def _get_default_metavar_for_positional(self, action):
return action.dest
class RawDescriptionHelpFormatter(HelpFormatter): class RawDescriptionHelpFormatter(HelpFormatter):
"""Help message formatter which retains any formatting in descriptions. """Help message formatter which retains any formatting in descriptions.
@ -672,22 +690,6 @@ class ArgumentDefaultsHelpFormatter(HelpFormatter):
return help return help
class MetavarTypeHelpFormatter(HelpFormatter):
"""Help message formatter which uses the argument 'type' as the default
metavar value (instead of the argument 'dest')
Only the name of this class is considered a public API. All the methods
provided by the class are considered an implementation detail.
"""
def _get_default_metavar_for_optional(self, action):
return action.type.__name__
def _get_default_metavar_for_positional(self, action):
return action.type.__name__
# ===================== # =====================
# Options and Arguments # Options and Arguments
# ===================== # =====================
@ -1055,7 +1057,7 @@ class _SubParsersAction(Action):
metavar += ' (%s)' % ', '.join(aliases) metavar += ' (%s)' % ', '.join(aliases)
sup = super(_SubParsersAction._ChoicesPseudoAction, self) sup = super(_SubParsersAction._ChoicesPseudoAction, self)
sup.__init__(option_strings=[], dest=dest, help=help, sup.__init__(option_strings=[], dest=dest, help=help,
metavar=metavar) metavar=metavar)
def __init__(self, def __init__(self,
option_strings, option_strings,
@ -1067,7 +1069,7 @@ class _SubParsersAction(Action):
self._prog_prefix = prog self._prog_prefix = prog
self._parser_class = parser_class self._parser_class = parser_class
self._name_parser_map = _collections.OrderedDict() self._name_parser_map = {}
self._choices_actions = [] self._choices_actions = []
super(_SubParsersAction, self).__init__( super(_SubParsersAction, self).__init__(
@ -1116,9 +1118,8 @@ class _SubParsersAction(Action):
try: try:
parser = self._name_parser_map[parser_name] parser = self._name_parser_map[parser_name]
except KeyError: except KeyError:
args = {'parser_name': parser_name, tup = parser_name, ', '.join(self._name_parser_map)
'choices': ', '.join(self._name_parser_map)} msg = _('unknown parser %r (choices: %s)' % tup)
msg = _('unknown parser %(parser_name)r (choices: %(choices)s)') % args
raise ArgumentError(self, msg) raise ArgumentError(self, msg)
# parse all the remaining options into the namespace # parse all the remaining options into the namespace
@ -1147,7 +1148,7 @@ class FileType(object):
the builtin open() function. the builtin open() function.
""" """
def __init__(self, mode='r', bufsize=-1): def __init__(self, mode='r', bufsize=None):
self._mode = mode self._mode = mode
self._bufsize = bufsize self._bufsize = bufsize
@ -1159,19 +1160,23 @@ class FileType(object):
elif 'w' in self._mode: elif 'w' in self._mode:
return _sys.stdout return _sys.stdout
else: else:
msg = _('argument "-" with mode %r') % self._mode msg = _('argument "-" with mode %r' % self._mode)
raise ValueError(msg) raise ValueError(msg)
# all other arguments are used as file names
try: try:
return open(string, self._mode, self._bufsize) # all other arguments are used as file names
except IOError as e: if self._bufsize:
return open(string, self._mode, self._bufsize)
else:
return open(string, self._mode)
except IOError:
err = _sys.exc_info()[1]
message = _("can't open '%s': %s") message = _("can't open '%s': %s")
raise ArgumentTypeError(message % (string, e)) raise ArgumentTypeError(message % (string, err))
def __repr__(self): def __repr__(self):
args = self._mode, self._bufsize args = [self._mode, self._bufsize]
args_str = ', '.join(repr(arg) for arg in args if arg != -1) args_str = ', '.join([repr(arg) for arg in args if arg is not None])
return '%s(%s)' % (type(self).__name__, args_str) return '%s(%s)' % (type(self).__name__, args_str)
# =========================== # ===========================
@ -1189,6 +1194,8 @@ class Namespace(_AttributeHolder):
for name in kwargs: for name in kwargs:
setattr(self, name, kwargs[name]) setattr(self, name, kwargs[name])
__hash__ = None
def __eq__(self, other): def __eq__(self, other):
return vars(self) == vars(other) return vars(self) == vars(other)
@ -1312,20 +1319,13 @@ class _ActionsContainer(object):
# create the action object, and add it to the parser # create the action object, and add it to the parser
action_class = self._pop_action_class(kwargs) action_class = self._pop_action_class(kwargs)
if not _callable(action_class): if not _callable(action_class):
raise ValueError('unknown action "%s"' % (action_class,)) raise ValueError('unknown action "%s"' % action_class)
action = action_class(**kwargs) action = action_class(**kwargs)
# raise an error if the action type is not callable # raise an error if the action type is not callable
type_func = self._registry_get('type', action.type, action.type) type_func = self._registry_get('type', action.type, action.type)
if not _callable(type_func): if not _callable(type_func):
raise ValueError('%r is not callable' % (type_func,)) raise ValueError('%r is not callable' % type_func)
# raise an error if the metavar does not match the type
if hasattr(self, "_get_formatter"):
try:
self._get_formatter()._format_args(action, None)
except TypeError:
raise ValueError("length of metavar tuple does not match nargs")
return self._add_action(action) return self._add_action(action)
@ -1426,11 +1426,10 @@ class _ActionsContainer(object):
for option_string in args: for option_string in args:
# error on strings that don't start with an appropriate prefix # error on strings that don't start with an appropriate prefix
if not option_string[0] in self.prefix_chars: if not option_string[0] in self.prefix_chars:
args = {'option': option_string, msg = _('invalid option string %r: '
'prefix_chars': self.prefix_chars} 'must start with a character %r')
msg = _('invalid option string %(option)r: ' tup = option_string, self.prefix_chars
'must start with a character %(prefix_chars)r') raise ValueError(msg % tup)
raise ValueError(msg % args)
# strings starting with two prefix characters are long options # strings starting with two prefix characters are long options
option_strings.append(option_string) option_strings.append(option_string)
@ -1483,9 +1482,7 @@ class _ActionsContainer(object):
conflict_handler(action, confl_optionals) conflict_handler(action, confl_optionals)
def _handle_conflict_error(self, action, conflicting_actions): def _handle_conflict_error(self, action, conflicting_actions):
message = ngettext('conflicting option string: %s', message = _('conflicting option string(s): %s')
'conflicting option strings: %s',
len(conflicting_actions))
conflict_string = ', '.join([option_string conflict_string = ', '.join([option_string
for option_string, action for option_string, action
in conflicting_actions]) in conflicting_actions])
@ -1528,7 +1525,6 @@ class _ArgumentGroup(_ActionsContainer):
self._defaults = container._defaults self._defaults = container._defaults
self._has_negative_number_optionals = \ self._has_negative_number_optionals = \
container._has_negative_number_optionals container._has_negative_number_optionals
self._mutually_exclusive_groups = container._mutually_exclusive_groups
def _add_action(self, action): def _add_action(self, action):
action = super(_ArgumentGroup, self)._add_action(action) action = super(_ArgumentGroup, self)._add_action(action)
@ -1630,7 +1626,10 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
# add help and version arguments if necessary # add help and version arguments if necessary
# (using explicit default to override global argument_default) # (using explicit default to override global argument_default)
default_prefix = '-' if '-' in prefix_chars else prefix_chars[0] if '-' in prefix_chars:
default_prefix = '-'
else:
default_prefix = prefix_chars[0]
if self.add_help: if self.add_help:
self.add_argument( self.add_argument(
default_prefix+'h', default_prefix*2+'help', default_prefix+'h', default_prefix*2+'help',
@ -1743,10 +1742,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
if action.dest is not SUPPRESS: if action.dest is not SUPPRESS:
if not hasattr(namespace, action.dest): if not hasattr(namespace, action.dest):
if action.default is not SUPPRESS: if action.default is not SUPPRESS:
default = action.default setattr(namespace, action.dest, action.default)
if isinstance(action.default, str):
default = self._get_value(action, default)
setattr(namespace, action.dest, default)
# add any parser defaults that aren't present # add any parser defaults that aren't present
for dest in self._defaults: for dest in self._defaults:
@ -1969,12 +1965,28 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
# if we didn't consume all the argument strings, there were extras # if we didn't consume all the argument strings, there were extras
extras.extend(arg_strings[stop_index:]) extras.extend(arg_strings[stop_index:])
# make sure all required actions were present # if we didn't use all the Positional objects, there were too few
required_actions = [_get_action_name(action) for action in self._actions # arg strings supplied.
if action.required and action not in seen_actions] if positionals:
if required_actions: self.error(_('too few arguments'))
self.error(_('the following arguments are required: %s') %
', '.join(required_actions)) # make sure all required actions were present, and convert defaults.
for action in self._actions:
if action not in seen_actions:
if action.required:
name = _get_action_name(action)
self.error(_('argument %s is required') % name)
else:
# Convert action default now instead of doing it before
# parsing arguments to avoid calling convert functions
# twice (which may fail) if the argument was given, but
# only if it was defined already in the namespace
if (action.default is not None and
isinstance(action.default, basestring) and
hasattr(namespace, action.dest) and
action.default is getattr(namespace, action.dest)):
setattr(namespace, action.dest,
self._get_value(action, action.default))
# make sure all required groups had one option present # make sure all required groups had one option present
for group in self._mutually_exclusive_groups: for group in self._mutually_exclusive_groups:
@ -2038,9 +2050,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
OPTIONAL: _('expected at most one argument'), OPTIONAL: _('expected at most one argument'),
ONE_OR_MORE: _('expected at least one argument'), ONE_OR_MORE: _('expected at least one argument'),
} }
default = ngettext('expected %s argument', default = _('expected %s argument(s)') % action.nargs
'expected %s arguments',
action.nargs) % action.nargs
msg = nargs_errors.get(action.nargs, default) msg = nargs_errors.get(action.nargs, default)
raise ArgumentError(action, msg) raise ArgumentError(action, msg)
@ -2096,9 +2106,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
if len(option_tuples) > 1: if len(option_tuples) > 1:
options = ', '.join([option_string options = ', '.join([option_string
for action, option_string, explicit_arg in option_tuples]) for action, option_string, explicit_arg in option_tuples])
args = {'option': arg_string, 'matches': options} tup = arg_string, options
msg = _('ambiguous option: %(option)s could match %(matches)s') self.error(_('ambiguous option: %s could match %s') % tup)
self.error(msg % args)
# if exactly one action matched, this segmentation is good, # if exactly one action matched, this segmentation is good,
# so return the parsed action # so return the parsed action
@ -2220,7 +2229,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
value = action.const value = action.const
else: else:
value = action.default value = action.default
if isinstance(value, str): if isinstance(value, basestring):
value = self._get_value(action, value) value = self._get_value(action, value)
self._check_value(action, value) self._check_value(action, value)
@ -2277,9 +2286,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
# TypeErrors or ValueErrors also indicate errors # TypeErrors or ValueErrors also indicate errors
except (TypeError, ValueError): except (TypeError, ValueError):
name = getattr(action.type, '__name__', repr(action.type)) name = getattr(action.type, '__name__', repr(action.type))
args = {'type': name, 'value': arg_string} msg = _('invalid %s value: %r')
msg = _('invalid %(type)s value: %(value)r') raise ArgumentError(action, msg % (name, arg_string))
raise ArgumentError(action, msg % args)
# return the converted value # return the converted value
return result return result
@ -2287,10 +2295,9 @@ 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: if action.choices is not None and value not in action.choices:
args = {'value': value, tup = value, ', '.join(map(repr, action.choices))
'choices': ', '.join(map(repr, action.choices))} msg = _('invalid choice: %r (choose from %s)') % tup
msg = _('invalid choice: %(value)r (choose from %(choices)s)') raise ArgumentError(action, msg)
raise ArgumentError(action, msg % args)
# ======================= # =======================
# Help-formatting methods # Help-formatting methods
@ -2382,5 +2389,4 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
should either exit or raise an exception. should either exit or raise an exception.
""" """
self.print_usage(_sys.stderr) self.print_usage(_sys.stderr)
args = {'prog': self.prog, 'message': message} self.exit(2, _('%s: error: %s\n') % (self.prog, message))
self.exit(2, _('%(prog)s: error: %(message)s\n') % args)