+# -*- coding: utf-8 -*-\r
+\r
+# Copyright © 2006-2009 Steven J. Bethard <steven.bethard@gmail.com>.\r
+#\r
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
+# use this file except in compliance with the License. You may obtain a copy\r
+# of the License at\r
+#\r
+# http://www.apache.org/licenses/LICENSE-2.0\r
+#\r
+# Unless required by applicable law or agreed to in writing, software\r
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
+# License for the specific language governing permissions and limitations\r
+# under the License.\r
+\r
+"""Command-line parsing library\r
+\r
+This module is an optparse-inspired command-line parsing library that:\r
+\r
+ - handles both optional and positional arguments\r
+ - produces highly informative usage messages\r
+ - supports parsers that dispatch to sub-parsers\r
+\r
+The following is a simple usage example that sums integers from the\r
+command-line and writes the result to a file::\r
+\r
+ parser = argparse.ArgumentParser(\r
+ description='sum the integers at the command line')\r
+ parser.add_argument(\r
+ 'integers', metavar='int', nargs='+', type=int,\r
+ help='an integer to be summed')\r
+ parser.add_argument(\r
+ '--log', default=sys.stdout, type=argparse.FileType('w'),\r
+ help='the file where the sum should be written')\r
+ args = parser.parse_args()\r
+ args.log.write('%s' % sum(args.integers))\r
+ args.log.close()\r
+\r
+The module contains the following public classes:\r
+\r
+ - ArgumentParser -- The main entry point for command-line parsing. As the\r
+ example above shows, the add_argument() method is used to populate\r
+ the parser with actions for optional and positional arguments. Then\r
+ the parse_args() method is invoked to convert the args at the\r
+ command-line into an object with attributes.\r
+\r
+ - ArgumentError -- The exception raised by ArgumentParser objects when\r
+ there are errors with the parser's actions. Errors raised while\r
+ parsing the command-line are caught by ArgumentParser and emitted\r
+ as command-line messages.\r
+\r
+ - FileType -- A factory for defining types of files to be created. As the\r
+ example above shows, instances of FileType are typically passed as\r
+ the type= argument of add_argument() calls.\r
+\r
+ - Action -- The base class for parser actions. Typically actions are\r
+ selected by passing strings like 'store_true' or 'append_const' to\r
+ the action= argument of add_argument(). However, for greater\r
+ customization of ArgumentParser actions, subclasses of Action may\r
+ be defined and passed as the action= argument.\r
+\r
+ - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,\r
+ ArgumentDefaultsHelpFormatter -- Formatter classes which\r
+ may be passed as the formatter_class= argument to the\r
+ ArgumentParser constructor. HelpFormatter is the default,\r
+ RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser\r
+ not to change the formatting for help text, and\r
+ ArgumentDefaultsHelpFormatter adds information about argument defaults\r
+ to the help.\r
+\r
+All other classes in this module are considered implementation details.\r
+(Also note that HelpFormatter and RawDescriptionHelpFormatter are only\r
+considered public as object names -- the API of the formatter objects is\r
+still considered an implementation detail.)\r
+"""\r
+\r
+__version__ = '1.0.1'\r
+__all__ = [\r
+ 'ArgumentParser',\r
+ 'ArgumentError',\r
+ 'Namespace',\r
+ 'Action',\r
+ 'FileType',\r
+ 'HelpFormatter',\r
+ 'RawDescriptionHelpFormatter',\r
+ 'RawTextHelpFormatter'\r
+ 'ArgumentDefaultsHelpFormatter',\r
+]\r
+\r
+\r
+import copy as _copy\r
+import os as _os\r
+import re as _re\r
+import sys as _sys\r
+import textwrap as _textwrap\r
+\r
+from gettext import gettext as _\r
+\r
+try:\r
+ _set = set\r
+except NameError:\r
+ from sets import Set as _set\r
+\r
+try:\r
+ _basestring = basestring\r
+except NameError:\r
+ _basestring = str\r
+\r
+try:\r
+ _sorted = sorted\r
+except NameError:\r
+\r
+ def _sorted(iterable, reverse=False):\r
+ result = list(iterable)\r
+ result.sort()\r
+ if reverse:\r
+ result.reverse()\r
+ return result\r
+\r
+# silence Python 2.6 buggy warnings about Exception.message\r
+if _sys.version_info[:2] == (2, 6):\r
+ import warnings\r
+ warnings.filterwarnings(\r
+ action='ignore',\r
+ message='BaseException.message has been deprecated as of Python 2.6',\r
+ category=DeprecationWarning,\r
+ module='argparse')\r
+\r
+\r
+SUPPRESS = '==SUPPRESS=='\r
+\r
+OPTIONAL = '?'\r
+ZERO_OR_MORE = '*'\r
+ONE_OR_MORE = '+'\r
+PARSER = '==PARSER=='\r
+\r
+# =============================\r
+# Utility functions and classes\r
+# =============================\r
+\r
+class _AttributeHolder(object):\r
+ """Abstract base class that provides __repr__.\r
+\r
+ The __repr__ method returns a string in the format::\r
+ ClassName(attr=name, attr=name, ...)\r
+ The attributes are determined either by a class-level attribute,\r
+ '_kwarg_names', or by inspecting the instance __dict__.\r
+ """\r
+\r
+ def __repr__(self):\r
+ type_name = type(self).__name__\r
+ arg_strings = []\r
+ for arg in self._get_args():\r
+ arg_strings.append(repr(arg))\r
+ for name, value in self._get_kwargs():\r
+ arg_strings.append('%s=%r' % (name, value))\r
+ return '%s(%s)' % (type_name, ', '.join(arg_strings))\r
+\r
+ def _get_kwargs(self):\r
+ return _sorted(self.__dict__.items())\r
+\r
+ def _get_args(self):\r
+ return []\r
+\r
+\r
+def _ensure_value(namespace, name, value):\r
+ if getattr(namespace, name, None) is None:\r
+ setattr(namespace, name, value)\r
+ return getattr(namespace, name)\r
+\r
+\r
+# ===============\r
+# Formatting Help\r
+# ===============\r
+\r
+class HelpFormatter(object):\r
+ """Formatter for generating usage messages and argument help strings.\r
+\r
+ Only the name of this class is considered a public API. All the methods\r
+ provided by the class are considered an implementation detail.\r
+ """\r
+\r
+ def __init__(self,\r
+ prog,\r
+ indent_increment=2,\r
+ max_help_position=24,\r
+ width=None):\r
+\r
+ # default setting for width\r
+ if width is None:\r
+ try:\r
+ width = int(_os.environ['COLUMNS'])\r
+ except (KeyError, ValueError):\r
+ width = 80\r
+ width -= 2\r
+\r
+ self._prog = prog\r
+ self._indent_increment = indent_increment\r
+ self._max_help_position = max_help_position\r
+ self._width = width\r
+\r
+ self._current_indent = 0\r
+ self._level = 0\r
+ self._action_max_length = 0\r
+\r
+ self._root_section = self._Section(self, None)\r
+ self._current_section = self._root_section\r
+\r
+ self._whitespace_matcher = _re.compile(r'\s+')\r
+ self._long_break_matcher = _re.compile(r'\n\n\n+')\r
+\r
+ # ===============================\r
+ # Section and indentation methods\r
+ # ===============================\r
+ def _indent(self):\r
+ self._current_indent += self._indent_increment\r
+ self._level += 1\r
+\r
+ def _dedent(self):\r
+ self._current_indent -= self._indent_increment\r
+ assert self._current_indent >= 0, 'Indent decreased below 0.'\r
+ self._level -= 1\r
+\r
+ class _Section(object):\r
+\r
+ def __init__(self, formatter, parent, heading=None):\r
+ self.formatter = formatter\r
+ self.parent = parent\r
+ self.heading = heading\r
+ self.items = []\r
+\r
+ def format_help(self):\r
+ # format the indented section\r
+ if self.parent is not None:\r
+ self.formatter._indent()\r
+ join = self.formatter._join_parts\r
+ for func, args in self.items:\r
+ func(*args)\r
+ item_help = join([func(*args) for func, args in self.items])\r
+ if self.parent is not None:\r
+ self.formatter._dedent()\r
+\r
+ # return nothing if the section was empty\r
+ if not item_help:\r
+ return ''\r
+\r
+ # add the heading if the section was non-empty\r
+ if self.heading is not SUPPRESS and self.heading is not None:\r
+ current_indent = self.formatter._current_indent\r
+ heading = '%*s%s:\n' % (current_indent, '', self.heading)\r
+ else:\r
+ heading = ''\r
+\r
+ # join the section-initial newline, the heading and the help\r
+ return join(['\n', heading, item_help, '\n'])\r
+\r
+ def _add_item(self, func, args):\r
+ self._current_section.items.append((func, args))\r
+\r
+ # ========================\r
+ # Message building methods\r
+ # ========================\r
+ def start_section(self, heading):\r
+ self._indent()\r
+ section = self._Section(self, self._current_section, heading)\r
+ self._add_item(section.format_help, [])\r
+ self._current_section = section\r
+\r
+ def end_section(self):\r
+ self._current_section = self._current_section.parent\r
+ self._dedent()\r
+\r
+ def add_text(self, text):\r
+ if text is not SUPPRESS and text is not None:\r
+ self._add_item(self._format_text, [text])\r
+\r
+ def add_usage(self, usage, actions, groups, prefix=None):\r
+ if usage is not SUPPRESS:\r
+ args = usage, actions, groups, prefix\r
+ self._add_item(self._format_usage, args)\r
+\r
+ def add_argument(self, action):\r
+ if action.help is not SUPPRESS:\r
+\r
+ # find all invocations\r
+ get_invocation = self._format_action_invocation\r
+ invocations = [get_invocation(action)]\r
+ for subaction in self._iter_indented_subactions(action):\r
+ invocations.append(get_invocation(subaction))\r
+\r
+ # update the maximum item length\r
+ invocation_length = max([len(s) for s in invocations])\r
+ action_length = invocation_length + self._current_indent\r
+ self._action_max_length = max(self._action_max_length,\r
+ action_length)\r
+\r
+ # add the item to the list\r
+ self._add_item(self._format_action, [action])\r
+\r
+ def add_arguments(self, actions):\r
+ for action in actions:\r
+ self.add_argument(action)\r
+\r
+ # =======================\r
+ # Help-formatting methods\r
+ # =======================\r
+ def format_help(self):\r
+ help = self._root_section.format_help()\r
+ if help:\r
+ help = self._long_break_matcher.sub('\n\n', help)\r
+ help = help.strip('\n') + '\n'\r
+ return help\r
+\r
+ def _join_parts(self, part_strings):\r
+ return ''.join([part\r
+ for part in part_strings\r
+ if part and part is not SUPPRESS])\r
+\r
+ def _format_usage(self, usage, actions, groups, prefix):\r
+ if prefix is None:\r
+ prefix = _('usage: ')\r
+\r
+ # if usage is specified, use that\r
+ if usage is not None:\r
+ usage = usage % dict(prog=self._prog)\r
+\r
+ # if no optionals or positionals are available, usage is just prog\r
+ elif usage is None and not actions:\r
+ usage = '%(prog)s' % dict(prog=self._prog)\r
+\r
+ # if optionals and positionals are available, calculate usage\r
+ elif usage is None:\r
+ prog = '%(prog)s' % dict(prog=self._prog)\r
+\r
+ # split optionals from positionals\r
+ optionals = []\r
+ positionals = []\r
+ for action in actions:\r
+ if action.option_strings:\r
+ optionals.append(action)\r
+ else:\r
+ positionals.append(action)\r
+\r
+ # build full usage string\r
+ format = self._format_actions_usage\r
+ action_usage = format(optionals + positionals, groups)\r
+ usage = ' '.join([s for s in [prog, action_usage] if s])\r
+\r
+ # wrap the usage parts if it's too long\r
+ text_width = self._width - self._current_indent\r
+ if len(prefix) + len(usage) > text_width:\r
+\r
+ # break usage into wrappable parts\r
+ part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'\r
+ opt_usage = format(optionals, groups)\r
+ pos_usage = format(positionals, groups)\r
+ opt_parts = _re.findall(part_regexp, opt_usage)\r
+ pos_parts = _re.findall(part_regexp, pos_usage)\r
+ assert ' '.join(opt_parts) == opt_usage\r
+ assert ' '.join(pos_parts) == pos_usage\r
+\r
+ # helper for wrapping lines\r
+ def get_lines(parts, indent, prefix=None):\r
+ lines = []\r
+ line = []\r
+ if prefix is not None:\r
+ line_len = len(prefix) - 1\r
+ else:\r
+ line_len = len(indent) - 1\r
+ for part in parts:\r
+ if line_len + 1 + len(part) > text_width:\r
+ lines.append(indent + ' '.join(line))\r
+ line = []\r
+ line_len = len(indent) - 1\r
+ line.append(part)\r
+ line_len += len(part) + 1\r
+ if line:\r
+ lines.append(indent + ' '.join(line))\r
+ if prefix is not None:\r
+ lines[0] = lines[0][len(indent):]\r
+ return lines\r
+\r
+ # if prog is short, follow it with optionals or positionals\r
+ if len(prefix) + len(prog) <= 0.75 * text_width:\r
+ indent = ' ' * (len(prefix) + len(prog) + 1)\r
+ if opt_parts:\r
+ lines = get_lines([prog] + opt_parts, indent, prefix)\r
+ lines.extend(get_lines(pos_parts, indent))\r
+ elif pos_parts:\r
+ lines = get_lines([prog] + pos_parts, indent, prefix)\r
+ else:\r
+ lines = [prog]\r
+\r
+ # if prog is long, put it on its own line\r
+ else:\r
+ indent = ' ' * len(prefix)\r
+ parts = opt_parts + pos_parts\r
+ lines = get_lines(parts, indent)\r
+ if len(lines) > 1:\r
+ lines = []\r
+ lines.extend(get_lines(opt_parts, indent))\r
+ lines.extend(get_lines(pos_parts, indent))\r
+ lines = [prog] + lines\r
+\r
+ # join lines into usage\r
+ usage = '\n'.join(lines)\r
+\r
+ # prefix with 'usage:'\r
+ return '%s%s\n\n' % (prefix, usage)\r
+\r
+ def _format_actions_usage(self, actions, groups):\r
+ # find group indices and identify actions in groups\r
+ group_actions = _set()\r
+ inserts = {}\r
+ for group in groups:\r
+ try:\r
+ start = actions.index(group._group_actions[0])\r
+ except ValueError:\r
+ continue\r
+ else:\r
+ end = start + len(group._group_actions)\r
+ if actions[start:end] == group._group_actions:\r
+ for action in group._group_actions:\r
+ group_actions.add(action)\r
+ if not group.required:\r
+ inserts[start] = '['\r
+ inserts[end] = ']'\r
+ else:\r
+ inserts[start] = '('\r
+ inserts[end] = ')'\r
+ for i in range(start + 1, end):\r
+ inserts[i] = '|'\r
+\r
+ # collect all actions format strings\r
+ parts = []\r
+ for i, action in enumerate(actions):\r
+\r
+ # suppressed arguments are marked with None\r
+ # remove | separators for suppressed arguments\r
+ if action.help is SUPPRESS:\r
+ parts.append(None)\r
+ if inserts.get(i) == '|':\r
+ inserts.pop(i)\r
+ elif inserts.get(i + 1) == '|':\r
+ inserts.pop(i + 1)\r
+\r
+ # produce all arg strings\r
+ elif not action.option_strings:\r
+ part = self._format_args(action, action.dest)\r
+\r
+ # if it's in a group, strip the outer []\r
+ if action in group_actions:\r
+ if part[0] == '[' and part[-1] == ']':\r
+ part = part[1:-1]\r
+\r
+ # add the action string to the list\r
+ parts.append(part)\r
+\r
+ # produce the first way to invoke the option in brackets\r
+ else:\r
+ option_string = action.option_strings[0]\r
+\r
+ # if the Optional doesn't take a value, format is:\r
+ # -s or --long\r
+ if action.nargs == 0:\r
+ part = '%s' % option_string\r
+\r
+ # if the Optional takes a value, format is:\r
+ # -s ARGS or --long ARGS\r
+ else:\r
+ default = action.dest.upper()\r
+ args_string = self._format_args(action, default)\r
+ part = '%s %s' % (option_string, args_string)\r
+\r
+ # make it look optional if it's not required or in a group\r
+ if not action.required and action not in group_actions:\r
+ part = '[%s]' % part\r
+\r
+ # add the action string to the list\r
+ parts.append(part)\r
+\r
+ # insert things at the necessary indices\r
+ for i in _sorted(inserts, reverse=True):\r
+ parts[i:i] = [inserts[i]]\r
+\r
+ # join all the action items with spaces\r
+ text = ' '.join([item for item in parts if item is not None])\r
+\r
+ # clean up separators for mutually exclusive groups\r
+ open = r'[\[(]'\r
+ close = r'[\])]'\r
+ text = _re.sub(r'(%s) ' % open, r'\1', text)\r
+ text = _re.sub(r' (%s)' % close, r'\1', text)\r
+ text = _re.sub(r'%s *%s' % (open, close), r'', text)\r
+ text = _re.sub(r'\(([^|]*)\)', r'\1', text)\r
+ text = text.strip()\r
+\r
+ # return the text\r
+ return text\r
+\r
+ def _format_text(self, text):\r
+ text_width = self._width - self._current_indent\r
+ indent = ' ' * self._current_indent\r
+ return self._fill_text(text, text_width, indent) + '\n\n'\r
+\r
+ def _format_action(self, action):\r
+ # determine the required width and the entry label\r
+ help_position = min(self._action_max_length + 2,\r
+ self._max_help_position)\r
+ help_width = self._width - help_position\r
+ action_width = help_position - self._current_indent - 2\r
+ action_header = self._format_action_invocation(action)\r
+\r
+ # ho nelp; start on same line and add a final newline\r
+ if not action.help:\r
+ tup = self._current_indent, '', action_header\r
+ action_header = '%*s%s\n' % tup\r
+\r
+ # short action name; start on the same line and pad two spaces\r
+ elif len(action_header) <= action_width:\r
+ tup = self._current_indent, '', action_width, action_header\r
+ action_header = '%*s%-*s ' % tup\r
+ indent_first = 0\r
+\r
+ # long action name; start on the next line\r
+ else:\r
+ tup = self._current_indent, '', action_header\r
+ action_header = '%*s%s\n' % tup\r
+ indent_first = help_position\r
+\r
+ # collect the pieces of the action help\r
+ parts = [action_header]\r
+\r
+ # if there was help for the action, add lines of help text\r
+ if action.help:\r
+ help_text = self._expand_help(action)\r
+ help_lines = self._split_lines(help_text, help_width)\r
+ parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))\r
+ for line in help_lines[1:]:\r
+ parts.append('%*s%s\n' % (help_position, '', line))\r
+\r
+ # or add a newline if the description doesn't end with one\r
+ elif not action_header.endswith('\n'):\r
+ parts.append('\n')\r
+\r
+ # if there are any sub-actions, add their help as well\r
+ for subaction in self._iter_indented_subactions(action):\r
+ parts.append(self._format_action(subaction))\r
+\r
+ # return a single string\r
+ return self._join_parts(parts)\r
+\r
+ def _format_action_invocation(self, action):\r
+ if not action.option_strings:\r
+ metavar, = self._metavar_formatter(action, action.dest)(1)\r
+ return metavar\r
+\r
+ else:\r
+ parts = []\r
+\r
+ # if the Optional doesn't take a value, format is:\r
+ # -s, --long\r
+ if action.nargs == 0:\r
+ parts.extend(action.option_strings)\r
+\r
+ # if the Optional takes a value, format is:\r
+ # -s ARGS, --long ARGS\r
+ else:\r
+ default = action.dest.upper()\r
+ args_string = self._format_args(action, default)\r
+ for option_string in action.option_strings:\r
+ parts.append('%s %s' % (option_string, args_string))\r
+\r
+ return ', '.join(parts)\r
+\r
+ def _metavar_formatter(self, action, default_metavar):\r
+ if action.metavar is not None:\r
+ result = action.metavar\r
+ elif action.choices is not None:\r
+ choice_strs = [str(choice) for choice in action.choices]\r
+ #result = '{%s}' % ','.join(choice_strs)\r
+ result = ""\r
+ else:\r
+ result = default_metavar\r
+\r
+ def format(tuple_size):\r
+ if isinstance(result, tuple):\r
+ return result\r
+ else:\r
+ return (result, ) * tuple_size\r
+ return format\r
+\r
+ def _format_args(self, action, default_metavar):\r
+ get_metavar = self._metavar_formatter(action, default_metavar)\r
+ if action.nargs is None:\r
+ result = '%s' % get_metavar(1)\r
+ elif action.nargs == OPTIONAL:\r
+ result = '[%s]' % get_metavar(1)\r
+ elif action.nargs == ZERO_OR_MORE:\r
+ result = '[%s [%s ...]]' % get_metavar(2)\r
+ elif action.nargs == ONE_OR_MORE:\r
+ result = '%s [%s ...]' % get_metavar(2)\r
+ elif action.nargs is PARSER:\r
+ result = '%s ...' % get_metavar(1)\r
+ else:\r
+ formats = ['%s' for _ in range(action.nargs)]\r
+ result = ' '.join(formats) % get_metavar(action.nargs)\r
+ return result\r
+\r
+ def _expand_help(self, action):\r
+ params = dict(vars(action), prog=self._prog)\r
+ for name in list(params):\r
+ if params[name] is SUPPRESS:\r
+ del params[name]\r
+ if params.get('choices') is not None:\r
+ choices_str = ', '.join([str(c) for c in params['choices']])\r
+ params['choices'] = choices_str\r
+ return self._get_help_string(action) % params\r
+\r
+ def _iter_indented_subactions(self, action):\r
+ try:\r
+ get_subactions = action._get_subactions\r
+ except AttributeError:\r
+ pass\r
+ else:\r
+ self._indent()\r
+ for subaction in get_subactions():\r
+ yield subaction\r
+ self._dedent()\r
+\r
+ def _split_lines(self, text, width):\r
+ text = self._whitespace_matcher.sub(' ', text).strip()\r
+ return _textwrap.wrap(text, width)\r
+\r
+ def _fill_text(self, text, width, indent):\r
+ text = self._whitespace_matcher.sub(' ', text).strip()\r
+ return _textwrap.fill(text, width, initial_indent=indent,\r
+ subsequent_indent=indent)\r
+\r
+ def _get_help_string(self, action):\r
+ return action.help\r
+\r
+\r
+class RawDescriptionHelpFormatter(HelpFormatter):\r
+ """Help message formatter which retains any formatting in descriptions.\r
+\r
+ Only the name of this class is considered a public API. All the methods\r
+ provided by the class are considered an implementation detail.\r
+ """\r
+\r
+ def _fill_text(self, text, width, indent):\r
+ return ''.join([indent + line for line in text.splitlines(True)])\r
+\r
+\r
+class RawTextHelpFormatter(RawDescriptionHelpFormatter):\r
+ """Help message formatter which retains formatting of all help text.\r
+\r
+ Only the name of this class is considered a public API. All the methods\r
+ provided by the class are considered an implementation detail.\r
+ """\r
+\r
+ def _split_lines(self, text, width):\r
+ return text.splitlines()\r
+\r
+\r
+class ArgumentDefaultsHelpFormatter(HelpFormatter):\r
+ """Help message formatter which adds default values to argument help.\r
+\r
+ Only the name of this class is considered a public API. All the methods\r
+ provided by the class are considered an implementation detail.\r
+ """\r
+\r
+ def _get_help_string(self, action):\r
+ help = action.help\r
+ if '%(default)' not in action.help:\r
+ if action.default is not SUPPRESS:\r
+ defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]\r
+ if action.option_strings or action.nargs in defaulting_nargs:\r
+ help += ' (default: %(default)s)'\r
+ return help\r
+\r
+\r
+# =====================\r
+# Options and Arguments\r
+# =====================\r
+\r
+def _get_action_name(argument):\r
+ if argument is None:\r
+ return None\r
+ elif argument.option_strings:\r
+ return '/'.join(argument.option_strings)\r
+ elif argument.metavar not in (None, SUPPRESS):\r
+ return argument.metavar\r
+ elif argument.dest not in (None, SUPPRESS):\r
+ return argument.dest\r
+ else:\r
+ return None\r
+\r
+\r
+class ArgumentError(Exception):\r
+ """An error from creating or using an argument (optional or positional).\r
+\r
+ The string value of this exception is the message, augmented with\r
+ information about the argument that caused it.\r
+ """\r
+\r
+ def __init__(self, argument, message):\r
+ self.argument_name = _get_action_name(argument)\r
+ self.message = message\r
+\r
+ def __str__(self):\r
+ if self.argument_name is None:\r
+ format = '%(message)s'\r
+ else:\r
+ format = 'argument %(argument_name)s: %(message)s'\r
+ return format % dict(message=self.message,\r
+ argument_name=self.argument_name)\r
+\r
+# ==============\r
+# Action classes\r
+# ==============\r
+\r
+class Action(_AttributeHolder):\r
+ """Information about how to convert command line strings to Python objects.\r
+\r
+ Action objects are used by an ArgumentParser to represent the information\r
+ needed to parse a single argument from one or more strings from the\r
+ command line. The keyword arguments to the Action constructor are also\r
+ all attributes of Action instances.\r
+\r
+ Keyword Arguments:\r
+\r
+ - option_strings -- A list of command-line option strings which\r
+ should be associated with this action.\r
+\r
+ - dest -- The name of the attribute to hold the created object(s)\r
+\r
+ - nargs -- The number of command-line arguments that should be\r
+ consumed. By default, one argument will be consumed and a single\r
+ value will be produced. Other values include:\r
+ - N (an integer) consumes N arguments (and produces a list)\r
+ - '?' consumes zero or one arguments\r
+ - '*' consumes zero or more arguments (and produces a list)\r
+ - '+' consumes one or more arguments (and produces a list)\r
+ Note that the difference between the default and nargs=1 is that\r
+ with the default, a single value will be produced, while with\r
+ nargs=1, a list containing a single value will be produced.\r
+\r
+ - const -- The value to be produced if the option is specified and the\r
+ option uses an action that takes no values.\r
+\r
+ - default -- The value to be produced if the option is not specified.\r
+\r
+ - type -- The type which the command-line arguments should be converted\r
+ to, should be one of 'string', 'int', 'float', 'complex' or a\r
+ callable object that accepts a single string argument. If None,\r
+ 'string' is assumed.\r
+\r
+ - choices -- A container of values that should be allowed. If not None,\r
+ after a command-line argument has been converted to the appropriate\r
+ type, an exception will be raised if it is not a member of this\r
+ collection.\r
+\r
+ - required -- True if the action must always be specified at the\r
+ command line. This is only meaningful for optional command-line\r
+ arguments.\r
+\r
+ - help -- The help string describing the argument.\r
+\r
+ - metavar -- The name to be used for the option's argument with the\r
+ help string. If None, the 'dest' value will be used as the name.\r
+ """\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest,\r
+ nargs=None,\r
+ const=None,\r
+ default=None,\r
+ type=None,\r
+ choices=None,\r
+ required=False,\r
+ help=None,\r
+ metavar=None):\r
+ self.option_strings = option_strings\r
+ self.dest = dest\r
+ self.nargs = nargs\r
+ self.const = const\r
+ self.default = default\r
+ self.type = type\r
+ self.choices = choices\r
+ self.required = required\r
+ self.help = help\r
+ self.metavar = metavar\r
+\r
+ def _get_kwargs(self):\r
+ names = [\r
+ 'option_strings',\r
+ 'dest',\r
+ 'nargs',\r
+ 'const',\r
+ 'default',\r
+ 'type',\r
+ 'choices',\r
+ 'help',\r
+ 'metavar',\r
+ ]\r
+ return [(name, getattr(self, name)) for name in names]\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ raise NotImplementedError(_('.__call__() not defined'))\r
+\r
+\r
+class _StoreAction(Action):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest,\r
+ nargs=None,\r
+ const=None,\r
+ default=None,\r
+ type=None,\r
+ choices=None,\r
+ required=False,\r
+ help=None,\r
+ metavar=None):\r
+ if nargs == 0:\r
+ raise ValueError('nargs for store actions must be > 0; if you '\r
+ 'have nothing to store, actions such as store '\r
+ 'true or store const may be more appropriate')\r
+ if const is not None and nargs != OPTIONAL:\r
+ raise ValueError('nargs must be %r to supply const' % OPTIONAL)\r
+ super(_StoreAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ nargs=nargs,\r
+ const=const,\r
+ default=default,\r
+ type=type,\r
+ choices=choices,\r
+ required=required,\r
+ help=help,\r
+ metavar=metavar)\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ setattr(namespace, self.dest, values)\r
+\r
+\r
+class _StoreConstAction(Action):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest,\r
+ const,\r
+ default=None,\r
+ required=False,\r
+ help=None,\r
+ metavar=None):\r
+ super(_StoreConstAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ nargs=0,\r
+ const=const,\r
+ default=default,\r
+ required=required,\r
+ help=help)\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ setattr(namespace, self.dest, self.const)\r
+\r
+\r
+class _StoreTrueAction(_StoreConstAction):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest,\r
+ default=False,\r
+ required=False,\r
+ help=None):\r
+ super(_StoreTrueAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ const=True,\r
+ default=default,\r
+ required=required,\r
+ help=help)\r
+\r
+\r
+class _StoreFalseAction(_StoreConstAction):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest,\r
+ default=True,\r
+ required=False,\r
+ help=None):\r
+ super(_StoreFalseAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ const=False,\r
+ default=default,\r
+ required=required,\r
+ help=help)\r
+\r
+\r
+class _AppendAction(Action):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest,\r
+ nargs=None,\r
+ const=None,\r
+ default=None,\r
+ type=None,\r
+ choices=None,\r
+ required=False,\r
+ help=None,\r
+ metavar=None):\r
+ if nargs == 0:\r
+ raise ValueError('nargs for append actions must be > 0; if arg '\r
+ 'strings are not supplying the value to append, '\r
+ 'the append const action may be more appropriate')\r
+ if const is not None and nargs != OPTIONAL:\r
+ raise ValueError('nargs must be %r to supply const' % OPTIONAL)\r
+ super(_AppendAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ nargs=nargs,\r
+ const=const,\r
+ default=default,\r
+ type=type,\r
+ choices=choices,\r
+ required=required,\r
+ help=help,\r
+ metavar=metavar)\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ items = _copy.copy(_ensure_value(namespace, self.dest, []))\r
+ items.append(values)\r
+ setattr(namespace, self.dest, items)\r
+\r
+\r
+class _AppendConstAction(Action):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest,\r
+ const,\r
+ default=None,\r
+ required=False,\r
+ help=None,\r
+ metavar=None):\r
+ super(_AppendConstAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ nargs=0,\r
+ const=const,\r
+ default=default,\r
+ required=required,\r
+ help=help,\r
+ metavar=metavar)\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ items = _copy.copy(_ensure_value(namespace, self.dest, []))\r
+ items.append(self.const)\r
+ setattr(namespace, self.dest, items)\r
+\r
+\r
+class _CountAction(Action):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest,\r
+ default=None,\r
+ required=False,\r
+ help=None):\r
+ super(_CountAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ nargs=0,\r
+ default=default,\r
+ required=required,\r
+ help=help)\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ new_count = _ensure_value(namespace, self.dest, 0) + 1\r
+ setattr(namespace, self.dest, new_count)\r
+\r
+\r
+class _HelpAction(Action):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest=SUPPRESS,\r
+ default=SUPPRESS,\r
+ help=None):\r
+ super(_HelpAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ default=default,\r
+ nargs=0,\r
+ help=help)\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ parser.print_help()\r
+ parser.exit()\r
+\r
+\r
+class _VersionAction(Action):\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ dest=SUPPRESS,\r
+ default=SUPPRESS,\r
+ help=None):\r
+ super(_VersionAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ default=default,\r
+ nargs=0,\r
+ help=help)\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ parser.print_version()\r
+ parser.exit()\r
+\r
+\r
+class _SubParsersAction(Action):\r
+\r
+ class _ChoicesPseudoAction(Action):\r
+\r
+ def __init__(self, name, help):\r
+ sup = super(_SubParsersAction._ChoicesPseudoAction, self)\r
+ sup.__init__(option_strings=[], dest=name, help=help)\r
+\r
+ def __init__(self,\r
+ option_strings,\r
+ prog,\r
+ parser_class,\r
+ dest=SUPPRESS,\r
+ help=None,\r
+ metavar=None):\r
+\r
+ self._prog_prefix = prog\r
+ self._parser_class = parser_class\r
+ self._name_parser_map = {}\r
+ self._choices_actions = []\r
+\r
+ super(_SubParsersAction, self).__init__(\r
+ option_strings=option_strings,\r
+ dest=dest,\r
+ nargs=PARSER,\r
+ choices=self._name_parser_map,\r
+ help=help,\r
+ metavar=metavar)\r
+\r
+ def add_parser(self, name, **kwargs):\r
+ # set prog from the existing prefix\r
+ if kwargs.get('prog') is None:\r
+ kwargs['prog'] = '%s %s' % (self._prog_prefix, name)\r
+\r
+ # create a pseudo-action to hold the choice help\r
+ if 'help' in kwargs:\r
+ help = kwargs.pop('help')\r
+ choice_action = self._ChoicesPseudoAction(name, help)\r
+ self._choices_actions.append(choice_action)\r
+\r
+ # create the parser and add it to the map\r
+ parser = self._parser_class(**kwargs)\r
+ self._name_parser_map[name] = parser\r
+ return parser\r
+\r
+ def _get_subactions(self):\r
+ return self._choices_actions\r
+\r
+ def __call__(self, parser, namespace, values, option_string=None):\r
+ parser_name = values[0]\r
+ arg_strings = values[1:]\r
+\r
+ # set the parser name if requested\r
+ if self.dest is not SUPPRESS:\r
+ setattr(namespace, self.dest, parser_name)\r
+\r
+ # select the parser\r
+ try:\r
+ parser = self._name_parser_map[parser_name]\r
+ except KeyError:\r
+ tup = parser_name, ', '.join(self._name_parser_map)\r
+ msg = _('unknown parser %r (choices: %s)' % tup)\r
+ raise ArgumentError(self, msg)\r
+\r
+ # parse all the remaining options into the namespace\r
+ parser.parse_args(arg_strings, namespace)\r
+\r
+\r
+# ==============\r
+# Type classes\r
+# ==============\r
+\r
+class FileType(object):\r
+ """Factory for creating file object types\r
+\r
+ Instances of FileType are typically passed as type= arguments to the\r
+ ArgumentParser add_argument() method.\r
+\r
+ Keyword Arguments:\r
+ - mode -- A string indicating how the file is to be opened. Accepts the\r
+ same values as the builtin open() function.\r
+ - bufsize -- The file's desired buffer size. Accepts the same values as\r
+ the builtin open() function.\r
+ """\r
+\r
+ def __init__(self, mode='r', bufsize=None):\r
+ self._mode = mode\r
+ self._bufsize = bufsize\r
+\r
+ def __call__(self, string):\r
+ # the special argument "-" means sys.std{in,out}\r
+ if string == '-':\r
+ if 'r' in self._mode:\r
+ return _sys.stdin\r
+ elif 'w' in self._mode:\r
+ return _sys.stdout\r
+ else:\r
+ msg = _('argument "-" with mode %r' % self._mode)\r
+ raise ValueError(msg)\r
+\r
+ # all other arguments are used as file names\r
+ if self._bufsize:\r
+ return open(string, self._mode, self._bufsize)\r
+ else:\r
+ return open(string, self._mode)\r
+\r
+ def __repr__(self):\r
+ args = [self._mode, self._bufsize]\r
+ args_str = ', '.join([repr(arg) for arg in args if arg is not None])\r
+ return '%s(%s)' % (type(self).__name__, args_str)\r
+\r
+# ===========================\r
+# Optional and Positional Parsing\r
+# ===========================\r
+\r
+class Namespace(_AttributeHolder):\r
+ """Simple object for storing attributes.\r
+\r
+ Implements equality by attribute names and values, and provides a simple\r
+ string representation.\r
+ """\r
+\r
+ def __init__(self, **kwargs):\r
+ for name in kwargs:\r
+ setattr(self, name, kwargs[name])\r
+\r
+ def __eq__(self, other):\r
+ return vars(self) == vars(other)\r
+\r
+ def __ne__(self, other):\r
+ return not (self == other)\r
+\r
+\r
+class _ActionsContainer(object):\r
+\r
+ def __init__(self,\r
+ description,\r
+ prefix_chars,\r
+ argument_default,\r
+ conflict_handler):\r
+ super(_ActionsContainer, self).__init__()\r
+\r
+ self.description = description\r
+ self.argument_default = argument_default\r
+ self.prefix_chars = prefix_chars\r
+ self.conflict_handler = conflict_handler\r
+\r
+ # set up registries\r
+ self._registries = {}\r
+\r
+ # register actions\r
+ self.register('action', None, _StoreAction)\r
+ self.register('action', 'store', _StoreAction)\r
+ self.register('action', 'store_const', _StoreConstAction)\r
+ self.register('action', 'store_true', _StoreTrueAction)\r
+ self.register('action', 'store_false', _StoreFalseAction)\r
+ self.register('action', 'append', _AppendAction)\r
+ self.register('action', 'append_const', _AppendConstAction)\r
+ self.register('action', 'count', _CountAction)\r
+ self.register('action', 'help', _HelpAction)\r
+ self.register('action', 'version', _VersionAction)\r
+ self.register('action', 'parsers', _SubParsersAction)\r
+\r
+ # raise an exception if the conflict handler is invalid\r
+ self._get_handler()\r
+\r
+ # action storage\r
+ self._actions = []\r
+ self._option_string_actions = {}\r
+\r
+ # groups\r
+ self._action_groups = []\r
+ self._mutually_exclusive_groups = []\r
+\r
+ # defaults storage\r
+ self._defaults = {}\r
+\r
+ # determines whether an "option" looks like a negative number\r
+ self._negative_number_matcher = _re.compile(r'^-\d+|-\d*.\d+$')\r
+\r
+ # whether or not there are any optionals that look like negative\r
+ # numbers -- uses a list so it can be shared and edited\r
+ self._has_negative_number_optionals = []\r
+\r
+ # ====================\r
+ # Registration methods\r
+ # ====================\r
+ def register(self, registry_name, value, object):\r
+ registry = self._registries.setdefault(registry_name, {})\r
+ registry[value] = object\r
+\r
+ def _registry_get(self, registry_name, value, default=None):\r
+ return self._registries[registry_name].get(value, default)\r
+\r
+ # ==================================\r
+ # Namespace default settings methods\r
+ # ==================================\r
+ def set_defaults(self, **kwargs):\r
+ self._defaults.update(kwargs)\r
+\r
+ # if these defaults match any existing arguments, replace\r
+ # the previous default on the object with the new one\r
+ for action in self._actions:\r
+ if action.dest in kwargs:\r
+ action.default = kwargs[action.dest]\r
+\r
+ # =======================\r
+ # Adding argument actions\r
+ # =======================\r
+ def add_argument(self, *args, **kwargs):\r
+ """\r
+ add_argument(dest, ..., name=value, ...)\r
+ add_argument(option_string, option_string, ..., name=value, ...)\r
+ """\r
+\r
+ # if no positional args are supplied or only one is supplied and\r
+ # it doesn't look like an option string, parse a positional\r
+ # argument\r
+ chars = self.prefix_chars\r
+ if not args or len(args) == 1 and args[0][0] not in chars:\r
+ kwargs = self._get_positional_kwargs(*args, **kwargs)\r
+\r
+ # otherwise, we're adding an optional argument\r
+ else:\r
+ kwargs = self._get_optional_kwargs(*args, **kwargs)\r
+\r
+ # if no default was supplied, use the parser-level default\r
+ if 'default' not in kwargs:\r
+ dest = kwargs['dest']\r
+ if dest in self._defaults:\r
+ kwargs['default'] = self._defaults[dest]\r
+ elif self.argument_default is not None:\r
+ kwargs['default'] = self.argument_default\r
+\r
+ # create the action object, and add it to the parser\r
+ action_class = self._pop_action_class(kwargs)\r
+ action = action_class(**kwargs)\r
+ return self._add_action(action)\r
+\r
+ def add_argument_group(self, *args, **kwargs):\r
+ group = _ArgumentGroup(self, *args, **kwargs)\r
+ self._action_groups.append(group)\r
+ return group\r
+\r
+ def add_mutually_exclusive_group(self, **kwargs):\r
+ group = _MutuallyExclusiveGroup(self, **kwargs)\r
+ self._mutually_exclusive_groups.append(group)\r
+ return group\r
+\r
+ def _add_action(self, action):\r
+ # resolve any conflicts\r
+ self._check_conflict(action)\r
+\r
+ # add to actions list\r
+ self._actions.append(action)\r
+ action.container = self\r
+\r
+ # index the action by any option strings it has\r
+ for option_string in action.option_strings:\r
+ self._option_string_actions[option_string] = action\r
+\r
+ # set the flag if any option strings look like negative numbers\r
+ for option_string in action.option_strings:\r
+ if self._negative_number_matcher.match(option_string):\r
+ if not self._has_negative_number_optionals:\r
+ self._has_negative_number_optionals.append(True)\r
+\r
+ # return the created action\r
+ return action\r
+\r
+ def _remove_action(self, action):\r
+ self._actions.remove(action)\r
+\r
+ def _add_container_actions(self, container):\r
+ # collect groups by titles\r
+ title_group_map = {}\r
+ for group in self._action_groups:\r
+ if group.title in title_group_map:\r
+ msg = _('cannot merge actions - two groups are named %r')\r
+ raise ValueError(msg % (group.title))\r
+ title_group_map[group.title] = group\r
+\r
+ # map each action to its group\r
+ group_map = {}\r
+ for group in container._action_groups:\r
+\r
+ # if a group with the title exists, use that, otherwise\r
+ # create a new group matching the container's group\r
+ if group.title not in title_group_map:\r
+ title_group_map[group.title] = self.add_argument_group(\r
+ title=group.title,\r
+ description=group.description,\r
+ conflict_handler=group.conflict_handler)\r
+\r
+ # map the actions to their new group\r
+ for action in group._group_actions:\r
+ group_map[action] = title_group_map[group.title]\r
+\r
+ # add container's mutually exclusive groups\r
+ # NOTE: if add_mutually_exclusive_group ever gains title= and\r
+ # description= then this code will need to be expanded as above\r
+ for group in container._mutually_exclusive_groups:\r
+ mutex_group = self.add_mutually_exclusive_group(\r
+ required=group.required)\r
+\r
+ # map the actions to their new mutex group\r
+ for action in group._group_actions:\r
+ group_map[action] = mutex_group\r
+\r
+ # add all actions to this container or their group\r
+ for action in container._actions:\r
+ group_map.get(action, self)._add_action(action)\r
+\r
+ def _get_positional_kwargs(self, dest, **kwargs):\r
+ # make sure required is not specified\r
+ if 'required' in kwargs:\r
+ msg = _("'required' is an invalid argument for positionals")\r
+ raise TypeError(msg)\r
+\r
+ # mark positional arguments as required if at least one is\r
+ # always required\r
+ if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:\r
+ kwargs['required'] = True\r
+ if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:\r
+ kwargs['required'] = True\r
+\r
+ # return the keyword arguments with no option strings\r
+ return dict(kwargs, dest=dest, option_strings=[])\r
+\r
+ def _get_optional_kwargs(self, *args, **kwargs):\r
+ # determine short and long option strings\r
+ option_strings = []\r
+ long_option_strings = []\r
+ for option_string in args:\r
+ # error on one-or-fewer-character option strings\r
+ if len(option_string) < 2:\r
+ msg = _('invalid option string %r: '\r
+ 'must be at least two characters long')\r
+ raise ValueError(msg % option_string)\r
+\r
+ # error on strings that don't start with an appropriate prefix\r
+ if not option_string[0] in self.prefix_chars:\r
+ msg = _('invalid option string %r: '\r
+ 'must start with a character %r')\r
+ tup = option_string, self.prefix_chars\r
+ raise ValueError(msg % tup)\r
+\r
+ # error on strings that are all prefix characters\r
+ if not (_set(option_string) - _set(self.prefix_chars)):\r
+ msg = _('invalid option string %r: '\r
+ 'must contain characters other than %r')\r
+ tup = option_string, self.prefix_chars\r
+ raise ValueError(msg % tup)\r
+\r
+ # strings starting with two prefix characters are long options\r
+ option_strings.append(option_string)\r
+ if option_string[0] in self.prefix_chars:\r
+ if option_string[1] in self.prefix_chars:\r
+ long_option_strings.append(option_string)\r
+\r
+ # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'\r
+ dest = kwargs.pop('dest', None)\r
+ if dest is None:\r
+ if long_option_strings:\r
+ dest_option_string = long_option_strings[0]\r
+ else:\r
+ dest_option_string = option_strings[0]\r
+ dest = dest_option_string.lstrip(self.prefix_chars)\r
+ dest = dest.replace('-', '_')\r
+\r
+ # return the updated keyword arguments\r
+ return dict(kwargs, dest=dest, option_strings=option_strings)\r
+\r
+ def _pop_action_class(self, kwargs, default=None):\r
+ action = kwargs.pop('action', default)\r
+ return self._registry_get('action', action, action)\r
+\r
+ def _get_handler(self):\r
+ # determine function from conflict handler string\r
+ handler_func_name = '_handle_conflict_%s' % self.conflict_handler\r
+ try:\r
+ return getattr(self, handler_func_name)\r
+ except AttributeError:\r
+ msg = _('invalid conflict_resolution value: %r')\r
+ raise ValueError(msg % self.conflict_handler)\r
+\r
+ def _check_conflict(self, action):\r
+\r
+ # find all options that conflict with this option\r
+ confl_optionals = []\r
+ for option_string in action.option_strings:\r
+ if option_string in self._option_string_actions:\r
+ confl_optional = self._option_string_actions[option_string]\r
+ confl_optionals.append((option_string, confl_optional))\r
+\r
+ # resolve any conflicts\r
+ if confl_optionals:\r
+ conflict_handler = self._get_handler()\r
+ conflict_handler(action, confl_optionals)\r
+\r
+ def _handle_conflict_error(self, action, conflicting_actions):\r
+ message = _('conflicting option string(s): %s')\r
+ conflict_string = ', '.join([option_string\r
+ for option_string, action\r
+ in conflicting_actions])\r
+ raise ArgumentError(action, message % conflict_string)\r
+\r
+ def _handle_conflict_resolve(self, action, conflicting_actions):\r
+\r
+ # remove all conflicting options\r
+ for option_string, action in conflicting_actions:\r
+\r
+ # remove the conflicting option\r
+ action.option_strings.remove(option_string)\r
+ self._option_string_actions.pop(option_string, None)\r
+\r
+ # if the option now has no option string, remove it from the\r
+ # container holding it\r
+ if not action.option_strings:\r
+ action.container._remove_action(action)\r
+\r
+\r
+class _ArgumentGroup(_ActionsContainer):\r
+\r
+ def __init__(self, container, title=None, description=None, **kwargs):\r
+ # add any missing keyword arguments by checking the container\r
+ update = kwargs.setdefault\r
+ update('conflict_handler', container.conflict_handler)\r
+ update('prefix_chars', container.prefix_chars)\r
+ update('argument_default', container.argument_default)\r
+ super_init = super(_ArgumentGroup, self).__init__\r
+ super_init(description=description, **kwargs)\r
+\r
+ # group attributes\r
+ self.title = title\r
+ self._group_actions = []\r
+\r
+ # share most attributes with the container\r
+ self._registries = container._registries\r
+ self._actions = container._actions\r
+ self._option_string_actions = container._option_string_actions\r
+ self._defaults = container._defaults\r
+ self._has_negative_number_optionals = \\r
+ container._has_negative_number_optionals\r
+\r
+ def _add_action(self, action):\r
+ action = super(_ArgumentGroup, self)._add_action(action)\r
+ self._group_actions.append(action)\r
+ return action\r
+\r
+ def _remove_action(self, action):\r
+ super(_ArgumentGroup, self)._remove_action(action)\r
+ self._group_actions.remove(action)\r
+\r
+\r
+class _MutuallyExclusiveGroup(_ArgumentGroup):\r
+\r
+ def __init__(self, container, required=False):\r
+ super(_MutuallyExclusiveGroup, self).__init__(container)\r
+ self.required = required\r
+ self._container = container\r
+\r
+ def _add_action(self, action):\r
+ if action.required:\r
+ msg = _('mutually exclusive arguments must be optional')\r
+ raise ValueError(msg)\r
+ action = self._container._add_action(action)\r
+ self._group_actions.append(action)\r
+ return action\r
+\r
+ def _remove_action(self, action):\r
+ self._container._remove_action(action)\r
+ self._group_actions.remove(action)\r
+\r
+\r
+class ArgumentParser(_AttributeHolder, _ActionsContainer):\r
+ """Object for parsing command line strings into Python objects.\r
+\r
+ Keyword Arguments:\r
+ - prog -- The name of the program (default: sys.argv[0])\r
+ - usage -- A usage message (default: auto-generated from arguments)\r
+ - description -- A description of what the program does\r
+ - epilog -- Text following the argument descriptions\r
+ - version -- Add a -v/--version option with the given version string\r
+ - parents -- Parsers whose arguments should be copied into this one\r
+ - formatter_class -- HelpFormatter class for printing help messages\r
+ - prefix_chars -- Characters that prefix optional arguments\r
+ - fromfile_prefix_chars -- Characters that prefix files containing\r
+ additional arguments\r
+ - argument_default -- The default value for all arguments\r
+ - conflict_handler -- String indicating how to handle conflicts\r
+ - add_help -- Add a -h/-help option\r
+ """\r
+\r
+ def __init__(self,\r
+ prog=None,\r
+ usage=None,\r
+ description=None,\r
+ epilog=None,\r
+ version=None,\r
+ parents=[],\r
+ formatter_class=HelpFormatter,\r
+ prefix_chars='-',\r
+ fromfile_prefix_chars=None,\r
+ argument_default=None,\r
+ conflict_handler='error',\r
+ add_help=True):\r
+\r
+ superinit = super(ArgumentParser, self).__init__\r
+ superinit(description=description,\r
+ prefix_chars=prefix_chars,\r
+ argument_default=argument_default,\r
+ conflict_handler=conflict_handler)\r
+\r
+ # default setting for prog\r
+ if prog is None:\r
+ prog = _os.path.basename(_sys.argv[0])\r
+\r
+ self.prog = prog\r
+ self.usage = usage\r
+ self.epilog = epilog\r
+ self.version = version\r
+ self.formatter_class = formatter_class\r
+ self.fromfile_prefix_chars = fromfile_prefix_chars\r
+ self.add_help = add_help\r
+\r
+ add_group = self.add_argument_group\r
+ self._positionals = add_group(_('arguments'))\r
+ self._optionals = add_group(_('options'))\r
+ self._subparsers = None\r
+\r
+ # register types\r
+ def identity(string):\r
+ return string\r
+ self.register('type', None, identity)\r
+\r
+ # add help and version arguments if necessary\r
+ # (using explicit default to override global argument_default)\r
+ if self.add_help:\r
+ self.add_argument(\r
+ '-h', '--help', action='help', default=SUPPRESS,\r
+ help=_('show this help message and exit'))\r
+ if self.version:\r
+ self.add_argument(\r
+ '-v', '--version', action='version', default=SUPPRESS,\r
+ help=_("show program's version number and exit"))\r
+\r
+ # add parent arguments and defaults\r
+ for parent in parents:\r
+ self._add_container_actions(parent)\r
+ try:\r
+ defaults = parent._defaults\r
+ except AttributeError:\r
+ pass\r
+ else:\r
+ self._defaults.update(defaults)\r
+\r
+ # =======================\r
+ # Pretty __repr__ methods\r
+ # =======================\r
+ def _get_kwargs(self):\r
+ names = [\r
+ 'prog',\r
+ 'usage',\r
+ 'description',\r
+ 'version',\r
+ 'formatter_class',\r
+ 'conflict_handler',\r
+ 'add_help',\r
+ ]\r
+ return [(name, getattr(self, name)) for name in names]\r
+\r
+ # ==================================\r
+ # Optional/Positional adding methods\r
+ # ==================================\r
+ def add_subparsers(self, **kwargs):\r
+ if self._subparsers is not None:\r
+ self.error(_('cannot have multiple subparser arguments'))\r
+\r
+ # add the parser class to the arguments if it's not present\r
+ kwargs.setdefault('parser_class', type(self))\r
+\r
+ if 'title' in kwargs or 'description' in kwargs:\r
+ title = _(kwargs.pop('title', 'subcommands'))\r
+ description = _(kwargs.pop('description', None))\r
+ self._subparsers = self.add_argument_group(title, description)\r
+ else:\r
+ self._subparsers = self._positionals\r
+\r
+ # prog defaults to the usage message of this parser, skipping\r
+ # optional arguments and with no "usage:" prefix\r
+ if kwargs.get('prog') is None:\r
+ formatter = self._get_formatter()\r
+ positionals = self._get_positional_actions()\r
+ groups = self._mutually_exclusive_groups\r
+ formatter.add_usage(self.usage, positionals, groups, '')\r
+ kwargs['prog'] = formatter.format_help().strip()\r
+\r
+ # create the parsers action and add it to the positionals list\r
+ parsers_class = self._pop_action_class(kwargs, 'parsers')\r
+ action = parsers_class(option_strings=[], **kwargs)\r
+ self._subparsers._add_action(action)\r
+\r
+ # return the created parsers action\r
+ return action\r
+\r
+ def _add_action(self, action):\r
+ if action.option_strings:\r
+ self._optionals._add_action(action)\r
+ else:\r
+ self._positionals._add_action(action)\r
+ return action\r
+\r
+ def _get_optional_actions(self):\r
+ return [action\r
+ for action in self._actions\r
+ if action.option_strings]\r
+\r
+ def _get_positional_actions(self):\r
+ return [action\r
+ for action in self._actions\r
+ if not action.option_strings]\r
+\r
+ # =====================================\r
+ # Command line argument parsing methods\r
+ # =====================================\r
+ def parse_args(self, args=None, namespace=None):\r
+ args, argv = self.parse_known_args(args, namespace)\r
+ if argv:\r
+ msg = _('unrecognized arguments: %s')\r
+ self.error(msg % ' '.join(argv))\r
+ return args\r
+\r
+ def parse_known_args(self, args=None, namespace=None):\r
+ # args default to the system args\r
+ if args is None:\r
+ args = _sys.argv[1:]\r
+\r
+ # default Namespace built from parser defaults\r
+ if namespace is None:\r
+ namespace = Namespace()\r
+\r
+ # add any action defaults that aren't present\r
+ for action in self._actions:\r
+ if action.dest is not SUPPRESS:\r
+ if not hasattr(namespace, action.dest):\r
+ if action.default is not SUPPRESS:\r
+ default = action.default\r
+ if isinstance(action.default, _basestring):\r
+ default = self._get_value(action, default)\r
+ setattr(namespace, action.dest, default)\r
+\r
+ # add any parser defaults that aren't present\r
+ for dest in self._defaults:\r
+ if not hasattr(namespace, dest):\r
+ setattr(namespace, dest, self._defaults[dest])\r
+\r
+ # parse the arguments and exit if there are any errors\r
+ try:\r
+ return self._parse_known_args(args, namespace)\r
+ except ArgumentError:\r
+ err = _sys.exc_info()[1]\r
+ self.error(str(err))\r
+\r
+ def _parse_known_args(self, arg_strings, namespace):\r
+ # replace arg strings that are file references\r
+ if self.fromfile_prefix_chars is not None:\r
+ arg_strings = self._read_args_from_files(arg_strings)\r
+\r
+ # map all mutually exclusive arguments to the other arguments\r
+ # they can't occur with\r
+ action_conflicts = {}\r
+ for mutex_group in self._mutually_exclusive_groups:\r
+ group_actions = mutex_group._group_actions\r
+ for i, mutex_action in enumerate(mutex_group._group_actions):\r
+ conflicts = action_conflicts.setdefault(mutex_action, [])\r
+ conflicts.extend(group_actions[:i])\r
+ conflicts.extend(group_actions[i + 1:])\r
+\r
+ # find all option indices, and determine the arg_string_pattern\r
+ # which has an 'O' if there is an option at an index,\r
+ # an 'A' if there is an argument, or a '-' if there is a '--'\r
+ option_string_indices = {}\r
+ arg_string_pattern_parts = []\r
+ arg_strings_iter = iter(arg_strings)\r
+ for i, arg_string in enumerate(arg_strings_iter):\r
+\r
+ # all args after -- are non-options\r
+ if arg_string == '--':\r
+ arg_string_pattern_parts.append('-')\r
+ for arg_string in arg_strings_iter:\r
+ arg_string_pattern_parts.append('A')\r
+\r
+ # otherwise, add the arg to the arg strings\r
+ # and note the index if it was an option\r
+ else:\r
+ option_tuple = self._parse_optional(arg_string)\r
+ if option_tuple is None:\r
+ pattern = 'A'\r
+ else:\r
+ option_string_indices[i] = option_tuple\r
+ pattern = 'O'\r
+ arg_string_pattern_parts.append(pattern)\r
+\r
+ # join the pieces together to form the pattern\r
+ arg_strings_pattern = ''.join(arg_string_pattern_parts)\r
+\r
+ # converts arg strings to the appropriate and then takes the action\r
+ seen_actions = _set()\r
+ seen_non_default_actions = _set()\r
+\r
+ def take_action(action, argument_strings, option_string=None):\r
+ seen_actions.add(action)\r
+ argument_values = self._get_values(action, argument_strings)\r
+\r
+ # error if this argument is not allowed with other previously\r
+ # seen arguments, assuming that actions that use the default\r
+ # value don't really count as "present"\r
+ if argument_values is not action.default:\r
+ seen_non_default_actions.add(action)\r
+ for conflict_action in action_conflicts.get(action, []):\r
+ if conflict_action in seen_non_default_actions:\r
+ msg = _('not allowed with argument %s')\r
+ action_name = _get_action_name(conflict_action)\r
+ raise ArgumentError(action, msg % action_name)\r
+\r
+ # take the action if we didn't receive a SUPPRESS value\r
+ # (e.g. from a default)\r
+ if argument_values is not SUPPRESS:\r
+ action(self, namespace, argument_values, option_string)\r
+\r
+ # function to convert arg_strings into an optional action\r
+ def consume_optional(start_index):\r
+\r
+ # get the optional identified at this index\r
+ option_tuple = option_string_indices[start_index]\r
+ action, option_string, explicit_arg = option_tuple\r
+\r
+ # identify additional optionals in the same arg string\r
+ # (e.g. -xyz is the same as -x -y -z if no args are required)\r
+ match_argument = self._match_argument\r
+ action_tuples = []\r
+ while True:\r
+\r
+ # if we found no optional action, skip it\r
+ if action is None:\r
+ extras.append(arg_strings[start_index])\r
+ return start_index + 1\r
+\r
+ # if there is an explicit argument, try to match the\r
+ # optional's string arguments to only this\r
+ if explicit_arg is not None:\r
+ arg_count = match_argument(action, 'A')\r
+\r
+ # if the action is a single-dash option and takes no\r
+ # arguments, try to parse more single-dash options out\r
+ # of the tail of the option string\r
+ chars = self.prefix_chars\r
+ if arg_count == 0 and option_string[1] not in chars:\r
+ action_tuples.append((action, [], option_string))\r
+ for char in self.prefix_chars:\r
+ option_string = char + explicit_arg[0]\r
+ explicit_arg = explicit_arg[1:] or None\r
+ optionals_map = self._option_string_actions\r
+ if option_string in optionals_map:\r
+ action = optionals_map[option_string]\r
+ break\r
+ else:\r
+ msg = _('ignored explicit argument %r')\r
+ raise ArgumentError(action, msg % explicit_arg)\r
+\r
+ # if the action expect exactly one argument, we've\r
+ # successfully matched the option; exit the loop\r
+ elif arg_count == 1:\r
+ stop = start_index + 1\r
+ args = [explicit_arg]\r
+ action_tuples.append((action, args, option_string))\r
+ break\r
+\r
+ # error if a double-dash option did not use the\r
+ # explicit argument\r
+ else:\r
+ msg = _('ignored explicit argument %r')\r
+ raise ArgumentError(action, msg % explicit_arg)\r
+\r
+ # if there is no explicit argument, try to match the\r
+ # optional's string arguments with the following strings\r
+ # if successful, exit the loop\r
+ else:\r
+ start = start_index + 1\r
+ selected_patterns = arg_strings_pattern[start:]\r
+ arg_count = match_argument(action, selected_patterns)\r
+ stop = start + arg_count\r
+ args = arg_strings[start:stop]\r
+ action_tuples.append((action, args, option_string))\r
+ break\r
+\r
+ # add the Optional to the list and return the index at which\r
+ # the Optional's string args stopped\r
+ assert action_tuples\r
+ for action, args, option_string in action_tuples:\r
+ take_action(action, args, option_string)\r
+ return stop\r
+\r
+ # the list of Positionals left to be parsed; this is modified\r
+ # by consume_positionals()\r
+ positionals = self._get_positional_actions()\r
+\r
+ # function to convert arg_strings into positional actions\r
+ def consume_positionals(start_index):\r
+ # match as many Positionals as possible\r
+ match_partial = self._match_arguments_partial\r
+ selected_pattern = arg_strings_pattern[start_index:]\r
+ arg_counts = match_partial(positionals, selected_pattern)\r
+\r
+ # slice off the appropriate arg strings for each Positional\r
+ # and add the Positional and its args to the list\r
+ for action, arg_count in zip(positionals, arg_counts):\r
+ args = arg_strings[start_index: start_index + arg_count]\r
+ start_index += arg_count\r
+ take_action(action, args)\r
+\r
+ # slice off the Positionals that we just parsed and return the\r
+ # index at which the Positionals' string args stopped\r
+ positionals[:] = positionals[len(arg_counts):]\r
+ return start_index\r
+\r
+ # consume Positionals and Optionals alternately, until we have\r
+ # passed the last option string\r
+ extras = []\r
+ start_index = 0\r
+ if option_string_indices:\r
+ max_option_string_index = max(option_string_indices)\r
+ else:\r
+ max_option_string_index = -1\r
+ while start_index <= max_option_string_index:\r
+\r
+ # consume any Positionals preceding the next option\r
+ next_option_string_index = min([\r
+ index\r
+ for index in option_string_indices\r
+ if index >= start_index])\r
+ if start_index != next_option_string_index:\r
+ positionals_end_index = consume_positionals(start_index)\r
+\r
+ # only try to parse the next optional if we didn't consume\r
+ # the option string during the positionals parsing\r
+ if positionals_end_index > start_index:\r
+ start_index = positionals_end_index\r
+ continue\r
+ else:\r
+ start_index = positionals_end_index\r
+\r
+ # if we consumed all the positionals we could and we're not\r
+ # at the index of an option string, there were extra arguments\r
+ if start_index not in option_string_indices:\r
+ strings = arg_strings[start_index:next_option_string_index]\r
+ extras.extend(strings)\r
+ start_index = next_option_string_index\r
+\r
+ # consume the next optional and any arguments for it\r
+ start_index = consume_optional(start_index)\r
+\r
+ # consume any positionals following the last Optional\r
+ stop_index = consume_positionals(start_index)\r
+\r
+ # if we didn't consume all the argument strings, there were extras\r
+ extras.extend(arg_strings[stop_index:])\r
+\r
+ # if we didn't use all the Positional objects, there were too few\r
+ # arg strings supplied.\r
+ if positionals:\r
+ self.error(_('too few arguments'))\r
+\r
+ # make sure all required actions were present\r
+ for action in self._actions:\r
+ if action.required:\r
+ if action not in seen_actions:\r
+ name = _get_action_name(action)\r
+ self.error(_('argument %s is required') % name)\r
+\r
+ # make sure all required groups had one option present\r
+ for group in self._mutually_exclusive_groups:\r
+ if group.required:\r
+ for action in group._group_actions:\r
+ if action in seen_non_default_actions:\r
+ break\r
+\r
+ # if no actions were used, report the error\r
+ else:\r
+ names = [_get_action_name(action)\r
+ for action in group._group_actions\r
+ if action.help is not SUPPRESS]\r
+ msg = _('one of the arguments %s is required')\r
+ self.error(msg % ' '.join(names))\r
+\r
+ # return the updated namespace and the extra arguments\r
+ return namespace, extras\r
+\r
+ def _read_args_from_files(self, arg_strings):\r
+ # expand arguments referencing files\r
+ new_arg_strings = []\r
+ for arg_string in arg_strings:\r
+\r
+ # for regular arguments, just add them back into the list\r
+ if arg_string[0] not in self.fromfile_prefix_chars:\r
+ new_arg_strings.append(arg_string)\r
+\r
+ # replace arguments referencing files with the file content\r
+ else:\r
+ try:\r
+ args_file = open(arg_string[1:])\r
+ try:\r
+ arg_strings = args_file.read().splitlines()\r
+ arg_strings = self._read_args_from_files(arg_strings)\r
+ new_arg_strings.extend(arg_strings)\r
+ finally:\r
+ args_file.close()\r
+ except IOError:\r
+ err = _sys.exc_info()[1]\r
+ self.error(str(err))\r
+\r
+ # return the modified argument list\r
+ return new_arg_strings\r
+\r
+ def _match_argument(self, action, arg_strings_pattern):\r
+ # match the pattern for this action to the arg strings\r
+ nargs_pattern = self._get_nargs_pattern(action)\r
+ match = _re.match(nargs_pattern, arg_strings_pattern)\r
+\r
+ # raise an exception if we weren't able to find a match\r
+ if match is None:\r
+ nargs_errors = {\r
+ None: _('expected one argument'),\r
+ OPTIONAL: _('expected at most one argument'),\r
+ ONE_OR_MORE: _('expected at least one argument'),\r
+ }\r
+ default = _('expected %s argument(s)') % action.nargs\r
+ msg = nargs_errors.get(action.nargs, default)\r
+ raise ArgumentError(action, msg)\r
+\r
+ # return the number of arguments matched\r
+ return len(match.group(1))\r
+\r
+ def _match_arguments_partial(self, actions, arg_strings_pattern):\r
+ # progressively shorten the actions list by slicing off the\r
+ # final actions until we find a match\r
+ result = []\r
+ for i in range(len(actions), 0, -1):\r
+ actions_slice = actions[:i]\r
+ pattern = ''.join([self._get_nargs_pattern(action)\r
+ for action in actions_slice])\r
+ match = _re.match(pattern, arg_strings_pattern)\r
+ if match is not None:\r
+ result.extend([len(string) for string in match.groups()])\r
+ break\r
+\r
+ # return the list of arg string counts\r
+ return result\r
+\r
+ def _parse_optional(self, arg_string):\r
+ # if it's an empty string, it was meant to be a positional\r
+ if not arg_string:\r
+ return None\r
+\r
+ # if it doesn't start with a prefix, it was meant to be positional\r
+ if not arg_string[0] in self.prefix_chars:\r
+ return None\r
+\r
+ # if it's just dashes, it was meant to be positional\r
+ if not arg_string.strip('-'):\r
+ return None\r
+\r
+ # if the option string is present in the parser, return the action\r
+ if arg_string in self._option_string_actions:\r
+ action = self._option_string_actions[arg_string]\r
+ return action, arg_string, None\r
+\r
+ # search through all possible prefixes of the option string\r
+ # and all actions in the parser for possible interpretations\r
+ option_tuples = self._get_option_tuples(arg_string)\r
+\r
+ # if multiple actions match, the option string was ambiguous\r
+ if len(option_tuples) > 1:\r
+ options = ', '.join([option_string\r
+ for action, option_string, explicit_arg in option_tuples])\r
+ tup = arg_string, options\r
+ self.error(_('ambiguous option: %s could match %s') % tup)\r
+\r
+ # if exactly one action matched, this segmentation is good,\r
+ # so return the parsed action\r
+ elif len(option_tuples) == 1:\r
+ option_tuple, = option_tuples\r
+ return option_tuple\r
+\r
+ # if it was not found as an option, but it looks like a negative\r
+ # number, it was meant to be positional\r
+ # unless there are negative-number-like options\r
+ if self._negative_number_matcher.match(arg_string):\r
+ if not self._has_negative_number_optionals:\r
+ return None\r
+\r
+ # if it contains a space, it was meant to be a positional\r
+ if ' ' in arg_string:\r
+ return None\r
+\r
+ # it was meant to be an optional but there is no such option\r
+ # in this parser (though it might be a valid option in a subparser)\r
+ return None, arg_string, None\r
+\r
+ def _get_option_tuples(self, option_string):\r
+ result = []\r
+\r
+ # option strings starting with two prefix characters are only\r
+ # split at the '='\r
+ chars = self.prefix_chars\r
+ if option_string[0] in chars and option_string[1] in chars:\r
+ if '=' in option_string:\r
+ option_prefix, explicit_arg = option_string.split('=', 1)\r
+ else:\r
+ option_prefix = option_string\r
+ explicit_arg = None\r
+ for option_string in self._option_string_actions:\r
+ if option_string.startswith(option_prefix):\r
+ action = self._option_string_actions[option_string]\r
+ tup = action, option_string, explicit_arg\r
+ result.append(tup)\r
+\r
+ # single character options can be concatenated with their arguments\r
+ # but multiple character options always have to have their argument\r
+ # separate\r
+ elif option_string[0] in chars and option_string[1] not in chars:\r
+ option_prefix = option_string\r
+ explicit_arg = None\r
+ short_option_prefix = option_string[:2]\r
+ short_explicit_arg = option_string[2:]\r
+\r
+ for option_string in self._option_string_actions:\r
+ if option_string == short_option_prefix:\r
+ action = self._option_string_actions[option_string]\r
+ tup = action, option_string, short_explicit_arg\r
+ result.append(tup)\r
+ elif option_string.startswith(option_prefix):\r
+ action = self._option_string_actions[option_string]\r
+ tup = action, option_string, explicit_arg\r
+ result.append(tup)\r
+\r
+ # shouldn't ever get here\r
+ else:\r
+ self.error(_('unexpected option string: %s') % option_string)\r
+\r
+ # return the collected option tuples\r
+ return result\r
+\r
+ def _get_nargs_pattern(self, action):\r
+ # in all examples below, we have to allow for '--' args\r
+ # which are represented as '-' in the pattern\r
+ nargs = action.nargs\r
+\r
+ # the default (None) is assumed to be a single argument\r
+ if nargs is None:\r
+ nargs_pattern = '(-*A-*)'\r
+\r
+ # allow zero or one arguments\r
+ elif nargs == OPTIONAL:\r
+ nargs_pattern = '(-*A?-*)'\r
+\r
+ # allow zero or more arguments\r
+ elif nargs == ZERO_OR_MORE:\r
+ nargs_pattern = '(-*[A-]*)'\r
+\r
+ # allow one or more arguments\r
+ elif nargs == ONE_OR_MORE:\r
+ nargs_pattern = '(-*A[A-]*)'\r
+\r
+ # allow one argument followed by any number of options or arguments\r
+ elif nargs is PARSER:\r
+ nargs_pattern = '(-*A[-AO]*)'\r
+\r
+ # all others should be integers\r
+ else:\r
+ nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)\r
+\r
+ # if this is an optional action, -- is not allowed\r
+ if action.option_strings:\r
+ nargs_pattern = nargs_pattern.replace('-*', '')\r
+ nargs_pattern = nargs_pattern.replace('-', '')\r
+\r
+ # return the pattern\r
+ return nargs_pattern\r
+\r
+ # ========================\r
+ # Value conversion methods\r
+ # ========================\r
+ def _get_values(self, action, arg_strings):\r
+ # for everything but PARSER args, strip out '--'\r
+ if action.nargs is not PARSER:\r
+ arg_strings = [s for s in arg_strings if s != '--']\r
+\r
+ # optional argument produces a default when not present\r
+ if not arg_strings and action.nargs == OPTIONAL:\r
+ if action.option_strings:\r
+ value = action.const\r
+ else:\r
+ value = action.default\r
+ if isinstance(value, _basestring):\r
+ value = self._get_value(action, value)\r
+ self._check_value(action, value)\r
+\r
+ # when nargs='*' on a positional, if there were no command-line\r
+ # args, use the default if it is anything other than None\r
+ elif (not arg_strings and action.nargs == ZERO_OR_MORE and\r
+ not action.option_strings):\r
+ if action.default is not None:\r
+ value = action.default\r
+ else:\r
+ value = arg_strings\r
+ self._check_value(action, value)\r
+\r
+ # single argument or optional argument produces a single value\r
+ elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:\r
+ arg_string, = arg_strings\r
+ value = self._get_value(action, arg_string)\r
+ self._check_value(action, value)\r
+\r
+ # PARSER arguments convert all values, but check only the first\r
+ elif action.nargs is PARSER:\r
+ value = [self._get_value(action, v) for v in arg_strings]\r
+ self._check_value(action, value[0])\r
+\r
+ # all other types of nargs produce a list\r
+ else:\r
+ value = [self._get_value(action, v) for v in arg_strings]\r
+ for v in value:\r
+ self._check_value(action, v)\r
+\r
+ # return the converted value\r
+ return value\r
+\r
+ def _get_value(self, action, arg_string):\r
+ type_func = self._registry_get('type', action.type, action.type)\r
+ if not hasattr(type_func, '__call__'):\r
+ if not hasattr(type_func, '__bases__'): # classic classes\r
+ msg = _('%r is not callable')\r
+ raise ArgumentError(action, msg % type_func)\r
+\r
+ # convert the value to the appropriate type\r
+ try:\r
+ result = type_func(arg_string)\r
+\r
+ # TypeErrors or ValueErrors indicate errors\r
+ except (TypeError, ValueError):\r
+ name = getattr(action.type, '__name__', repr(action.type))\r
+ msg = _('invalid %s value: %r')\r
+ raise ArgumentError(action, msg % (name, arg_string))\r
+\r
+ # return the converted value\r
+ return result\r
+\r
+ def _check_value(self, action, value):\r
+ # converted value must be one of the choices (if specified)\r
+ if action.choices is not None and value not in action.choices:\r
+ tup = value, ', '.join(map(repr, action.choices))\r
+ msg = _('invalid choice: %r (choose from %s)') % tup\r
+ raise ArgumentError(action, msg)\r
+\r
+ # =======================\r
+ # Help-formatting methods\r
+ # =======================\r
+ def format_usage(self):\r
+ formatter = self._get_formatter()\r
+ formatter.add_usage(self.usage, self._actions,\r
+ self._mutually_exclusive_groups)\r
+ return formatter.format_help()\r
+\r
+ def format_help(self):\r
+ formatter = self._get_formatter()\r
+\r
+ # usage\r
+ formatter.add_usage(self.usage, self._actions,\r
+ self._mutually_exclusive_groups)\r
+\r
+ # description\r
+ formatter.add_text(self.description)\r
+\r
+ # positionals, optionals and user-defined groups\r
+ for action_group in self._action_groups:\r
+ formatter.start_section(action_group.title)\r
+ formatter.add_text(action_group.description)\r
+ formatter.add_arguments(action_group._group_actions)\r
+ formatter.end_section()\r
+\r
+ # epilog\r
+ formatter.add_text(self.epilog)\r
+\r
+ # determine help from format above\r
+ return formatter.format_help()\r
+\r
+ def format_version(self):\r
+ formatter = self._get_formatter()\r
+ formatter.add_text(self.version)\r
+ return formatter.format_help()\r
+\r
+ def _get_formatter(self):\r
+ return self.formatter_class(prog=self.prog)\r
+\r
+ # =====================\r
+ # Help-printing methods\r
+ # =====================\r
+ def print_usage(self, file=None):\r
+ self._print_message(self.format_usage(), file)\r
+\r
+ def print_help(self, file=None):\r
+ self._print_message(self.format_help(), file)\r
+\r
+ def print_version(self, file=None):\r
+ self._print_message(self.format_version(), file)\r
+\r
+ def _print_message(self, message, file=None):\r
+ if message:\r
+ if file is None:\r
+ file = _sys.stderr\r
+ file.write(message)\r
+\r
+ # ===============\r
+ # Exiting methods\r
+ # ===============\r
+ def exit(self, status=0, message=None):\r
+ if message:\r
+ _sys.stderr.write(message)\r
+ _sys.exit(status)\r
+\r
+ def error(self, message):\r
+ """error(message: string)\r
+\r
+ Prints a usage message incorporating the message to stderr and\r
+ exits.\r
+\r
+ If you override this in a subclass, it should not return -- it\r
+ should either exit or raise an exception.\r
+ """\r
+ self.print_usage(_sys.stderr)\r
+ self.exit(2, _('%s: error: %s\n') % (self.prog, message))\r