diff options
Diffstat (limited to 'Lib/argparse.py')
-rw-r--r-- | Lib/argparse.py | 524 |
1 files changed, 163 insertions, 361 deletions
diff --git a/Lib/argparse.py b/Lib/argparse.py index 5d3ce2a..d000486 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1,5 +1,4 @@ # Author: Steven J. Bethard <steven.bethard@gmail.com>. -# New maintainer as of 29 August 2019: Raymond Hettinger <raymond.hettinger@gmail.com> """Command-line parsing library @@ -67,13 +66,11 @@ __all__ = [ 'ArgumentParser', 'ArgumentError', 'ArgumentTypeError', - 'BooleanOptionalAction', 'FileType', 'HelpFormatter', 'ArgumentDefaultsHelpFormatter', 'RawDescriptionHelpFormatter', 'RawTextHelpFormatter', - 'MetavarTypeHelpFormatter', 'Namespace', 'Action', 'ONE_OR_MORE', @@ -85,11 +82,19 @@ __all__ = [ ] +import collections as _collections +import copy as _copy import os as _os import re as _re import sys as _sys +import textwrap as _textwrap + +from gettext import gettext as _ + + +def _callable(obj): + return hasattr(obj, '__call__') or hasattr(obj, '__bases__') -from gettext import gettext as _, ngettext SUPPRESS = '==SUPPRESS==' @@ -116,16 +121,10 @@ class _AttributeHolder(object): def __repr__(self): type_name = type(self).__name__ arg_strings = [] - star_args = {} for arg in self._get_args(): arg_strings.append(repr(arg)) for name, value in self._get_kwargs(): - if name.isidentifier(): - arg_strings.append('%s=%r' % (name, value)) - else: - star_args[name] = value - if star_args: - arg_strings.append('**%s' % repr(star_args)) + arg_strings.append('%s=%r' % (name, value)) return '%s(%s)' % (type_name, ', '.join(arg_strings)) def _get_kwargs(self): @@ -135,16 +134,10 @@ class _AttributeHolder(object): return [] -def _copy_items(items): - if items is None: - return [] - # The copy module is used only in the 'append' and 'append_const' - # actions, and it is needed only when the default value isn't a list. - # Delay its import for speeding up the common case. - if type(items) is list: - return items[:] - import copy - return copy.copy(items) +def _ensure_value(namespace, name, value): + if getattr(namespace, name, None) is None: + setattr(namespace, name, value) + return getattr(namespace, name) # =============== @@ -166,12 +159,15 @@ class HelpFormatter(object): # default setting for width if width is None: - import shutil - width = shutil.get_terminal_size().columns + try: + width = int(_os.environ['COLUMNS']) + except (KeyError, ValueError): + width = 80 width -= 2 self._prog = prog self._indent_increment = indent_increment + self._max_help_position = max_help_position self._max_help_position = min(max_help_position, max(width - 20, indent_increment * 2)) self._width = width @@ -183,7 +179,7 @@ class HelpFormatter(object): self._root_section = self._Section(self, None) self._current_section = self._root_section - self._whitespace_matcher = _re.compile(r'\s+', _re.ASCII) + self._whitespace_matcher = _re.compile(r'\s+') self._long_break_matcher = _re.compile(r'\n\n\n+') # =============================== @@ -211,6 +207,8 @@ class HelpFormatter(object): if self.parent is not None: self.formatter._indent() join = self.formatter._join_parts + for func, args in self.items: + func(*args) item_help = join([func(*args) for func, args in self.items]) if self.parent is not None: self.formatter._dedent() @@ -264,7 +262,7 @@ class HelpFormatter(object): invocations.append(get_invocation(subaction)) # update the maximum item length - invocation_length = max(map(len, invocations)) + invocation_length = max([len(s) for s in invocations]) action_length = invocation_length + self._current_indent self._action_max_length = max(self._action_max_length, action_length) @@ -406,19 +404,13 @@ class HelpFormatter(object): inserts[start] += ' [' else: inserts[start] = '[' - if end in inserts: - inserts[end] += ']' - else: - inserts[end] = ']' + inserts[end] = ']' else: if start in inserts: inserts[start] += ' (' else: inserts[start] = '(' - if end in inserts: - inserts[end] += ')' - else: - inserts[end] = ')' + inserts[end] = ')' for i in range(start + 1, end): inserts[i] = '|' @@ -437,8 +429,7 @@ class HelpFormatter(object): # produce all arg strings elif not action.option_strings: - default = self._get_default_metavar_for_positional(action) - part = self._format_args(action, default) + part = self._format_args(action, action.dest) # if it's in a group, strip the outer [] if action in group_actions: @@ -455,12 +446,12 @@ class HelpFormatter(object): # if the Optional doesn't take a value, format is: # -s or --long if action.nargs == 0: - part = action.format_usage() + part = '%s' % option_string # if the Optional takes a value, format is: # -s ARGS or --long ARGS else: - default = self._get_default_metavar_for_optional(action) + default = action.dest.upper() args_string = self._format_args(action, default) part = '%s %s' % (option_string, args_string) @@ -505,7 +496,7 @@ class HelpFormatter(object): action_width = help_position - self._current_indent - 2 action_header = self._format_action_invocation(action) - # no help; start on same line and add a final newline + # ho nelp; start on same line and add a final newline if not action.help: tup = self._current_indent, '', action_header action_header = '%*s%s\n' % tup @@ -546,8 +537,7 @@ class HelpFormatter(object): def _format_action_invocation(self, action): if not action.option_strings: - default = self._get_default_metavar_for_positional(action) - metavar, = self._metavar_formatter(action, default)(1) + metavar, = self._metavar_formatter(action, action.dest)(1) return metavar else: @@ -561,7 +551,7 @@ class HelpFormatter(object): # if the Optional takes a value, format is: # -s ARGS, --long ARGS else: - default = self._get_default_metavar_for_optional(action) + default = action.dest.upper() args_string = self._format_args(action, default) for option_string in action.option_strings: parts.append('%s %s' % (option_string, args_string)) @@ -591,24 +581,15 @@ class HelpFormatter(object): elif action.nargs == OPTIONAL: result = '[%s]' % get_metavar(1) elif action.nargs == ZERO_OR_MORE: - metavar = get_metavar(1) - if len(metavar) == 2: - result = '[%s [%s ...]]' % metavar - else: - result = '[%s ...]' % metavar + result = '[%s [%s ...]]' % get_metavar(2) elif action.nargs == ONE_OR_MORE: result = '%s [%s ...]' % get_metavar(2) elif action.nargs == REMAINDER: result = '...' elif action.nargs == PARSER: result = '%s ...' % get_metavar(1) - elif action.nargs == SUPPRESS: - result = '' else: - try: - formats = ['%s' for _ in range(action.nargs)] - except TypeError: - raise ValueError("invalid nargs value") from None + formats = ['%s' for _ in range(action.nargs)] result = ' '.join(formats) % get_metavar(action.nargs) return result @@ -632,32 +613,22 @@ class HelpFormatter(object): pass else: self._indent() - yield from get_subactions() + for subaction in get_subactions(): + yield subaction self._dedent() def _split_lines(self, text, width): text = self._whitespace_matcher.sub(' ', text).strip() - # The textwrap module is used only for formatting help. - # Delay its import for speeding up the common usage of argparse. - import textwrap - return textwrap.wrap(text, width) + return _textwrap.wrap(text, width) def _fill_text(self, text, width, indent): text = self._whitespace_matcher.sub(' ', text).strip() - import textwrap - return textwrap.fill(text, width, - initial_indent=indent, - subsequent_indent=indent) + return _textwrap.fill(text, width, initial_indent=indent, + subsequent_indent=indent) def _get_help_string(self, action): 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): """Help message formatter which retains any formatting in descriptions. @@ -667,7 +638,7 @@ class RawDescriptionHelpFormatter(HelpFormatter): """ def _fill_text(self, text, width, indent): - return ''.join(indent + line for line in text.splitlines(keepends=True)) + return ''.join([indent + line for line in text.splitlines(True)]) class RawTextHelpFormatter(RawDescriptionHelpFormatter): @@ -698,22 +669,6 @@ class ArgumentDefaultsHelpFormatter(HelpFormatter): 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 # ===================== @@ -847,53 +802,9 @@ class Action(_AttributeHolder): ] return [(name, getattr(self, name)) for name in names] - def format_usage(self): - return self.option_strings[0] - def __call__(self, parser, namespace, values, option_string=None): raise NotImplementedError(_('.__call__() not defined')) -class BooleanOptionalAction(Action): - def __init__(self, - option_strings, - dest, - const=None, - default=None, - type=None, - choices=None, - required=False, - help=None, - metavar=None): - - _option_strings = [] - for option_string in option_strings: - _option_strings.append(option_string) - - if option_string.startswith('--'): - option_string = '--no-' + option_string[2:] - _option_strings.append(option_string) - - if help is not None and default is not None: - help += f" (default: {default})" - - super().__init__( - option_strings=_option_strings, - dest=dest, - nargs=0, - default=default, - type=type, - choices=choices, - required=required, - help=help, - metavar=metavar) - - def __call__(self, parser, namespace, values, option_string=None): - if option_string in self.option_strings: - setattr(namespace, self.dest, not option_string.startswith('--no-')) - - def format_usage(self): - return ' | '.join(self.option_strings) - class _StoreAction(Action): @@ -909,7 +820,7 @@ class _StoreAction(Action): help=None, metavar=None): if nargs == 0: - raise ValueError('nargs for store actions must be != 0; if you ' + raise ValueError('nargs for store actions must be > 0; if you ' 'have nothing to store, actions such as store ' 'true or store const may be more appropriate') if const is not None and nargs != OPTIONAL: @@ -1001,7 +912,7 @@ class _AppendAction(Action): help=None, metavar=None): if nargs == 0: - raise ValueError('nargs for append actions must be != 0; if arg ' + raise ValueError('nargs for append actions must be > 0; if arg ' 'strings are not supplying the value to append, ' 'the append const action may be more appropriate') if const is not None and nargs != OPTIONAL: @@ -1019,8 +930,7 @@ class _AppendAction(Action): metavar=metavar) def __call__(self, parser, namespace, values, option_string=None): - items = getattr(namespace, self.dest, None) - items = _copy_items(items) + items = _copy.copy(_ensure_value(namespace, self.dest, [])) items.append(values) setattr(namespace, self.dest, items) @@ -1046,8 +956,7 @@ class _AppendConstAction(Action): metavar=metavar) def __call__(self, parser, namespace, values, option_string=None): - items = getattr(namespace, self.dest, None) - items = _copy_items(items) + items = _copy.copy(_ensure_value(namespace, self.dest, [])) items.append(self.const) setattr(namespace, self.dest, items) @@ -1069,10 +978,8 @@ class _CountAction(Action): help=help) def __call__(self, parser, namespace, values, option_string=None): - count = getattr(namespace, self.dest, None) - if count is None: - count = 0 - setattr(namespace, self.dest, count + 1) + new_count = _ensure_value(namespace, self.dest, 0) + 1 + setattr(namespace, self.dest, new_count) class _HelpAction(Action): @@ -1116,34 +1023,28 @@ class _VersionAction(Action): version = parser.version formatter = parser._get_formatter() formatter.add_text(version) - parser._print_message(formatter.format_help(), _sys.stdout) - parser.exit() + parser.exit(message=formatter.format_help()) class _SubParsersAction(Action): class _ChoicesPseudoAction(Action): - def __init__(self, name, aliases, help): - metavar = dest = name - if aliases: - metavar += ' (%s)' % ', '.join(aliases) + def __init__(self, name, help): sup = super(_SubParsersAction._ChoicesPseudoAction, self) - sup.__init__(option_strings=[], dest=dest, help=help, - metavar=metavar) + sup.__init__(option_strings=[], dest=name, help=help) def __init__(self, option_strings, prog, parser_class, dest=SUPPRESS, - required=False, help=None, metavar=None): self._prog_prefix = prog self._parser_class = parser_class - self._name_parser_map = {} + self._name_parser_map = _collections.OrderedDict() self._choices_actions = [] super(_SubParsersAction, self).__init__( @@ -1151,7 +1052,6 @@ class _SubParsersAction(Action): dest=dest, nargs=PARSER, choices=self._name_parser_map, - required=required, help=help, metavar=metavar) @@ -1160,22 +1060,15 @@ class _SubParsersAction(Action): if kwargs.get('prog') is None: kwargs['prog'] = '%s %s' % (self._prog_prefix, name) - aliases = kwargs.pop('aliases', ()) - # create a pseudo-action to hold the choice help if 'help' in kwargs: help = kwargs.pop('help') - choice_action = self._ChoicesPseudoAction(name, aliases, help) + choice_action = self._ChoicesPseudoAction(name, help) self._choices_actions.append(choice_action) # create the parser and add it to the map parser = self._parser_class(**kwargs) self._name_parser_map[name] = parser - - # make parser available under aliases also - for alias in aliases: - self._name_parser_map[alias] = parser - return parser def _get_subactions(self): @@ -1193,9 +1086,8 @@ class _SubParsersAction(Action): try: parser = self._name_parser_map[parser_name] except KeyError: - args = {'parser_name': parser_name, - 'choices': ', '.join(self._name_parser_map)} - msg = _('unknown parser %(parser_name)r (choices: %(choices)s)') % args + tup = parser_name, ', '.join(self._name_parser_map) + msg = _('unknown parser %r (choices: %s)') % tup raise ArgumentError(self, msg) # parse all the remaining options into the namespace @@ -1213,12 +1105,6 @@ class _SubParsersAction(Action): vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, []) getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings) -class _ExtendAction(_AppendAction): - def __call__(self, parser, namespace, values, option_string=None): - items = getattr(namespace, self.dest, None) - items = _copy_items(items) - items.extend(values) - setattr(namespace, self.dest, items) # ============== # Type classes @@ -1235,17 +1121,11 @@ class FileType(object): same values as the builtin open() function. - bufsize -- The file's desired buffer size. Accepts the same values as the builtin open() function. - - encoding -- The file's encoding. Accepts the same values as the - builtin open() function. - - errors -- A string indicating how encoding and decoding errors are to - be handled. Accepts the same value as the builtin open() function. """ - def __init__(self, mode='r', bufsize=-1, encoding=None, errors=None): + def __init__(self, mode='r', bufsize=-1): self._mode = mode self._bufsize = bufsize - self._encoding = encoding - self._errors = errors def __call__(self, string): # the special argument "-" means sys.std{in,out} @@ -1260,19 +1140,14 @@ class FileType(object): # all other arguments are used as file names try: - return open(string, self._mode, self._bufsize, self._encoding, - self._errors) - except OSError as e: - args = {'filename': string, 'error': e} - message = _("can't open '%(filename)s': %(error)s") - raise ArgumentTypeError(message % args) + return open(string, self._mode, self._bufsize) + except IOError as e: + message = _("can't open '%s': %s") + raise ArgumentTypeError(message % (string, e)) def __repr__(self): args = self._mode, self._bufsize - kwargs = [('encoding', self._encoding), ('errors', self._errors)] - args_str = ', '.join([repr(arg) for arg in args if arg != -1] + - ['%s=%r' % (kw, arg) for kw, arg in kwargs - if arg is not None]) + args_str = ', '.join(repr(arg) for arg in args if arg != -1) return '%s(%s)' % (type(self).__name__, args_str) # =========================== @@ -1290,11 +1165,18 @@ class Namespace(_AttributeHolder): for name in kwargs: setattr(self, name, kwargs[name]) + __hash__ = None + def __eq__(self, other): if not isinstance(other, Namespace): return NotImplemented return vars(self) == vars(other) + def __ne__(self, other): + if not isinstance(other, Namespace): + return NotImplemented + return not (self == other) + def __contains__(self, key): return key in self.__dict__ @@ -1328,7 +1210,6 @@ class _ActionsContainer(object): self.register('action', 'help', _HelpAction) self.register('action', 'version', _VersionAction) self.register('action', 'parsers', _SubParsersAction) - self.register('action', 'extend', _ExtendAction) # raise an exception if the conflict handler is invalid self._get_handler() @@ -1412,19 +1293,15 @@ class _ActionsContainer(object): # create the action object, and add it to the parser action_class = self._pop_action_class(kwargs) - if not callable(action_class): + if not _callable(action_class): raise ValueError('unknown action "%s"' % (action_class,)) action = action_class(**kwargs) # raise an error if the action type is not callable 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,)) - if type_func is FileType: - raise ValueError('%r is a FileType class object, instance of it' - ' must be passed' % (type_func,)) - # raise an error if the metavar does not match the type if hasattr(self, "_get_formatter"): try: @@ -1531,16 +1408,17 @@ class _ActionsContainer(object): for option_string in args: # error on strings that don't start with an appropriate prefix if not option_string[0] in self.prefix_chars: - args = {'option': option_string, - 'prefix_chars': self.prefix_chars} - msg = _('invalid option string %(option)r: ' - 'must start with a character %(prefix_chars)r') - raise ValueError(msg % args) + msg = _('invalid option string %r: ' + 'must start with a character %r') + tup = option_string, self.prefix_chars + raise ValueError(msg % tup) # strings starting with two prefix characters are long options option_strings.append(option_string) - if len(option_string) > 1 and option_string[1] in self.prefix_chars: - long_option_strings.append(option_string) + if option_string[0] in self.prefix_chars: + if len(option_string) > 1: + if option_string[1] in self.prefix_chars: + long_option_strings.append(option_string) # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x' dest = kwargs.pop('dest', None) @@ -1586,9 +1464,7 @@ class _ActionsContainer(object): conflict_handler(action, confl_optionals) def _handle_conflict_error(self, action, conflicting_actions): - message = ngettext('conflicting option string: %s', - 'conflicting option strings: %s', - len(conflicting_actions)) + message = _('conflicting option string(s): %s') conflict_string = ', '.join([option_string for option_string, action in conflicting_actions]) @@ -1679,9 +1555,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): - argument_default -- The default value for all arguments - conflict_handler -- String indicating how to handle conflicts - add_help -- Add a -h/-help option - - 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 """ def __init__(self, @@ -1689,15 +1562,22 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): usage=None, description=None, epilog=None, + version=None, parents=[], formatter_class=HelpFormatter, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', - add_help=True, - allow_abbrev=True, - exit_on_error=True): + add_help=True): + + if version is not None: + import warnings + warnings.warn( + """The "version" argument to ArgumentParser is deprecated. """ + """Please use """ + """"add_argument(..., action='version', version="N", ...)" """ + """instead""", DeprecationWarning) superinit = super(ArgumentParser, self).__init__ superinit(description=description, @@ -1712,11 +1592,10 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): self.prog = prog self.usage = usage self.epilog = epilog + self.version = version self.formatter_class = formatter_class self.fromfile_prefix_chars = fromfile_prefix_chars self.add_help = add_help - self.allow_abbrev = allow_abbrev - self.exit_on_error = exit_on_error add_group = self.add_argument_group self._positionals = add_group(_('positional arguments')) @@ -1728,7 +1607,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): return string self.register('type', None, identity) - # add help argument if necessary + # add help and version arguments if necessary # (using explicit default to override global argument_default) default_prefix = '-' if '-' in prefix_chars else prefix_chars[0] if self.add_help: @@ -1736,6 +1615,12 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): default_prefix+'h', default_prefix*2+'help', action='help', default=SUPPRESS, help=_('show this help message and exit')) + if self.version: + self.add_argument( + default_prefix+'v', default_prefix*2+'version', + action='version', default=SUPPRESS, + version=self.version, + help=_("show program's version number and exit")) # add parent arguments and defaults for parent in parents: @@ -1755,6 +1640,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): 'prog', 'usage', 'description', + 'version', 'formatter_class', 'conflict_handler', 'add_help', @@ -1847,19 +1733,15 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): setattr(namespace, dest, self._defaults[dest]) # parse the arguments and exit if there are any errors - if self.exit_on_error: - try: - namespace, args = self._parse_known_args(args, namespace) - except ArgumentError: - err = _sys.exc_info()[1] - self.error(str(err)) - else: + try: namespace, args = self._parse_known_args(args, namespace) - - if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): - args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) - delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) - return namespace, args + if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): + args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) + delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) + return namespace, args + except ArgumentError: + err = _sys.exc_info()[1] + self.error(str(err)) def _parse_known_args(self, arg_strings, namespace): # replace arg strings that are file references @@ -2066,29 +1948,29 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # if we didn't consume all the argument strings, there were extras extras.extend(arg_strings[stop_index:]) - # make sure all required actions were present and also convert - # action defaults which were not given as arguments - required_actions = [] + # if we didn't use all the Positional objects, there were too few + # arg strings supplied. + if positionals: + self.error(_('too few arguments')) + + # make sure all required actions were present, and convert defaults. for action in self._actions: if action not in seen_actions: if action.required: - required_actions.append(_get_action_name(action)) + 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, str) and - hasattr(namespace, action.dest) and - action.default is getattr(namespace, action.dest)): + 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)) - if required_actions: - self.error(_('the following arguments are required: %s') % - ', '.join(required_actions)) - # make sure all required groups had one option present for group in self._mutually_exclusive_groups: if group.required: @@ -2119,14 +2001,17 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # replace arguments referencing files with the file content else: try: - with open(arg_string[1:]) as args_file: + args_file = open(arg_string[1:]) + try: arg_strings = [] for arg_line in args_file.read().splitlines(): for arg in self.convert_arg_line_to_args(arg_line): arg_strings.append(arg) arg_strings = self._read_args_from_files(arg_strings) new_arg_strings.extend(arg_strings) - except OSError: + finally: + args_file.close() + except IOError: err = _sys.exc_info()[1] self.error(str(err)) @@ -2148,11 +2033,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): OPTIONAL: _('expected at most one argument'), ONE_OR_MORE: _('expected at least one argument'), } - msg = nargs_errors.get(action.nargs) - if msg is None: - msg = ngettext('expected %s argument', - 'expected %s arguments', - action.nargs) % action.nargs + default = _('expected %s argument(s)') % action.nargs + msg = nargs_errors.get(action.nargs, default) raise ArgumentError(action, msg) # return the number of arguments matched @@ -2199,24 +2081,22 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): action = self._option_string_actions[option_string] return action, option_string, explicit_arg - if self.allow_abbrev or not arg_string.startswith('--'): - # search through all possible prefixes of the option string - # and all actions in the parser for possible interpretations - option_tuples = self._get_option_tuples(arg_string) - - # if multiple actions match, the option string was ambiguous - if len(option_tuples) > 1: - options = ', '.join([option_string - for action, option_string, explicit_arg in option_tuples]) - args = {'option': arg_string, 'matches': options} - msg = _('ambiguous option: %(option)s could match %(matches)s') - self.error(msg % args) - - # if exactly one action matched, this segmentation is good, - # so return the parsed action - elif len(option_tuples) == 1: - option_tuple, = option_tuples - return option_tuple + # search through all possible prefixes of the option string + # and all actions in the parser for possible interpretations + option_tuples = self._get_option_tuples(arg_string) + + # if multiple actions match, the option string was ambiguous + if len(option_tuples) > 1: + options = ', '.join([option_string + for action, option_string, explicit_arg in option_tuples]) + tup = arg_string, options + self.error(_('ambiguous option: %s could match %s') % tup) + + # if exactly one action matched, this segmentation is good, + # so return the parsed action + elif len(option_tuples) == 1: + option_tuple, = option_tuples + return option_tuple # if it was not found as an option, but it looks like a negative # number, it was meant to be positional @@ -2306,10 +2186,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): elif nargs == PARSER: nargs_pattern = '(-*A[-AO]*)' - # suppress action, like nargs=0 - elif nargs == SUPPRESS: - nargs_pattern = '(-*-*)' - # all others should be integers else: nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs) @@ -2323,91 +2199,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): return nargs_pattern # ======================== - # Alt command line argument parsing, allowing free intermix - # ======================== - - def parse_intermixed_args(self, args=None, namespace=None): - args, argv = self.parse_known_intermixed_args(args, namespace) - if argv: - msg = _('unrecognized arguments: %s') - self.error(msg % ' '.join(argv)) - return args - - def parse_known_intermixed_args(self, args=None, namespace=None): - # returns a namespace and list of extras - # - # positional can be freely intermixed with optionals. optionals are - # first parsed with all positional arguments deactivated. The 'extras' - # are then parsed. If the parser definition is incompatible with the - # intermixed assumptions (e.g. use of REMAINDER, subparsers) a - # TypeError is raised. - # - # positionals are 'deactivated' by setting nargs and default to - # SUPPRESS. This blocks the addition of that positional to the - # namespace - - positionals = self._get_positional_actions() - a = [action for action in positionals - if action.nargs in [PARSER, REMAINDER]] - if a: - raise TypeError('parse_intermixed_args: positional arg' - ' with nargs=%s'%a[0].nargs) - - if [action.dest for group in self._mutually_exclusive_groups - for action in group._group_actions if action in positionals]: - raise TypeError('parse_intermixed_args: positional in' - ' mutuallyExclusiveGroup') - - try: - save_usage = self.usage - try: - if self.usage is None: - # capture the full usage for use in error messages - self.usage = self.format_usage()[7:] - for action in positionals: - # deactivate positionals - action.save_nargs = action.nargs - # action.nargs = 0 - action.nargs = SUPPRESS - action.save_default = action.default - action.default = SUPPRESS - namespace, remaining_args = self.parse_known_args(args, - namespace) - for action in positionals: - # remove the empty positional values from namespace - if (hasattr(namespace, action.dest) - and getattr(namespace, action.dest)==[]): - from warnings import warn - warn('Do not expect %s in %s' % (action.dest, namespace)) - delattr(namespace, action.dest) - finally: - # restore nargs and usage before exiting - for action in positionals: - action.nargs = action.save_nargs - action.default = action.save_default - optionals = self._get_optional_actions() - try: - # parse positionals. optionals aren't normally required, but - # they could be, so make sure they aren't. - for action in optionals: - action.save_required = action.required - action.required = False - for group in self._mutually_exclusive_groups: - group.save_required = group.required - group.required = False - namespace, extras = self.parse_known_args(remaining_args, - namespace) - finally: - # restore parser values before exiting - for action in optionals: - action.required = action.save_required - for group in self._mutually_exclusive_groups: - group.required = group.save_required - finally: - self.usage = save_usage - return namespace, extras - - # ======================== # Value conversion methods # ======================== def _get_values(self, action, arg_strings): @@ -2424,7 +2215,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): value = action.const else: value = action.default - if isinstance(value, str): + if isinstance(value, basestring): value = self._get_value(action, value) self._check_value(action, value) @@ -2453,10 +2244,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): value = [self._get_value(action, v) for v in arg_strings] self._check_value(action, value[0]) - # SUPPRESS argument does not put anything in the namespace - elif action.nargs == SUPPRESS: - value = SUPPRESS - # all other types of nargs produce a list else: value = [self._get_value(action, v) for v in arg_strings] @@ -2468,7 +2255,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): def _get_value(self, action, arg_string): type_func = self._registry_get('type', action.type, action.type) - if not callable(type_func): + if not _callable(type_func): msg = _('%r is not callable') raise ArgumentError(action, msg % type_func) @@ -2485,9 +2272,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # TypeErrors or ValueErrors also indicate errors except (TypeError, ValueError): name = getattr(action.type, '__name__', repr(action.type)) - args = {'type': name, 'value': arg_string} - msg = _('invalid %(type)s value: %(value)r') - raise ArgumentError(action, msg % args) + msg = _('invalid %s value: %r') + raise ArgumentError(action, msg % (name, arg_string)) # return the converted value return result @@ -2495,10 +2281,9 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): 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) + tup = value, ', '.join(map(repr, action.choices)) + msg = _('invalid choice: %r (choose from %s)') % tup + raise ArgumentError(action, msg) # ======================= # Help-formatting methods @@ -2532,6 +2317,16 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # determine help from format above return formatter.format_help() + def format_version(self): + import warnings + warnings.warn( + 'The format_version method is deprecated -- the "version" ' + 'argument to ArgumentParser is no longer supported.', + DeprecationWarning) + formatter = self._get_formatter() + formatter.add_text(self.version) + return formatter.format_help() + def _get_formatter(self): return self.formatter_class(prog=self.prog) @@ -2548,6 +2343,14 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): file = _sys.stdout self._print_message(self.format_help(), file) + def print_version(self, file=None): + import warnings + warnings.warn( + 'The print_version method is deprecated -- the "version" ' + 'argument to ArgumentParser is no longer supported.', + DeprecationWarning) + self._print_message(self.format_version(), file) + def _print_message(self, message, file=None): if message: if file is None: @@ -2572,5 +2375,4 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): should either exit or raise an exception. """ self.print_usage(_sys.stderr) - args = {'prog': self.prog, 'message': message} - self.exit(2, _('%(prog)s: error: %(message)s\n') % args) + self.exit(2, _('%s: error: %s\n') % (self.prog, message)) |