1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/external/argparse.py Mon Feb 20 15:10:53 2012 +0100
1.3 @@ -0,0 +1,2312 @@
1.4 +# Author: Steven J. Bethard <steven.bethard@gmail.com>.
1.5 +
1.6 +"""Command-line parsing library
1.7 +
1.8 +This module is an optparse-inspired command-line parsing library that:
1.9 +
1.10 + - handles both optional and positional arguments
1.11 + - produces highly informative usage messages
1.12 + - supports parsers that dispatch to sub-parsers
1.13 +
1.14 +The following is a simple usage example that sums integers from the
1.15 +command-line and writes the result to a file::
1.16 +
1.17 + parser = argparse.ArgumentParser(
1.18 + description='sum the integers at the command line')
1.19 + parser.add_argument(
1.20 + 'integers', metavar='int', nargs='+', type=int,
1.21 + help='an integer to be summed')
1.22 + parser.add_argument(
1.23 + '--log', default=sys.stdout, type=argparse.FileType('w'),
1.24 + help='the file where the sum should be written')
1.25 + args = parser.parse_args()
1.26 + args.log.write('%s' % sum(args.integers))
1.27 + args.log.close()
1.28 +
1.29 +The module contains the following public classes:
1.30 +
1.31 + - ArgumentParser -- The main entry point for command-line parsing. As the
1.32 + example above shows, the add_argument() method is used to populate
1.33 + the parser with actions for optional and positional arguments. Then
1.34 + the parse_args() method is invoked to convert the args at the
1.35 + command-line into an object with attributes.
1.36 +
1.37 + - ArgumentError -- The exception raised by ArgumentParser objects when
1.38 + there are errors with the parser's actions. Errors raised while
1.39 + parsing the command-line are caught by ArgumentParser and emitted
1.40 + as command-line messages.
1.41 +
1.42 + - FileType -- A factory for defining types of files to be created. As the
1.43 + example above shows, instances of FileType are typically passed as
1.44 + the type= argument of add_argument() calls.
1.45 +
1.46 + - Action -- The base class for parser actions. Typically actions are
1.47 + selected by passing strings like 'store_true' or 'append_const' to
1.48 + the action= argument of add_argument(). However, for greater
1.49 + customization of ArgumentParser actions, subclasses of Action may
1.50 + be defined and passed as the action= argument.
1.51 +
1.52 + - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
1.53 + ArgumentDefaultsHelpFormatter -- Formatter classes which
1.54 + may be passed as the formatter_class= argument to the
1.55 + ArgumentParser constructor. HelpFormatter is the default,
1.56 + RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
1.57 + not to change the formatting for help text, and
1.58 + ArgumentDefaultsHelpFormatter adds information about argument defaults
1.59 + to the help.
1.60 +
1.61 +All other classes in this module are considered implementation details.
1.62 +(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
1.63 +considered public as object names -- the API of the formatter objects is
1.64 +still considered an implementation detail.)
1.65 +"""
1.66 +
1.67 +__version__ = '1.1'
1.68 +__all__ = [
1.69 + 'ArgumentParser',
1.70 + 'ArgumentError',
1.71 + 'Namespace',
1.72 + 'Action',
1.73 + 'FileType',
1.74 + 'HelpFormatter',
1.75 + 'RawDescriptionHelpFormatter',
1.76 + 'RawTextHelpFormatter',
1.77 + 'ArgumentDefaultsHelpFormatter',
1.78 +]
1.79 +
1.80 +
1.81 +import copy as _copy
1.82 +import os as _os
1.83 +import re as _re
1.84 +import sys as _sys
1.85 +import textwrap as _textwrap
1.86 +
1.87 +from gettext import gettext as _
1.88 +
1.89 +
1.90 +def _callable(obj):
1.91 + return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
1.92 +
1.93 +
1.94 +SUPPRESS = '==SUPPRESS=='
1.95 +
1.96 +OPTIONAL = '?'
1.97 +ZERO_OR_MORE = '*'
1.98 +ONE_OR_MORE = '+'
1.99 +PARSER = 'A...'
1.100 +REMAINDER = '...'
1.101 +
1.102 +# =============================
1.103 +# Utility functions and classes
1.104 +# =============================
1.105 +
1.106 +class _AttributeHolder(object):
1.107 + """Abstract base class that provides __repr__.
1.108 +
1.109 + The __repr__ method returns a string in the format::
1.110 + ClassName(attr=name, attr=name, ...)
1.111 + The attributes are determined either by a class-level attribute,
1.112 + '_kwarg_names', or by inspecting the instance __dict__.
1.113 + """
1.114 +
1.115 + def __repr__(self):
1.116 + type_name = type(self).__name__
1.117 + arg_strings = []
1.118 + for arg in self._get_args():
1.119 + arg_strings.append(repr(arg))
1.120 + for name, value in self._get_kwargs():
1.121 + arg_strings.append('%s=%r' % (name, value))
1.122 + return '%s(%s)' % (type_name, ', '.join(arg_strings))
1.123 +
1.124 + def _get_kwargs(self):
1.125 + return sorted(self.__dict__.items())
1.126 +
1.127 + def _get_args(self):
1.128 + return []
1.129 +
1.130 +
1.131 +def _ensure_value(namespace, name, value):
1.132 + if getattr(namespace, name, None) is None:
1.133 + setattr(namespace, name, value)
1.134 + return getattr(namespace, name)
1.135 +
1.136 +
1.137 +# ===============
1.138 +# Formatting Help
1.139 +# ===============
1.140 +
1.141 +class HelpFormatter(object):
1.142 + """Formatter for generating usage messages and argument help strings.
1.143 +
1.144 + Only the name of this class is considered a public API. All the methods
1.145 + provided by the class are considered an implementation detail.
1.146 + """
1.147 +
1.148 + def __init__(self,
1.149 + prog,
1.150 + indent_increment=2,
1.151 + max_help_position=24,
1.152 + width=None):
1.153 +
1.154 + # default setting for width
1.155 + if width is None:
1.156 + try:
1.157 + width = int(_os.environ['COLUMNS'])
1.158 + except (KeyError, ValueError):
1.159 + width = 80
1.160 + width -= 2
1.161 +
1.162 + self._prog = prog
1.163 + self._indent_increment = indent_increment
1.164 + self._max_help_position = max_help_position
1.165 + self._width = width
1.166 +
1.167 + self._current_indent = 0
1.168 + self._level = 0
1.169 + self._action_max_length = 0
1.170 +
1.171 + self._root_section = self._Section(self, None)
1.172 + self._current_section = self._root_section
1.173 +
1.174 + self._whitespace_matcher = _re.compile(r'\s+')
1.175 + self._long_break_matcher = _re.compile(r'\n\n\n+')
1.176 +
1.177 + # ===============================
1.178 + # Section and indentation methods
1.179 + # ===============================
1.180 + def _indent(self):
1.181 + self._current_indent += self._indent_increment
1.182 + self._level += 1
1.183 +
1.184 + def _dedent(self):
1.185 + self._current_indent -= self._indent_increment
1.186 + assert self._current_indent >= 0, 'Indent decreased below 0.'
1.187 + self._level -= 1
1.188 +
1.189 + class _Section(object):
1.190 +
1.191 + def __init__(self, formatter, parent, heading=None):
1.192 + self.formatter = formatter
1.193 + self.parent = parent
1.194 + self.heading = heading
1.195 + self.items = []
1.196 +
1.197 + def format_help(self):
1.198 + # format the indented section
1.199 + if self.parent is not None:
1.200 + self.formatter._indent()
1.201 + join = self.formatter._join_parts
1.202 + for func, args in self.items:
1.203 + func(*args)
1.204 + item_help = join([func(*args) for func, args in self.items])
1.205 + if self.parent is not None:
1.206 + self.formatter._dedent()
1.207 +
1.208 + # return nothing if the section was empty
1.209 + if not item_help:
1.210 + return ''
1.211 +
1.212 + # add the heading if the section was non-empty
1.213 + if self.heading is not SUPPRESS and self.heading is not None:
1.214 + current_indent = self.formatter._current_indent
1.215 + heading = '%*s%s:\n' % (current_indent, '', self.heading)
1.216 + else:
1.217 + heading = ''
1.218 +
1.219 + # join the section-initial newline, the heading and the help
1.220 + return join(['\n', heading, item_help, '\n'])
1.221 +
1.222 + def _add_item(self, func, args):
1.223 + self._current_section.items.append((func, args))
1.224 +
1.225 + # ========================
1.226 + # Message building methods
1.227 + # ========================
1.228 + def start_section(self, heading):
1.229 + self._indent()
1.230 + section = self._Section(self, self._current_section, heading)
1.231 + self._add_item(section.format_help, [])
1.232 + self._current_section = section
1.233 +
1.234 + def end_section(self):
1.235 + self._current_section = self._current_section.parent
1.236 + self._dedent()
1.237 +
1.238 + def add_text(self, text):
1.239 + if text is not SUPPRESS and text is not None:
1.240 + self._add_item(self._format_text, [text])
1.241 +
1.242 + def add_usage(self, usage, actions, groups, prefix=None):
1.243 + if usage is not SUPPRESS:
1.244 + args = usage, actions, groups, prefix
1.245 + self._add_item(self._format_usage, args)
1.246 +
1.247 + def add_argument(self, action):
1.248 + if action.help is not SUPPRESS:
1.249 +
1.250 + # find all invocations
1.251 + get_invocation = self._format_action_invocation
1.252 + invocations = [get_invocation(action)]
1.253 + for subaction in self._iter_indented_subactions(action):
1.254 + invocations.append(get_invocation(subaction))
1.255 +
1.256 + # update the maximum item length
1.257 + invocation_length = max([len(s) for s in invocations])
1.258 + action_length = invocation_length + self._current_indent
1.259 + self._action_max_length = max(self._action_max_length,
1.260 + action_length)
1.261 +
1.262 + # add the item to the list
1.263 + self._add_item(self._format_action, [action])
1.264 +
1.265 + def add_arguments(self, actions):
1.266 + for action in actions:
1.267 + self.add_argument(action)
1.268 +
1.269 + # =======================
1.270 + # Help-formatting methods
1.271 + # =======================
1.272 + def format_help(self):
1.273 + help = self._root_section.format_help()
1.274 + if help:
1.275 + help = self._long_break_matcher.sub('\n\n', help)
1.276 + help = help.strip('\n') + '\n'
1.277 + return help
1.278 +
1.279 + def _join_parts(self, part_strings):
1.280 + return ''.join([part
1.281 + for part in part_strings
1.282 + if part and part is not SUPPRESS])
1.283 +
1.284 + def _format_usage(self, usage, actions, groups, prefix):
1.285 + if prefix is None:
1.286 + prefix = _('usage: ')
1.287 +
1.288 + # if usage is specified, use that
1.289 + if usage is not None:
1.290 + usage = usage % dict(prog=self._prog)
1.291 +
1.292 + # if no optionals or positionals are available, usage is just prog
1.293 + elif usage is None and not actions:
1.294 + usage = '%(prog)s' % dict(prog=self._prog)
1.295 +
1.296 + # if optionals and positionals are available, calculate usage
1.297 + elif usage is None:
1.298 + prog = '%(prog)s' % dict(prog=self._prog)
1.299 +
1.300 + # split optionals from positionals
1.301 + optionals = []
1.302 + positionals = []
1.303 + for action in actions:
1.304 + if action.option_strings:
1.305 + optionals.append(action)
1.306 + else:
1.307 + positionals.append(action)
1.308 +
1.309 + # build full usage string
1.310 + format = self._format_actions_usage
1.311 + action_usage = format(optionals + positionals, groups)
1.312 + usage = ' '.join([s for s in [prog, action_usage] if s])
1.313 +
1.314 + # wrap the usage parts if it's too long
1.315 + text_width = self._width - self._current_indent
1.316 + if len(prefix) + len(usage) > text_width:
1.317 +
1.318 + # break usage into wrappable parts
1.319 + part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
1.320 + opt_usage = format(optionals, groups)
1.321 + pos_usage = format(positionals, groups)
1.322 + opt_parts = _re.findall(part_regexp, opt_usage)
1.323 + pos_parts = _re.findall(part_regexp, pos_usage)
1.324 + assert ' '.join(opt_parts) == opt_usage
1.325 + assert ' '.join(pos_parts) == pos_usage
1.326 +
1.327 + # helper for wrapping lines
1.328 + def get_lines(parts, indent, prefix=None):
1.329 + lines = []
1.330 + line = []
1.331 + if prefix is not None:
1.332 + line_len = len(prefix) - 1
1.333 + else:
1.334 + line_len = len(indent) - 1
1.335 + for part in parts:
1.336 + if line_len + 1 + len(part) > text_width:
1.337 + lines.append(indent + ' '.join(line))
1.338 + line = []
1.339 + line_len = len(indent) - 1
1.340 + line.append(part)
1.341 + line_len += len(part) + 1
1.342 + if line:
1.343 + lines.append(indent + ' '.join(line))
1.344 + if prefix is not None:
1.345 + lines[0] = lines[0][len(indent):]
1.346 + return lines
1.347 +
1.348 + # if prog is short, follow it with optionals or positionals
1.349 + if len(prefix) + len(prog) <= 0.75 * text_width:
1.350 + indent = ' ' * (len(prefix) + len(prog) + 1)
1.351 + if opt_parts:
1.352 + lines = get_lines([prog] + opt_parts, indent, prefix)
1.353 + lines.extend(get_lines(pos_parts, indent))
1.354 + elif pos_parts:
1.355 + lines = get_lines([prog] + pos_parts, indent, prefix)
1.356 + else:
1.357 + lines = [prog]
1.358 +
1.359 + # if prog is long, put it on its own line
1.360 + else:
1.361 + indent = ' ' * len(prefix)
1.362 + parts = opt_parts + pos_parts
1.363 + lines = get_lines(parts, indent)
1.364 + if len(lines) > 1:
1.365 + lines = []
1.366 + lines.extend(get_lines(opt_parts, indent))
1.367 + lines.extend(get_lines(pos_parts, indent))
1.368 + lines = [prog] + lines
1.369 +
1.370 + # join lines into usage
1.371 + usage = '\n'.join(lines)
1.372 +
1.373 + # prefix with 'usage:'
1.374 + return '%s%s\n\n' % (prefix, usage)
1.375 +
1.376 + def _format_actions_usage(self, actions, groups):
1.377 + # find group indices and identify actions in groups
1.378 + group_actions = set()
1.379 + inserts = {}
1.380 + for group in groups:
1.381 + try:
1.382 + start = actions.index(group._group_actions[0])
1.383 + except ValueError:
1.384 + continue
1.385 + else:
1.386 + end = start + len(group._group_actions)
1.387 + if actions[start:end] == group._group_actions:
1.388 + for action in group._group_actions:
1.389 + group_actions.add(action)
1.390 + if not group.required:
1.391 + inserts[start] = '['
1.392 + inserts[end] = ']'
1.393 + else:
1.394 + inserts[start] = '('
1.395 + inserts[end] = ')'
1.396 + for i in range(start + 1, end):
1.397 + inserts[i] = '|'
1.398 +
1.399 + # collect all actions format strings
1.400 + parts = []
1.401 + for i, action in enumerate(actions):
1.402 +
1.403 + # suppressed arguments are marked with None
1.404 + # remove | separators for suppressed arguments
1.405 + if action.help is SUPPRESS:
1.406 + parts.append(None)
1.407 + if inserts.get(i) == '|':
1.408 + inserts.pop(i)
1.409 + elif inserts.get(i + 1) == '|':
1.410 + inserts.pop(i + 1)
1.411 +
1.412 + # produce all arg strings
1.413 + elif not action.option_strings:
1.414 + part = self._format_args(action, action.dest)
1.415 +
1.416 + # if it's in a group, strip the outer []
1.417 + if action in group_actions:
1.418 + if part[0] == '[' and part[-1] == ']':
1.419 + part = part[1:-1]
1.420 +
1.421 + # add the action string to the list
1.422 + parts.append(part)
1.423 +
1.424 + # produce the first way to invoke the option in brackets
1.425 + else:
1.426 + option_string = action.option_strings[0]
1.427 +
1.428 + # if the Optional doesn't take a value, format is:
1.429 + # -s or --long
1.430 + if action.nargs == 0:
1.431 + part = '%s' % option_string
1.432 +
1.433 + # if the Optional takes a value, format is:
1.434 + # -s ARGS or --long ARGS
1.435 + else:
1.436 + default = action.dest.upper()
1.437 + args_string = self._format_args(action, default)
1.438 + part = '%s %s' % (option_string, args_string)
1.439 +
1.440 + # make it look optional if it's not required or in a group
1.441 + if not action.required and action not in group_actions:
1.442 + part = '[%s]' % part
1.443 +
1.444 + # add the action string to the list
1.445 + parts.append(part)
1.446 +
1.447 + # insert things at the necessary indices
1.448 + for i in sorted(inserts, reverse=True):
1.449 + parts[i:i] = [inserts[i]]
1.450 +
1.451 + # join all the action items with spaces
1.452 + text = ' '.join([item for item in parts if item is not None])
1.453 +
1.454 + # clean up separators for mutually exclusive groups
1.455 + open = r'[\[(]'
1.456 + close = r'[\])]'
1.457 + text = _re.sub(r'(%s) ' % open, r'\1', text)
1.458 + text = _re.sub(r' (%s)' % close, r'\1', text)
1.459 + text = _re.sub(r'%s *%s' % (open, close), r'', text)
1.460 + text = _re.sub(r'\(([^|]*)\)', r'\1', text)
1.461 + text = text.strip()
1.462 +
1.463 + # return the text
1.464 + return text
1.465 +
1.466 + def _format_text(self, text):
1.467 + if '%(prog)' in text:
1.468 + text = text % dict(prog=self._prog)
1.469 + text_width = self._width - self._current_indent
1.470 + indent = ' ' * self._current_indent
1.471 + return self._fill_text(text, text_width, indent) + '\n\n'
1.472 +
1.473 + def _format_action(self, action):
1.474 + # determine the required width and the entry label
1.475 + help_position = min(self._action_max_length + 2,
1.476 + self._max_help_position)
1.477 + help_width = self._width - help_position
1.478 + action_width = help_position - self._current_indent - 2
1.479 + action_header = self._format_action_invocation(action)
1.480 +
1.481 + # ho nelp; start on same line and add a final newline
1.482 + if not action.help:
1.483 + tup = self._current_indent, '', action_header
1.484 + action_header = '%*s%s\n' % tup
1.485 +
1.486 + # short action name; start on the same line and pad two spaces
1.487 + elif len(action_header) <= action_width:
1.488 + tup = self._current_indent, '', action_width, action_header
1.489 + action_header = '%*s%-*s ' % tup
1.490 + indent_first = 0
1.491 +
1.492 + # long action name; start on the next line
1.493 + else:
1.494 + tup = self._current_indent, '', action_header
1.495 + action_header = '%*s%s\n' % tup
1.496 + indent_first = help_position
1.497 +
1.498 + # collect the pieces of the action help
1.499 + parts = [action_header]
1.500 +
1.501 + # if there was help for the action, add lines of help text
1.502 + if action.help:
1.503 + help_text = self._expand_help(action)
1.504 + help_lines = self._split_lines(help_text, help_width)
1.505 + parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
1.506 + for line in help_lines[1:]:
1.507 + parts.append('%*s%s\n' % (help_position, '', line))
1.508 +
1.509 + # or add a newline if the description doesn't end with one
1.510 + elif not action_header.endswith('\n'):
1.511 + parts.append('\n')
1.512 +
1.513 + # if there are any sub-actions, add their help as well
1.514 + for subaction in self._iter_indented_subactions(action):
1.515 + parts.append(self._format_action(subaction))
1.516 +
1.517 + # return a single string
1.518 + return self._join_parts(parts)
1.519 +
1.520 + def _format_action_invocation(self, action):
1.521 + if not action.option_strings:
1.522 + metavar, = self._metavar_formatter(action, action.dest)(1)
1.523 + return metavar
1.524 +
1.525 + else:
1.526 + parts = []
1.527 +
1.528 + # if the Optional doesn't take a value, format is:
1.529 + # -s, --long
1.530 + if action.nargs == 0:
1.531 + parts.extend(action.option_strings)
1.532 +
1.533 + # if the Optional takes a value, format is:
1.534 + # -s ARGS, --long ARGS
1.535 + else:
1.536 + default = action.dest.upper()
1.537 + args_string = self._format_args(action, default)
1.538 + for option_string in action.option_strings:
1.539 + parts.append('%s %s' % (option_string, args_string))
1.540 +
1.541 + return ', '.join(parts)
1.542 +
1.543 + def _metavar_formatter(self, action, default_metavar):
1.544 + if action.metavar is not None:
1.545 + result = action.metavar
1.546 + elif action.choices is not None:
1.547 + choice_strs = [str(choice) for choice in action.choices]
1.548 + result = '{%s}' % ','.join(choice_strs)
1.549 + else:
1.550 + result = default_metavar
1.551 +
1.552 + def format(tuple_size):
1.553 + if isinstance(result, tuple):
1.554 + return result
1.555 + else:
1.556 + return (result, ) * tuple_size
1.557 + return format
1.558 +
1.559 + def _format_args(self, action, default_metavar):
1.560 + get_metavar = self._metavar_formatter(action, default_metavar)
1.561 + if action.nargs is None:
1.562 + result = '%s' % get_metavar(1)
1.563 + elif action.nargs == OPTIONAL:
1.564 + result = '[%s]' % get_metavar(1)
1.565 + elif action.nargs == ZERO_OR_MORE:
1.566 + result = '[%s [%s ...]]' % get_metavar(2)
1.567 + elif action.nargs == ONE_OR_MORE:
1.568 + result = '%s [%s ...]' % get_metavar(2)
1.569 + elif action.nargs == REMAINDER:
1.570 + result = '...'
1.571 + elif action.nargs == PARSER:
1.572 + result = '%s ...' % get_metavar(1)
1.573 + else:
1.574 + formats = ['%s' for _ in range(action.nargs)]
1.575 + result = ' '.join(formats) % get_metavar(action.nargs)
1.576 + return result
1.577 +
1.578 + def _expand_help(self, action):
1.579 + params = dict(vars(action), prog=self._prog)
1.580 + for name in list(params):
1.581 + if params[name] is SUPPRESS:
1.582 + del params[name]
1.583 + for name in list(params):
1.584 + if hasattr(params[name], '__name__'):
1.585 + params[name] = params[name].__name__
1.586 + if params.get('choices') is not None:
1.587 + choices_str = ', '.join([str(c) for c in params['choices']])
1.588 + params['choices'] = choices_str
1.589 + return self._get_help_string(action) % params
1.590 +
1.591 + def _iter_indented_subactions(self, action):
1.592 + try:
1.593 + get_subactions = action._get_subactions
1.594 + except AttributeError:
1.595 + pass
1.596 + else:
1.597 + self._indent()
1.598 + for subaction in get_subactions():
1.599 + yield subaction
1.600 + self._dedent()
1.601 +
1.602 + def _split_lines(self, text, width):
1.603 + text = self._whitespace_matcher.sub(' ', text).strip()
1.604 + return _textwrap.wrap(text, width)
1.605 +
1.606 + def _fill_text(self, text, width, indent):
1.607 + text = self._whitespace_matcher.sub(' ', text).strip()
1.608 + return _textwrap.fill(text, width, initial_indent=indent,
1.609 + subsequent_indent=indent)
1.610 +
1.611 + def _get_help_string(self, action):
1.612 + return action.help
1.613 +
1.614 +
1.615 +class RawDescriptionHelpFormatter(HelpFormatter):
1.616 + """Help message formatter which retains any formatting in descriptions.
1.617 +
1.618 + Only the name of this class is considered a public API. All the methods
1.619 + provided by the class are considered an implementation detail.
1.620 + """
1.621 +
1.622 + def _fill_text(self, text, width, indent):
1.623 + return ''.join([indent + line for line in text.splitlines(True)])
1.624 +
1.625 +
1.626 +class RawTextHelpFormatter(RawDescriptionHelpFormatter):
1.627 + """Help message formatter which retains formatting of all help text.
1.628 +
1.629 + Only the name of this class is considered a public API. All the methods
1.630 + provided by the class are considered an implementation detail.
1.631 + """
1.632 +
1.633 + def _split_lines(self, text, width):
1.634 + return text.splitlines()
1.635 +
1.636 +
1.637 +class ArgumentDefaultsHelpFormatter(HelpFormatter):
1.638 + """Help message formatter which adds default values to argument help.
1.639 +
1.640 + Only the name of this class is considered a public API. All the methods
1.641 + provided by the class are considered an implementation detail.
1.642 + """
1.643 +
1.644 + def _get_help_string(self, action):
1.645 + help = action.help
1.646 + if '%(default)' not in action.help:
1.647 + if action.default is not SUPPRESS:
1.648 + defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
1.649 + if action.option_strings or action.nargs in defaulting_nargs:
1.650 + help += ' (default: %(default)s)'
1.651 + return help
1.652 +
1.653 +
1.654 +# =====================
1.655 +# Options and Arguments
1.656 +# =====================
1.657 +
1.658 +def _get_action_name(argument):
1.659 + if argument is None:
1.660 + return None
1.661 + elif argument.option_strings:
1.662 + return '/'.join(argument.option_strings)
1.663 + elif argument.metavar not in (None, SUPPRESS):
1.664 + return argument.metavar
1.665 + elif argument.dest not in (None, SUPPRESS):
1.666 + return argument.dest
1.667 + else:
1.668 + return None
1.669 +
1.670 +
1.671 +class ArgumentError(Exception):
1.672 + """An error from creating or using an argument (optional or positional).
1.673 +
1.674 + The string value of this exception is the message, augmented with
1.675 + information about the argument that caused it.
1.676 + """
1.677 +
1.678 + def __init__(self, argument, message):
1.679 + self.argument_name = _get_action_name(argument)
1.680 + self.message = message
1.681 +
1.682 + def __str__(self):
1.683 + if self.argument_name is None:
1.684 + format = '%(message)s'
1.685 + else:
1.686 + format = 'argument %(argument_name)s: %(message)s'
1.687 + return format % dict(message=self.message,
1.688 + argument_name=self.argument_name)
1.689 +
1.690 +
1.691 +class ArgumentTypeError(Exception):
1.692 + """An error from trying to convert a command line string to a type."""
1.693 + pass
1.694 +
1.695 +
1.696 +# ==============
1.697 +# Action classes
1.698 +# ==============
1.699 +
1.700 +class Action(_AttributeHolder):
1.701 + """Information about how to convert command line strings to Python objects.
1.702 +
1.703 + Action objects are used by an ArgumentParser to represent the information
1.704 + needed to parse a single argument from one or more strings from the
1.705 + command line. The keyword arguments to the Action constructor are also
1.706 + all attributes of Action instances.
1.707 +
1.708 + Keyword Arguments:
1.709 +
1.710 + - option_strings -- A list of command-line option strings which
1.711 + should be associated with this action.
1.712 +
1.713 + - dest -- The name of the attribute to hold the created object(s)
1.714 +
1.715 + - nargs -- The number of command-line arguments that should be
1.716 + consumed. By default, one argument will be consumed and a single
1.717 + value will be produced. Other values include:
1.718 + - N (an integer) consumes N arguments (and produces a list)
1.719 + - '?' consumes zero or one arguments
1.720 + - '*' consumes zero or more arguments (and produces a list)
1.721 + - '+' consumes one or more arguments (and produces a list)
1.722 + Note that the difference between the default and nargs=1 is that
1.723 + with the default, a single value will be produced, while with
1.724 + nargs=1, a list containing a single value will be produced.
1.725 +
1.726 + - const -- The value to be produced if the option is specified and the
1.727 + option uses an action that takes no values.
1.728 +
1.729 + - default -- The value to be produced if the option is not specified.
1.730 +
1.731 + - type -- The type which the command-line arguments should be converted
1.732 + to, should be one of 'string', 'int', 'float', 'complex' or a
1.733 + callable object that accepts a single string argument. If None,
1.734 + 'string' is assumed.
1.735 +
1.736 + - choices -- A container of values that should be allowed. If not None,
1.737 + after a command-line argument has been converted to the appropriate
1.738 + type, an exception will be raised if it is not a member of this
1.739 + collection.
1.740 +
1.741 + - required -- True if the action must always be specified at the
1.742 + command line. This is only meaningful for optional command-line
1.743 + arguments.
1.744 +
1.745 + - help -- The help string describing the argument.
1.746 +
1.747 + - metavar -- The name to be used for the option's argument with the
1.748 + help string. If None, the 'dest' value will be used as the name.
1.749 + """
1.750 +
1.751 + def __init__(self,
1.752 + option_strings,
1.753 + dest,
1.754 + nargs=None,
1.755 + const=None,
1.756 + default=None,
1.757 + type=None,
1.758 + choices=None,
1.759 + required=False,
1.760 + help=None,
1.761 + metavar=None):
1.762 + self.option_strings = option_strings
1.763 + self.dest = dest
1.764 + self.nargs = nargs
1.765 + self.const = const
1.766 + self.default = default
1.767 + self.type = type
1.768 + self.choices = choices
1.769 + self.required = required
1.770 + self.help = help
1.771 + self.metavar = metavar
1.772 +
1.773 + def _get_kwargs(self):
1.774 + names = [
1.775 + 'option_strings',
1.776 + 'dest',
1.777 + 'nargs',
1.778 + 'const',
1.779 + 'default',
1.780 + 'type',
1.781 + 'choices',
1.782 + 'help',
1.783 + 'metavar',
1.784 + ]
1.785 + return [(name, getattr(self, name)) for name in names]
1.786 +
1.787 + def __call__(self, parser, namespace, values, option_string=None):
1.788 + raise NotImplementedError(_('.__call__() not defined'))
1.789 +
1.790 +
1.791 +class _StoreAction(Action):
1.792 +
1.793 + def __init__(self,
1.794 + option_strings,
1.795 + dest,
1.796 + nargs=None,
1.797 + const=None,
1.798 + default=None,
1.799 + type=None,
1.800 + choices=None,
1.801 + required=False,
1.802 + help=None,
1.803 + metavar=None):
1.804 + if nargs == 0:
1.805 + raise ValueError('nargs for store actions must be > 0; if you '
1.806 + 'have nothing to store, actions such as store '
1.807 + 'true or store const may be more appropriate')
1.808 + if const is not None and nargs != OPTIONAL:
1.809 + raise ValueError('nargs must be %r to supply const' % OPTIONAL)
1.810 + super(_StoreAction, self).__init__(
1.811 + option_strings=option_strings,
1.812 + dest=dest,
1.813 + nargs=nargs,
1.814 + const=const,
1.815 + default=default,
1.816 + type=type,
1.817 + choices=choices,
1.818 + required=required,
1.819 + help=help,
1.820 + metavar=metavar)
1.821 +
1.822 + def __call__(self, parser, namespace, values, option_string=None):
1.823 + setattr(namespace, self.dest, values)
1.824 +
1.825 +
1.826 +class _StoreConstAction(Action):
1.827 +
1.828 + def __init__(self,
1.829 + option_strings,
1.830 + dest,
1.831 + const,
1.832 + default=None,
1.833 + required=False,
1.834 + help=None,
1.835 + metavar=None):
1.836 + super(_StoreConstAction, self).__init__(
1.837 + option_strings=option_strings,
1.838 + dest=dest,
1.839 + nargs=0,
1.840 + const=const,
1.841 + default=default,
1.842 + required=required,
1.843 + help=help)
1.844 +
1.845 + def __call__(self, parser, namespace, values, option_string=None):
1.846 + setattr(namespace, self.dest, self.const)
1.847 +
1.848 +
1.849 +class _StoreTrueAction(_StoreConstAction):
1.850 +
1.851 + def __init__(self,
1.852 + option_strings,
1.853 + dest,
1.854 + default=False,
1.855 + required=False,
1.856 + help=None):
1.857 + super(_StoreTrueAction, self).__init__(
1.858 + option_strings=option_strings,
1.859 + dest=dest,
1.860 + const=True,
1.861 + default=default,
1.862 + required=required,
1.863 + help=help)
1.864 +
1.865 +
1.866 +class _StoreFalseAction(_StoreConstAction):
1.867 +
1.868 + def __init__(self,
1.869 + option_strings,
1.870 + dest,
1.871 + default=True,
1.872 + required=False,
1.873 + help=None):
1.874 + super(_StoreFalseAction, self).__init__(
1.875 + option_strings=option_strings,
1.876 + dest=dest,
1.877 + const=False,
1.878 + default=default,
1.879 + required=required,
1.880 + help=help)
1.881 +
1.882 +
1.883 +class _AppendAction(Action):
1.884 +
1.885 + def __init__(self,
1.886 + option_strings,
1.887 + dest,
1.888 + nargs=None,
1.889 + const=None,
1.890 + default=None,
1.891 + type=None,
1.892 + choices=None,
1.893 + required=False,
1.894 + help=None,
1.895 + metavar=None):
1.896 + if nargs == 0:
1.897 + raise ValueError('nargs for append actions must be > 0; if arg '
1.898 + 'strings are not supplying the value to append, '
1.899 + 'the append const action may be more appropriate')
1.900 + if const is not None and nargs != OPTIONAL:
1.901 + raise ValueError('nargs must be %r to supply const' % OPTIONAL)
1.902 + super(_AppendAction, self).__init__(
1.903 + option_strings=option_strings,
1.904 + dest=dest,
1.905 + nargs=nargs,
1.906 + const=const,
1.907 + default=default,
1.908 + type=type,
1.909 + choices=choices,
1.910 + required=required,
1.911 + help=help,
1.912 + metavar=metavar)
1.913 +
1.914 + def __call__(self, parser, namespace, values, option_string=None):
1.915 + items = _copy.copy(_ensure_value(namespace, self.dest, []))
1.916 + items.append(values)
1.917 + setattr(namespace, self.dest, items)
1.918 +
1.919 +
1.920 +class _AppendConstAction(Action):
1.921 +
1.922 + def __init__(self,
1.923 + option_strings,
1.924 + dest,
1.925 + const,
1.926 + default=None,
1.927 + required=False,
1.928 + help=None,
1.929 + metavar=None):
1.930 + super(_AppendConstAction, self).__init__(
1.931 + option_strings=option_strings,
1.932 + dest=dest,
1.933 + nargs=0,
1.934 + const=const,
1.935 + default=default,
1.936 + required=required,
1.937 + help=help,
1.938 + metavar=metavar)
1.939 +
1.940 + def __call__(self, parser, namespace, values, option_string=None):
1.941 + items = _copy.copy(_ensure_value(namespace, self.dest, []))
1.942 + items.append(self.const)
1.943 + setattr(namespace, self.dest, items)
1.944 +
1.945 +
1.946 +class _CountAction(Action):
1.947 +
1.948 + def __init__(self,
1.949 + option_strings,
1.950 + dest,
1.951 + default=None,
1.952 + required=False,
1.953 + help=None):
1.954 + super(_CountAction, self).__init__(
1.955 + option_strings=option_strings,
1.956 + dest=dest,
1.957 + nargs=0,
1.958 + default=default,
1.959 + required=required,
1.960 + help=help)
1.961 +
1.962 + def __call__(self, parser, namespace, values, option_string=None):
1.963 + new_count = _ensure_value(namespace, self.dest, 0) + 1
1.964 + setattr(namespace, self.dest, new_count)
1.965 +
1.966 +
1.967 +class _HelpAction(Action):
1.968 +
1.969 + def __init__(self,
1.970 + option_strings,
1.971 + dest=SUPPRESS,
1.972 + default=SUPPRESS,
1.973 + help=None):
1.974 + super(_HelpAction, self).__init__(
1.975 + option_strings=option_strings,
1.976 + dest=dest,
1.977 + default=default,
1.978 + nargs=0,
1.979 + help=help)
1.980 +
1.981 + def __call__(self, parser, namespace, values, option_string=None):
1.982 + parser.print_help()
1.983 + parser.exit()
1.984 +
1.985 +
1.986 +class _VersionAction(Action):
1.987 +
1.988 + def __init__(self,
1.989 + option_strings,
1.990 + version=None,
1.991 + dest=SUPPRESS,
1.992 + default=SUPPRESS,
1.993 + help="show program's version number and exit"):
1.994 + super(_VersionAction, self).__init__(
1.995 + option_strings=option_strings,
1.996 + dest=dest,
1.997 + default=default,
1.998 + nargs=0,
1.999 + help=help)
1.1000 + self.version = version
1.1001 +
1.1002 + def __call__(self, parser, namespace, values, option_string=None):
1.1003 + version = self.version
1.1004 + if version is None:
1.1005 + version = parser.version
1.1006 + formatter = parser._get_formatter()
1.1007 + formatter.add_text(version)
1.1008 + parser.exit(message=formatter.format_help())
1.1009 +
1.1010 +
1.1011 +class _SubParsersAction(Action):
1.1012 +
1.1013 + class _ChoicesPseudoAction(Action):
1.1014 +
1.1015 + def __init__(self, name, help):
1.1016 + sup = super(_SubParsersAction._ChoicesPseudoAction, self)
1.1017 + sup.__init__(option_strings=[], dest=name, help=help)
1.1018 +
1.1019 + def __init__(self,
1.1020 + option_strings,
1.1021 + prog,
1.1022 + parser_class,
1.1023 + dest=SUPPRESS,
1.1024 + help=None,
1.1025 + metavar=None):
1.1026 +
1.1027 + self._prog_prefix = prog
1.1028 + self._parser_class = parser_class
1.1029 + self._name_parser_map = {}
1.1030 + self._choices_actions = []
1.1031 +
1.1032 + super(_SubParsersAction, self).__init__(
1.1033 + option_strings=option_strings,
1.1034 + dest=dest,
1.1035 + nargs=PARSER,
1.1036 + choices=self._name_parser_map,
1.1037 + help=help,
1.1038 + metavar=metavar)
1.1039 +
1.1040 + def add_parser(self, name, **kwargs):
1.1041 + # set prog from the existing prefix
1.1042 + if kwargs.get('prog') is None:
1.1043 + kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
1.1044 +
1.1045 + # create a pseudo-action to hold the choice help
1.1046 + if 'help' in kwargs:
1.1047 + help = kwargs.pop('help')
1.1048 + choice_action = self._ChoicesPseudoAction(name, help)
1.1049 + self._choices_actions.append(choice_action)
1.1050 +
1.1051 + # create the parser and add it to the map
1.1052 + parser = self._parser_class(**kwargs)
1.1053 + self._name_parser_map[name] = parser
1.1054 + return parser
1.1055 +
1.1056 + def _get_subactions(self):
1.1057 + return self._choices_actions
1.1058 +
1.1059 + def __call__(self, parser, namespace, values, option_string=None):
1.1060 + parser_name = values[0]
1.1061 + arg_strings = values[1:]
1.1062 +
1.1063 + # set the parser name if requested
1.1064 + if self.dest is not SUPPRESS:
1.1065 + setattr(namespace, self.dest, parser_name)
1.1066 +
1.1067 + # select the parser
1.1068 + try:
1.1069 + parser = self._name_parser_map[parser_name]
1.1070 + except KeyError:
1.1071 + tup = parser_name, ', '.join(self._name_parser_map)
1.1072 + msg = _('unknown parser %r (choices: %s)' % tup)
1.1073 + raise ArgumentError(self, msg)
1.1074 +
1.1075 + # parse all the remaining options into the namespace
1.1076 + parser.parse_args(arg_strings, namespace)
1.1077 +
1.1078 +
1.1079 +# ==============
1.1080 +# Type classes
1.1081 +# ==============
1.1082 +
1.1083 +class FileType(object):
1.1084 + """Factory for creating file object types
1.1085 +
1.1086 + Instances of FileType are typically passed as type= arguments to the
1.1087 + ArgumentParser add_argument() method.
1.1088 +
1.1089 + Keyword Arguments:
1.1090 + - mode -- A string indicating how the file is to be opened. Accepts the
1.1091 + same values as the builtin open() function.
1.1092 + - bufsize -- The file's desired buffer size. Accepts the same values as
1.1093 + the builtin open() function.
1.1094 + """
1.1095 +
1.1096 + def __init__(self, mode='r', bufsize=None):
1.1097 + self._mode = mode
1.1098 + self._bufsize = bufsize
1.1099 +
1.1100 + def __call__(self, string):
1.1101 + # the special argument "-" means sys.std{in,out}
1.1102 + if string == '-':
1.1103 + if 'r' in self._mode:
1.1104 + return _sys.stdin
1.1105 + elif 'w' in self._mode:
1.1106 + return _sys.stdout
1.1107 + else:
1.1108 + msg = _('argument "-" with mode %r' % self._mode)
1.1109 + raise ValueError(msg)
1.1110 +
1.1111 + # all other arguments are used as file names
1.1112 + if self._bufsize:
1.1113 + return open(string, self._mode, self._bufsize)
1.1114 + else:
1.1115 + return open(string, self._mode)
1.1116 +
1.1117 + def __repr__(self):
1.1118 + args = [self._mode, self._bufsize]
1.1119 + args_str = ', '.join([repr(arg) for arg in args if arg is not None])
1.1120 + return '%s(%s)' % (type(self).__name__, args_str)
1.1121 +
1.1122 +# ===========================
1.1123 +# Optional and Positional Parsing
1.1124 +# ===========================
1.1125 +
1.1126 +class Namespace(_AttributeHolder):
1.1127 + """Simple object for storing attributes.
1.1128 +
1.1129 + Implements equality by attribute names and values, and provides a simple
1.1130 + string representation.
1.1131 + """
1.1132 +
1.1133 + def __init__(self, **kwargs):
1.1134 + for name in kwargs:
1.1135 + setattr(self, name, kwargs[name])
1.1136 +
1.1137 + def __eq__(self, other):
1.1138 + return vars(self) == vars(other)
1.1139 +
1.1140 + def __ne__(self, other):
1.1141 + return not (self == other)
1.1142 +
1.1143 + def __contains__(self, key):
1.1144 + return key in self.__dict__
1.1145 +
1.1146 +
1.1147 +class _ActionsContainer(object):
1.1148 +
1.1149 + def __init__(self,
1.1150 + description,
1.1151 + prefix_chars,
1.1152 + argument_default,
1.1153 + conflict_handler):
1.1154 + super(_ActionsContainer, self).__init__()
1.1155 +
1.1156 + self.description = description
1.1157 + self.argument_default = argument_default
1.1158 + self.prefix_chars = prefix_chars
1.1159 + self.conflict_handler = conflict_handler
1.1160 +
1.1161 + # set up registries
1.1162 + self._registries = {}
1.1163 +
1.1164 + # register actions
1.1165 + self.register('action', None, _StoreAction)
1.1166 + self.register('action', 'store', _StoreAction)
1.1167 + self.register('action', 'store_const', _StoreConstAction)
1.1168 + self.register('action', 'store_true', _StoreTrueAction)
1.1169 + self.register('action', 'store_false', _StoreFalseAction)
1.1170 + self.register('action', 'append', _AppendAction)
1.1171 + self.register('action', 'append_const', _AppendConstAction)
1.1172 + self.register('action', 'count', _CountAction)
1.1173 + self.register('action', 'help', _HelpAction)
1.1174 + self.register('action', 'version', _VersionAction)
1.1175 + self.register('action', 'parsers', _SubParsersAction)
1.1176 +
1.1177 + # raise an exception if the conflict handler is invalid
1.1178 + self._get_handler()
1.1179 +
1.1180 + # action storage
1.1181 + self._actions = []
1.1182 + self._option_string_actions = {}
1.1183 +
1.1184 + # groups
1.1185 + self._action_groups = []
1.1186 + self._mutually_exclusive_groups = []
1.1187 +
1.1188 + # defaults storage
1.1189 + self._defaults = {}
1.1190 +
1.1191 + # determines whether an "option" looks like a negative number
1.1192 + self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')
1.1193 +
1.1194 + # whether or not there are any optionals that look like negative
1.1195 + # numbers -- uses a list so it can be shared and edited
1.1196 + self._has_negative_number_optionals = []
1.1197 +
1.1198 + # ====================
1.1199 + # Registration methods
1.1200 + # ====================
1.1201 + def register(self, registry_name, value, object):
1.1202 + registry = self._registries.setdefault(registry_name, {})
1.1203 + registry[value] = object
1.1204 +
1.1205 + def _registry_get(self, registry_name, value, default=None):
1.1206 + return self._registries[registry_name].get(value, default)
1.1207 +
1.1208 + # ==================================
1.1209 + # Namespace default accessor methods
1.1210 + # ==================================
1.1211 + def set_defaults(self, **kwargs):
1.1212 + self._defaults.update(kwargs)
1.1213 +
1.1214 + # if these defaults match any existing arguments, replace
1.1215 + # the previous default on the object with the new one
1.1216 + for action in self._actions:
1.1217 + if action.dest in kwargs:
1.1218 + action.default = kwargs[action.dest]
1.1219 +
1.1220 + def get_default(self, dest):
1.1221 + for action in self._actions:
1.1222 + if action.dest == dest and action.default is not None:
1.1223 + return action.default
1.1224 + return self._defaults.get(dest, None)
1.1225 +
1.1226 +
1.1227 + # =======================
1.1228 + # Adding argument actions
1.1229 + # =======================
1.1230 + def add_argument(self, *args, **kwargs):
1.1231 + """
1.1232 + add_argument(dest, ..., name=value, ...)
1.1233 + add_argument(option_string, option_string, ..., name=value, ...)
1.1234 + """
1.1235 +
1.1236 + # if no positional args are supplied or only one is supplied and
1.1237 + # it doesn't look like an option string, parse a positional
1.1238 + # argument
1.1239 + chars = self.prefix_chars
1.1240 + if not args or len(args) == 1 and args[0][0] not in chars:
1.1241 + if args and 'dest' in kwargs:
1.1242 + raise ValueError('dest supplied twice for positional argument')
1.1243 + kwargs = self._get_positional_kwargs(*args, **kwargs)
1.1244 +
1.1245 + # otherwise, we're adding an optional argument
1.1246 + else:
1.1247 + kwargs = self._get_optional_kwargs(*args, **kwargs)
1.1248 +
1.1249 + # if no default was supplied, use the parser-level default
1.1250 + if 'default' not in kwargs:
1.1251 + dest = kwargs['dest']
1.1252 + if dest in self._defaults:
1.1253 + kwargs['default'] = self._defaults[dest]
1.1254 + elif self.argument_default is not None:
1.1255 + kwargs['default'] = self.argument_default
1.1256 +
1.1257 + # create the action object, and add it to the parser
1.1258 + action_class = self._pop_action_class(kwargs)
1.1259 + if not _callable(action_class):
1.1260 + raise ValueError('unknown action "%s"' % action_class)
1.1261 + action = action_class(**kwargs)
1.1262 +
1.1263 + # raise an error if the action type is not callable
1.1264 + type_func = self._registry_get('type', action.type, action.type)
1.1265 + if not _callable(type_func):
1.1266 + raise ValueError('%r is not callable' % type_func)
1.1267 +
1.1268 + return self._add_action(action)
1.1269 +
1.1270 + def add_argument_group(self, *args, **kwargs):
1.1271 + group = _ArgumentGroup(self, *args, **kwargs)
1.1272 + self._action_groups.append(group)
1.1273 + return group
1.1274 +
1.1275 + def add_mutually_exclusive_group(self, **kwargs):
1.1276 + group = _MutuallyExclusiveGroup(self, **kwargs)
1.1277 + self._mutually_exclusive_groups.append(group)
1.1278 + return group
1.1279 +
1.1280 + def _add_action(self, action):
1.1281 + # resolve any conflicts
1.1282 + self._check_conflict(action)
1.1283 +
1.1284 + # add to actions list
1.1285 + self._actions.append(action)
1.1286 + action.container = self
1.1287 +
1.1288 + # index the action by any option strings it has
1.1289 + for option_string in action.option_strings:
1.1290 + self._option_string_actions[option_string] = action
1.1291 +
1.1292 + # set the flag if any option strings look like negative numbers
1.1293 + for option_string in action.option_strings:
1.1294 + if self._negative_number_matcher.match(option_string):
1.1295 + if not self._has_negative_number_optionals:
1.1296 + self._has_negative_number_optionals.append(True)
1.1297 +
1.1298 + # return the created action
1.1299 + return action
1.1300 +
1.1301 + def _remove_action(self, action):
1.1302 + self._actions.remove(action)
1.1303 +
1.1304 + def _add_container_actions(self, container):
1.1305 + # collect groups by titles
1.1306 + title_group_map = {}
1.1307 + for group in self._action_groups:
1.1308 + if group.title in title_group_map:
1.1309 + msg = _('cannot merge actions - two groups are named %r')
1.1310 + raise ValueError(msg % (group.title))
1.1311 + title_group_map[group.title] = group
1.1312 +
1.1313 + # map each action to its group
1.1314 + group_map = {}
1.1315 + for group in container._action_groups:
1.1316 +
1.1317 + # if a group with the title exists, use that, otherwise
1.1318 + # create a new group matching the container's group
1.1319 + if group.title not in title_group_map:
1.1320 + title_group_map[group.title] = self.add_argument_group(
1.1321 + title=group.title,
1.1322 + description=group.description,
1.1323 + conflict_handler=group.conflict_handler)
1.1324 +
1.1325 + # map the actions to their new group
1.1326 + for action in group._group_actions:
1.1327 + group_map[action] = title_group_map[group.title]
1.1328 +
1.1329 + # add container's mutually exclusive groups
1.1330 + # NOTE: if add_mutually_exclusive_group ever gains title= and
1.1331 + # description= then this code will need to be expanded as above
1.1332 + for group in container._mutually_exclusive_groups:
1.1333 + mutex_group = self.add_mutually_exclusive_group(
1.1334 + required=group.required)
1.1335 +
1.1336 + # map the actions to their new mutex group
1.1337 + for action in group._group_actions:
1.1338 + group_map[action] = mutex_group
1.1339 +
1.1340 + # add all actions to this container or their group
1.1341 + for action in container._actions:
1.1342 + group_map.get(action, self)._add_action(action)
1.1343 +
1.1344 + def _get_positional_kwargs(self, dest, **kwargs):
1.1345 + # make sure required is not specified
1.1346 + if 'required' in kwargs:
1.1347 + msg = _("'required' is an invalid argument for positionals")
1.1348 + raise TypeError(msg)
1.1349 +
1.1350 + # mark positional arguments as required if at least one is
1.1351 + # always required
1.1352 + if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
1.1353 + kwargs['required'] = True
1.1354 + if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
1.1355 + kwargs['required'] = True
1.1356 +
1.1357 + # return the keyword arguments with no option strings
1.1358 + return dict(kwargs, dest=dest, option_strings=[])
1.1359 +
1.1360 + def _get_optional_kwargs(self, *args, **kwargs):
1.1361 + # determine short and long option strings
1.1362 + option_strings = []
1.1363 + long_option_strings = []
1.1364 + for option_string in args:
1.1365 + # error on strings that don't start with an appropriate prefix
1.1366 + if not option_string[0] in self.prefix_chars:
1.1367 + msg = _('invalid option string %r: '
1.1368 + 'must start with a character %r')
1.1369 + tup = option_string, self.prefix_chars
1.1370 + raise ValueError(msg % tup)
1.1371 +
1.1372 + # strings starting with two prefix characters are long options
1.1373 + option_strings.append(option_string)
1.1374 + if option_string[0] in self.prefix_chars:
1.1375 + if len(option_string) > 1:
1.1376 + if option_string[1] in self.prefix_chars:
1.1377 + long_option_strings.append(option_string)
1.1378 +
1.1379 + # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
1.1380 + dest = kwargs.pop('dest', None)
1.1381 + if dest is None:
1.1382 + if long_option_strings:
1.1383 + dest_option_string = long_option_strings[0]
1.1384 + else:
1.1385 + dest_option_string = option_strings[0]
1.1386 + dest = dest_option_string.lstrip(self.prefix_chars)
1.1387 + if not dest:
1.1388 + msg = _('dest= is required for options like %r')
1.1389 + raise ValueError(msg % option_string)
1.1390 + dest = dest.replace('-', '_')
1.1391 +
1.1392 + # return the updated keyword arguments
1.1393 + return dict(kwargs, dest=dest, option_strings=option_strings)
1.1394 +
1.1395 + def _pop_action_class(self, kwargs, default=None):
1.1396 + action = kwargs.pop('action', default)
1.1397 + return self._registry_get('action', action, action)
1.1398 +
1.1399 + def _get_handler(self):
1.1400 + # determine function from conflict handler string
1.1401 + handler_func_name = '_handle_conflict_%s' % self.conflict_handler
1.1402 + try:
1.1403 + return getattr(self, handler_func_name)
1.1404 + except AttributeError:
1.1405 + msg = _('invalid conflict_resolution value: %r')
1.1406 + raise ValueError(msg % self.conflict_handler)
1.1407 +
1.1408 + def _check_conflict(self, action):
1.1409 +
1.1410 + # find all options that conflict with this option
1.1411 + confl_optionals = []
1.1412 + for option_string in action.option_strings:
1.1413 + if option_string in self._option_string_actions:
1.1414 + confl_optional = self._option_string_actions[option_string]
1.1415 + confl_optionals.append((option_string, confl_optional))
1.1416 +
1.1417 + # resolve any conflicts
1.1418 + if confl_optionals:
1.1419 + conflict_handler = self._get_handler()
1.1420 + conflict_handler(action, confl_optionals)
1.1421 +
1.1422 + def _handle_conflict_error(self, action, conflicting_actions):
1.1423 + message = _('conflicting option string(s): %s')
1.1424 + conflict_string = ', '.join([option_string
1.1425 + for option_string, action
1.1426 + in conflicting_actions])
1.1427 + raise ArgumentError(action, message % conflict_string)
1.1428 +
1.1429 + def _handle_conflict_resolve(self, action, conflicting_actions):
1.1430 +
1.1431 + # remove all conflicting options
1.1432 + for option_string, action in conflicting_actions:
1.1433 +
1.1434 + # remove the conflicting option
1.1435 + action.option_strings.remove(option_string)
1.1436 + self._option_string_actions.pop(option_string, None)
1.1437 +
1.1438 + # if the option now has no option string, remove it from the
1.1439 + # container holding it
1.1440 + if not action.option_strings:
1.1441 + action.container._remove_action(action)
1.1442 +
1.1443 +
1.1444 +class _ArgumentGroup(_ActionsContainer):
1.1445 +
1.1446 + def __init__(self, container, title=None, description=None, **kwargs):
1.1447 + # add any missing keyword arguments by checking the container
1.1448 + update = kwargs.setdefault
1.1449 + update('conflict_handler', container.conflict_handler)
1.1450 + update('prefix_chars', container.prefix_chars)
1.1451 + update('argument_default', container.argument_default)
1.1452 + super_init = super(_ArgumentGroup, self).__init__
1.1453 + super_init(description=description, **kwargs)
1.1454 +
1.1455 + # group attributes
1.1456 + self.title = title
1.1457 + self._group_actions = []
1.1458 +
1.1459 + # share most attributes with the container
1.1460 + self._registries = container._registries
1.1461 + self._actions = container._actions
1.1462 + self._option_string_actions = container._option_string_actions
1.1463 + self._defaults = container._defaults
1.1464 + self._has_negative_number_optionals = \
1.1465 + container._has_negative_number_optionals
1.1466 +
1.1467 + def _add_action(self, action):
1.1468 + action = super(_ArgumentGroup, self)._add_action(action)
1.1469 + self._group_actions.append(action)
1.1470 + return action
1.1471 +
1.1472 + def _remove_action(self, action):
1.1473 + super(_ArgumentGroup, self)._remove_action(action)
1.1474 + self._group_actions.remove(action)
1.1475 +
1.1476 +
1.1477 +class _MutuallyExclusiveGroup(_ArgumentGroup):
1.1478 +
1.1479 + def __init__(self, container, required=False):
1.1480 + super(_MutuallyExclusiveGroup, self).__init__(container)
1.1481 + self.required = required
1.1482 + self._container = container
1.1483 +
1.1484 + def _add_action(self, action):
1.1485 + if action.required:
1.1486 + msg = _('mutually exclusive arguments must be optional')
1.1487 + raise ValueError(msg)
1.1488 + action = self._container._add_action(action)
1.1489 + self._group_actions.append(action)
1.1490 + return action
1.1491 +
1.1492 + def _remove_action(self, action):
1.1493 + self._container._remove_action(action)
1.1494 + self._group_actions.remove(action)
1.1495 +
1.1496 +
1.1497 +class ArgumentParser(_AttributeHolder, _ActionsContainer):
1.1498 + """Object for parsing command line strings into Python objects.
1.1499 +
1.1500 + Keyword Arguments:
1.1501 + - prog -- The name of the program (default: sys.argv[0])
1.1502 + - usage -- A usage message (default: auto-generated from arguments)
1.1503 + - description -- A description of what the program does
1.1504 + - epilog -- Text following the argument descriptions
1.1505 + - parents -- Parsers whose arguments should be copied into this one
1.1506 + - formatter_class -- HelpFormatter class for printing help messages
1.1507 + - prefix_chars -- Characters that prefix optional arguments
1.1508 + - fromfile_prefix_chars -- Characters that prefix files containing
1.1509 + additional arguments
1.1510 + - argument_default -- The default value for all arguments
1.1511 + - conflict_handler -- String indicating how to handle conflicts
1.1512 + - add_help -- Add a -h/-help option
1.1513 + """
1.1514 +
1.1515 + def __init__(self,
1.1516 + prog=None,
1.1517 + usage=None,
1.1518 + description=None,
1.1519 + epilog=None,
1.1520 + version=None,
1.1521 + parents=[],
1.1522 + formatter_class=HelpFormatter,
1.1523 + prefix_chars='-',
1.1524 + fromfile_prefix_chars=None,
1.1525 + argument_default=None,
1.1526 + conflict_handler='error',
1.1527 + add_help=True):
1.1528 +
1.1529 + if version is not None:
1.1530 + import warnings
1.1531 + warnings.warn(
1.1532 + """The "version" argument to ArgumentParser is deprecated. """
1.1533 + """Please use """
1.1534 + """"add_argument(..., action='version', version="N", ...)" """
1.1535 + """instead""", DeprecationWarning)
1.1536 +
1.1537 + superinit = super(ArgumentParser, self).__init__
1.1538 + superinit(description=description,
1.1539 + prefix_chars=prefix_chars,
1.1540 + argument_default=argument_default,
1.1541 + conflict_handler=conflict_handler)
1.1542 +
1.1543 + # default setting for prog
1.1544 + if prog is None:
1.1545 + prog = _os.path.basename(_sys.argv[0])
1.1546 +
1.1547 + self.prog = prog
1.1548 + self.usage = usage
1.1549 + self.epilog = epilog
1.1550 + self.version = version
1.1551 + self.formatter_class = formatter_class
1.1552 + self.fromfile_prefix_chars = fromfile_prefix_chars
1.1553 + self.add_help = add_help
1.1554 +
1.1555 + add_group = self.add_argument_group
1.1556 + self._positionals = add_group(_('positional arguments'))
1.1557 + self._optionals = add_group(_('optional arguments'))
1.1558 + self._subparsers = None
1.1559 +
1.1560 + # register types
1.1561 + def identity(string):
1.1562 + return string
1.1563 + self.register('type', None, identity)
1.1564 +
1.1565 + # add help and version arguments if necessary
1.1566 + # (using explicit default to override global argument_default)
1.1567 + default_prefix = '-' if '-' in prefix_chars else prefix_chars[0]
1.1568 + if self.add_help:
1.1569 + self.add_argument(
1.1570 + default_prefix+'h', default_prefix*2+'help',
1.1571 + action='help', default=SUPPRESS,
1.1572 + help=_('show this help message and exit'))
1.1573 + if self.version:
1.1574 + self.add_argument(
1.1575 + default_prefix+'v', default_prefix*2+'version',
1.1576 + action='version', default=SUPPRESS,
1.1577 + version=self.version,
1.1578 + help=_("show program's version number and exit"))
1.1579 +
1.1580 + # add parent arguments and defaults
1.1581 + for parent in parents:
1.1582 + self._add_container_actions(parent)
1.1583 + try:
1.1584 + defaults = parent._defaults
1.1585 + except AttributeError:
1.1586 + pass
1.1587 + else:
1.1588 + self._defaults.update(defaults)
1.1589 +
1.1590 + # =======================
1.1591 + # Pretty __repr__ methods
1.1592 + # =======================
1.1593 + def _get_kwargs(self):
1.1594 + names = [
1.1595 + 'prog',
1.1596 + 'usage',
1.1597 + 'description',
1.1598 + 'version',
1.1599 + 'formatter_class',
1.1600 + 'conflict_handler',
1.1601 + 'add_help',
1.1602 + ]
1.1603 + return [(name, getattr(self, name)) for name in names]
1.1604 +
1.1605 + # ==================================
1.1606 + # Optional/Positional adding methods
1.1607 + # ==================================
1.1608 + def add_subparsers(self, **kwargs):
1.1609 + if self._subparsers is not None:
1.1610 + self.error(_('cannot have multiple subparser arguments'))
1.1611 +
1.1612 + # add the parser class to the arguments if it's not present
1.1613 + kwargs.setdefault('parser_class', type(self))
1.1614 +
1.1615 + if 'title' in kwargs or 'description' in kwargs:
1.1616 + title = _(kwargs.pop('title', 'subcommands'))
1.1617 + description = _(kwargs.pop('description', None))
1.1618 + self._subparsers = self.add_argument_group(title, description)
1.1619 + else:
1.1620 + self._subparsers = self._positionals
1.1621 +
1.1622 + # prog defaults to the usage message of this parser, skipping
1.1623 + # optional arguments and with no "usage:" prefix
1.1624 + if kwargs.get('prog') is None:
1.1625 + formatter = self._get_formatter()
1.1626 + positionals = self._get_positional_actions()
1.1627 + groups = self._mutually_exclusive_groups
1.1628 + formatter.add_usage(self.usage, positionals, groups, '')
1.1629 + kwargs['prog'] = formatter.format_help().strip()
1.1630 +
1.1631 + # create the parsers action and add it to the positionals list
1.1632 + parsers_class = self._pop_action_class(kwargs, 'parsers')
1.1633 + action = parsers_class(option_strings=[], **kwargs)
1.1634 + self._subparsers._add_action(action)
1.1635 +
1.1636 + # return the created parsers action
1.1637 + return action
1.1638 +
1.1639 + def _add_action(self, action):
1.1640 + if action.option_strings:
1.1641 + self._optionals._add_action(action)
1.1642 + else:
1.1643 + self._positionals._add_action(action)
1.1644 + return action
1.1645 +
1.1646 + def _get_optional_actions(self):
1.1647 + return [action
1.1648 + for action in self._actions
1.1649 + if action.option_strings]
1.1650 +
1.1651 + def _get_positional_actions(self):
1.1652 + return [action
1.1653 + for action in self._actions
1.1654 + if not action.option_strings]
1.1655 +
1.1656 + # =====================================
1.1657 + # Command line argument parsing methods
1.1658 + # =====================================
1.1659 + def parse_args(self, args=None, namespace=None):
1.1660 + args, argv = self.parse_known_args(args, namespace)
1.1661 + if argv:
1.1662 + msg = _('unrecognized arguments: %s')
1.1663 + self.error(msg % ' '.join(argv))
1.1664 + return args
1.1665 +
1.1666 + def parse_known_args(self, args=None, namespace=None):
1.1667 + # args default to the system args
1.1668 + if args is None:
1.1669 + args = _sys.argv[1:]
1.1670 +
1.1671 + # default Namespace built from parser defaults
1.1672 + if namespace is None:
1.1673 + namespace = Namespace()
1.1674 +
1.1675 + # add any action defaults that aren't present
1.1676 + for action in self._actions:
1.1677 + if action.dest is not SUPPRESS:
1.1678 + if not hasattr(namespace, action.dest):
1.1679 + if action.default is not SUPPRESS:
1.1680 + default = action.default
1.1681 + if isinstance(action.default, str):
1.1682 + default = self._get_value(action, default)
1.1683 + setattr(namespace, action.dest, default)
1.1684 +
1.1685 + # add any parser defaults that aren't present
1.1686 + for dest in self._defaults:
1.1687 + if not hasattr(namespace, dest):
1.1688 + setattr(namespace, dest, self._defaults[dest])
1.1689 +
1.1690 + # parse the arguments and exit if there are any errors
1.1691 + try:
1.1692 + return self._parse_known_args(args, namespace)
1.1693 + except ArgumentError:
1.1694 + err = _sys.exc_info()[1]
1.1695 + self.error(str(err))
1.1696 +
1.1697 + def _parse_known_args(self, arg_strings, namespace):
1.1698 + # replace arg strings that are file references
1.1699 + if self.fromfile_prefix_chars is not None:
1.1700 + arg_strings = self._read_args_from_files(arg_strings)
1.1701 +
1.1702 + # map all mutually exclusive arguments to the other arguments
1.1703 + # they can't occur with
1.1704 + action_conflicts = {}
1.1705 + for mutex_group in self._mutually_exclusive_groups:
1.1706 + group_actions = mutex_group._group_actions
1.1707 + for i, mutex_action in enumerate(mutex_group._group_actions):
1.1708 + conflicts = action_conflicts.setdefault(mutex_action, [])
1.1709 + conflicts.extend(group_actions[:i])
1.1710 + conflicts.extend(group_actions[i + 1:])
1.1711 +
1.1712 + # find all option indices, and determine the arg_string_pattern
1.1713 + # which has an 'O' if there is an option at an index,
1.1714 + # an 'A' if there is an argument, or a '-' if there is a '--'
1.1715 + option_string_indices = {}
1.1716 + arg_string_pattern_parts = []
1.1717 + arg_strings_iter = iter(arg_strings)
1.1718 + for i, arg_string in enumerate(arg_strings_iter):
1.1719 +
1.1720 + # all args after -- are non-options
1.1721 + if arg_string == '--':
1.1722 + arg_string_pattern_parts.append('-')
1.1723 + for arg_string in arg_strings_iter:
1.1724 + arg_string_pattern_parts.append('A')
1.1725 +
1.1726 + # otherwise, add the arg to the arg strings
1.1727 + # and note the index if it was an option
1.1728 + else:
1.1729 + option_tuple = self._parse_optional(arg_string)
1.1730 + if option_tuple is None:
1.1731 + pattern = 'A'
1.1732 + else:
1.1733 + option_string_indices[i] = option_tuple
1.1734 + pattern = 'O'
1.1735 + arg_string_pattern_parts.append(pattern)
1.1736 +
1.1737 + # join the pieces together to form the pattern
1.1738 + arg_strings_pattern = ''.join(arg_string_pattern_parts)
1.1739 +
1.1740 + # converts arg strings to the appropriate and then takes the action
1.1741 + seen_actions = set()
1.1742 + seen_non_default_actions = set()
1.1743 +
1.1744 + def take_action(action, argument_strings, option_string=None):
1.1745 + seen_actions.add(action)
1.1746 + argument_values = self._get_values(action, argument_strings)
1.1747 +
1.1748 + # error if this argument is not allowed with other previously
1.1749 + # seen arguments, assuming that actions that use the default
1.1750 + # value don't really count as "present"
1.1751 + if argument_values is not action.default:
1.1752 + seen_non_default_actions.add(action)
1.1753 + for conflict_action in action_conflicts.get(action, []):
1.1754 + if conflict_action in seen_non_default_actions:
1.1755 + msg = _('not allowed with argument %s')
1.1756 + action_name = _get_action_name(conflict_action)
1.1757 + raise ArgumentError(action, msg % action_name)
1.1758 +
1.1759 + # take the action if we didn't receive a SUPPRESS value
1.1760 + # (e.g. from a default)
1.1761 + if argument_values is not SUPPRESS:
1.1762 + action(self, namespace, argument_values, option_string)
1.1763 +
1.1764 + # function to convert arg_strings into an optional action
1.1765 + def consume_optional(start_index):
1.1766 +
1.1767 + # get the optional identified at this index
1.1768 + option_tuple = option_string_indices[start_index]
1.1769 + action, option_string, explicit_arg = option_tuple
1.1770 +
1.1771 + # identify additional optionals in the same arg string
1.1772 + # (e.g. -xyz is the same as -x -y -z if no args are required)
1.1773 + match_argument = self._match_argument
1.1774 + action_tuples = []
1.1775 + while True:
1.1776 +
1.1777 + # if we found no optional action, skip it
1.1778 + if action is None:
1.1779 + extras.append(arg_strings[start_index])
1.1780 + return start_index + 1
1.1781 +
1.1782 + # if there is an explicit argument, try to match the
1.1783 + # optional's string arguments to only this
1.1784 + if explicit_arg is not None:
1.1785 + arg_count = match_argument(action, 'A')
1.1786 +
1.1787 + # if the action is a single-dash option and takes no
1.1788 + # arguments, try to parse more single-dash options out
1.1789 + # of the tail of the option string
1.1790 + chars = self.prefix_chars
1.1791 + if arg_count == 0 and option_string[1] not in chars:
1.1792 + action_tuples.append((action, [], option_string))
1.1793 + for char in self.prefix_chars:
1.1794 + option_string = char + explicit_arg[0]
1.1795 + explicit_arg = explicit_arg[1:] or None
1.1796 + optionals_map = self._option_string_actions
1.1797 + if option_string in optionals_map:
1.1798 + action = optionals_map[option_string]
1.1799 + break
1.1800 + else:
1.1801 + msg = _('ignored explicit argument %r')
1.1802 + raise ArgumentError(action, msg % explicit_arg)
1.1803 +
1.1804 + # if the action expect exactly one argument, we've
1.1805 + # successfully matched the option; exit the loop
1.1806 + elif arg_count == 1:
1.1807 + stop = start_index + 1
1.1808 + args = [explicit_arg]
1.1809 + action_tuples.append((action, args, option_string))
1.1810 + break
1.1811 +
1.1812 + # error if a double-dash option did not use the
1.1813 + # explicit argument
1.1814 + else:
1.1815 + msg = _('ignored explicit argument %r')
1.1816 + raise ArgumentError(action, msg % explicit_arg)
1.1817 +
1.1818 + # if there is no explicit argument, try to match the
1.1819 + # optional's string arguments with the following strings
1.1820 + # if successful, exit the loop
1.1821 + else:
1.1822 + start = start_index + 1
1.1823 + selected_patterns = arg_strings_pattern[start:]
1.1824 + arg_count = match_argument(action, selected_patterns)
1.1825 + stop = start + arg_count
1.1826 + args = arg_strings[start:stop]
1.1827 + action_tuples.append((action, args, option_string))
1.1828 + break
1.1829 +
1.1830 + # add the Optional to the list and return the index at which
1.1831 + # the Optional's string args stopped
1.1832 + assert action_tuples
1.1833 + for action, args, option_string in action_tuples:
1.1834 + take_action(action, args, option_string)
1.1835 + return stop
1.1836 +
1.1837 + # the list of Positionals left to be parsed; this is modified
1.1838 + # by consume_positionals()
1.1839 + positionals = self._get_positional_actions()
1.1840 +
1.1841 + # function to convert arg_strings into positional actions
1.1842 + def consume_positionals(start_index):
1.1843 + # match as many Positionals as possible
1.1844 + match_partial = self._match_arguments_partial
1.1845 + selected_pattern = arg_strings_pattern[start_index:]
1.1846 + arg_counts = match_partial(positionals, selected_pattern)
1.1847 +
1.1848 + # slice off the appropriate arg strings for each Positional
1.1849 + # and add the Positional and its args to the list
1.1850 + for action, arg_count in zip(positionals, arg_counts):
1.1851 + args = arg_strings[start_index: start_index + arg_count]
1.1852 + start_index += arg_count
1.1853 + take_action(action, args)
1.1854 +
1.1855 + # slice off the Positionals that we just parsed and return the
1.1856 + # index at which the Positionals' string args stopped
1.1857 + positionals[:] = positionals[len(arg_counts):]
1.1858 + return start_index
1.1859 +
1.1860 + # consume Positionals and Optionals alternately, until we have
1.1861 + # passed the last option string
1.1862 + extras = []
1.1863 + start_index = 0
1.1864 + if option_string_indices:
1.1865 + max_option_string_index = max(option_string_indices)
1.1866 + else:
1.1867 + max_option_string_index = -1
1.1868 + while start_index <= max_option_string_index:
1.1869 +
1.1870 + # consume any Positionals preceding the next option
1.1871 + next_option_string_index = min([
1.1872 + index
1.1873 + for index in option_string_indices
1.1874 + if index >= start_index])
1.1875 + if start_index != next_option_string_index:
1.1876 + positionals_end_index = consume_positionals(start_index)
1.1877 +
1.1878 + # only try to parse the next optional if we didn't consume
1.1879 + # the option string during the positionals parsing
1.1880 + if positionals_end_index > start_index:
1.1881 + start_index = positionals_end_index
1.1882 + continue
1.1883 + else:
1.1884 + start_index = positionals_end_index
1.1885 +
1.1886 + # if we consumed all the positionals we could and we're not
1.1887 + # at the index of an option string, there were extra arguments
1.1888 + if start_index not in option_string_indices:
1.1889 + strings = arg_strings[start_index:next_option_string_index]
1.1890 + extras.extend(strings)
1.1891 + start_index = next_option_string_index
1.1892 +
1.1893 + # consume the next optional and any arguments for it
1.1894 + start_index = consume_optional(start_index)
1.1895 +
1.1896 + # consume any positionals following the last Optional
1.1897 + stop_index = consume_positionals(start_index)
1.1898 +
1.1899 + # if we didn't consume all the argument strings, there were extras
1.1900 + extras.extend(arg_strings[stop_index:])
1.1901 +
1.1902 + # if we didn't use all the Positional objects, there were too few
1.1903 + # arg strings supplied.
1.1904 + if positionals:
1.1905 + self.error(_('too few arguments'))
1.1906 +
1.1907 + # make sure all required actions were present
1.1908 + for action in self._actions:
1.1909 + if action.required:
1.1910 + if action not in seen_actions:
1.1911 + name = _get_action_name(action)
1.1912 + self.error(_('argument %s is required') % name)
1.1913 +
1.1914 + # make sure all required groups had one option present
1.1915 + for group in self._mutually_exclusive_groups:
1.1916 + if group.required:
1.1917 + for action in group._group_actions:
1.1918 + if action in seen_non_default_actions:
1.1919 + break
1.1920 +
1.1921 + # if no actions were used, report the error
1.1922 + else:
1.1923 + names = [_get_action_name(action)
1.1924 + for action in group._group_actions
1.1925 + if action.help is not SUPPRESS]
1.1926 + msg = _('one of the arguments %s is required')
1.1927 + self.error(msg % ' '.join(names))
1.1928 +
1.1929 + # return the updated namespace and the extra arguments
1.1930 + return namespace, extras
1.1931 +
1.1932 + def _read_args_from_files(self, arg_strings):
1.1933 + # expand arguments referencing files
1.1934 + new_arg_strings = []
1.1935 + for arg_string in arg_strings:
1.1936 +
1.1937 + # for regular arguments, just add them back into the list
1.1938 + if arg_string[0] not in self.fromfile_prefix_chars:
1.1939 + new_arg_strings.append(arg_string)
1.1940 +
1.1941 + # replace arguments referencing files with the file content
1.1942 + else:
1.1943 + try:
1.1944 + args_file = open(arg_string[1:])
1.1945 + try:
1.1946 + arg_strings = []
1.1947 + for arg_line in args_file.read().splitlines():
1.1948 + for arg in self.convert_arg_line_to_args(arg_line):
1.1949 + arg_strings.append(arg)
1.1950 + arg_strings = self._read_args_from_files(arg_strings)
1.1951 + new_arg_strings.extend(arg_strings)
1.1952 + finally:
1.1953 + args_file.close()
1.1954 + except IOError:
1.1955 + err = _sys.exc_info()[1]
1.1956 + self.error(str(err))
1.1957 +
1.1958 + # return the modified argument list
1.1959 + return new_arg_strings
1.1960 +
1.1961 + def convert_arg_line_to_args(self, arg_line):
1.1962 + return [arg_line]
1.1963 +
1.1964 + def _match_argument(self, action, arg_strings_pattern):
1.1965 + # match the pattern for this action to the arg strings
1.1966 + nargs_pattern = self._get_nargs_pattern(action)
1.1967 + match = _re.match(nargs_pattern, arg_strings_pattern)
1.1968 +
1.1969 + # raise an exception if we weren't able to find a match
1.1970 + if match is None:
1.1971 + nargs_errors = {
1.1972 + None: _('expected one argument'),
1.1973 + OPTIONAL: _('expected at most one argument'),
1.1974 + ONE_OR_MORE: _('expected at least one argument'),
1.1975 + }
1.1976 + default = _('expected %s argument(s)') % action.nargs
1.1977 + msg = nargs_errors.get(action.nargs, default)
1.1978 + raise ArgumentError(action, msg)
1.1979 +
1.1980 + # return the number of arguments matched
1.1981 + return len(match.group(1))
1.1982 +
1.1983 + def _match_arguments_partial(self, actions, arg_strings_pattern):
1.1984 + # progressively shorten the actions list by slicing off the
1.1985 + # final actions until we find a match
1.1986 + result = []
1.1987 + for i in range(len(actions), 0, -1):
1.1988 + actions_slice = actions[:i]
1.1989 + pattern = ''.join([self._get_nargs_pattern(action)
1.1990 + for action in actions_slice])
1.1991 + match = _re.match(pattern, arg_strings_pattern)
1.1992 + if match is not None:
1.1993 + result.extend([len(string) for string in match.groups()])
1.1994 + break
1.1995 +
1.1996 + # return the list of arg string counts
1.1997 + return result
1.1998 +
1.1999 + def _parse_optional(self, arg_string):
1.2000 + # if it's an empty string, it was meant to be a positional
1.2001 + if not arg_string:
1.2002 + return None
1.2003 +
1.2004 + # if it doesn't start with a prefix, it was meant to be positional
1.2005 + if not arg_string[0] in self.prefix_chars:
1.2006 + return None
1.2007 +
1.2008 + # if the option string is present in the parser, return the action
1.2009 + if arg_string in self._option_string_actions:
1.2010 + action = self._option_string_actions[arg_string]
1.2011 + return action, arg_string, None
1.2012 +
1.2013 + # if it's just a single character, it was meant to be positional
1.2014 + if len(arg_string) == 1:
1.2015 + return None
1.2016 +
1.2017 + # if the option string before the "=" is present, return the action
1.2018 + if '=' in arg_string:
1.2019 + option_string, explicit_arg = arg_string.split('=', 1)
1.2020 + if option_string in self._option_string_actions:
1.2021 + action = self._option_string_actions[option_string]
1.2022 + return action, option_string, explicit_arg
1.2023 +
1.2024 + # search through all possible prefixes of the option string
1.2025 + # and all actions in the parser for possible interpretations
1.2026 + option_tuples = self._get_option_tuples(arg_string)
1.2027 +
1.2028 + # if multiple actions match, the option string was ambiguous
1.2029 + if len(option_tuples) > 1:
1.2030 + options = ', '.join([option_string
1.2031 + for action, option_string, explicit_arg in option_tuples])
1.2032 + tup = arg_string, options
1.2033 + self.error(_('ambiguous option: %s could match %s') % tup)
1.2034 +
1.2035 + # if exactly one action matched, this segmentation is good,
1.2036 + # so return the parsed action
1.2037 + elif len(option_tuples) == 1:
1.2038 + option_tuple, = option_tuples
1.2039 + return option_tuple
1.2040 +
1.2041 + # if it was not found as an option, but it looks like a negative
1.2042 + # number, it was meant to be positional
1.2043 + # unless there are negative-number-like options
1.2044 + if self._negative_number_matcher.match(arg_string):
1.2045 + if not self._has_negative_number_optionals:
1.2046 + return None
1.2047 +
1.2048 + # if it contains a space, it was meant to be a positional
1.2049 + if ' ' in arg_string:
1.2050 + return None
1.2051 +
1.2052 + # it was meant to be an optional but there is no such option
1.2053 + # in this parser (though it might be a valid option in a subparser)
1.2054 + return None, arg_string, None
1.2055 +
1.2056 + def _get_option_tuples(self, option_string):
1.2057 + result = []
1.2058 +
1.2059 + # option strings starting with two prefix characters are only
1.2060 + # split at the '='
1.2061 + chars = self.prefix_chars
1.2062 + if option_string[0] in chars and option_string[1] in chars:
1.2063 + if '=' in option_string:
1.2064 + option_prefix, explicit_arg = option_string.split('=', 1)
1.2065 + else:
1.2066 + option_prefix = option_string
1.2067 + explicit_arg = None
1.2068 + for option_string in self._option_string_actions:
1.2069 + if option_string.startswith(option_prefix):
1.2070 + action = self._option_string_actions[option_string]
1.2071 + tup = action, option_string, explicit_arg
1.2072 + result.append(tup)
1.2073 +
1.2074 + # single character options can be concatenated with their arguments
1.2075 + # but multiple character options always have to have their argument
1.2076 + # separate
1.2077 + elif option_string[0] in chars and option_string[1] not in chars:
1.2078 + option_prefix = option_string
1.2079 + explicit_arg = None
1.2080 + short_option_prefix = option_string[:2]
1.2081 + short_explicit_arg = option_string[2:]
1.2082 +
1.2083 + for option_string in self._option_string_actions:
1.2084 + if option_string == short_option_prefix:
1.2085 + action = self._option_string_actions[option_string]
1.2086 + tup = action, option_string, short_explicit_arg
1.2087 + result.append(tup)
1.2088 + elif option_string.startswith(option_prefix):
1.2089 + action = self._option_string_actions[option_string]
1.2090 + tup = action, option_string, explicit_arg
1.2091 + result.append(tup)
1.2092 +
1.2093 + # shouldn't ever get here
1.2094 + else:
1.2095 + self.error(_('unexpected option string: %s') % option_string)
1.2096 +
1.2097 + # return the collected option tuples
1.2098 + return result
1.2099 +
1.2100 + def _get_nargs_pattern(self, action):
1.2101 + # in all examples below, we have to allow for '--' args
1.2102 + # which are represented as '-' in the pattern
1.2103 + nargs = action.nargs
1.2104 +
1.2105 + # the default (None) is assumed to be a single argument
1.2106 + if nargs is None:
1.2107 + nargs_pattern = '(-*A-*)'
1.2108 +
1.2109 + # allow zero or one arguments
1.2110 + elif nargs == OPTIONAL:
1.2111 + nargs_pattern = '(-*A?-*)'
1.2112 +
1.2113 + # allow zero or more arguments
1.2114 + elif nargs == ZERO_OR_MORE:
1.2115 + nargs_pattern = '(-*[A-]*)'
1.2116 +
1.2117 + # allow one or more arguments
1.2118 + elif nargs == ONE_OR_MORE:
1.2119 + nargs_pattern = '(-*A[A-]*)'
1.2120 +
1.2121 + # allow any number of options or arguments
1.2122 + elif nargs == REMAINDER:
1.2123 + nargs_pattern = '([-AO]*)'
1.2124 +
1.2125 + # allow one argument followed by any number of options or arguments
1.2126 + elif nargs == PARSER:
1.2127 + nargs_pattern = '(-*A[-AO]*)'
1.2128 +
1.2129 + # all others should be integers
1.2130 + else:
1.2131 + nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
1.2132 +
1.2133 + # if this is an optional action, -- is not allowed
1.2134 + if action.option_strings:
1.2135 + nargs_pattern = nargs_pattern.replace('-*', '')
1.2136 + nargs_pattern = nargs_pattern.replace('-', '')
1.2137 +
1.2138 + # return the pattern
1.2139 + return nargs_pattern
1.2140 +
1.2141 + # ========================
1.2142 + # Value conversion methods
1.2143 + # ========================
1.2144 + def _get_values(self, action, arg_strings):
1.2145 + # for everything but PARSER args, strip out '--'
1.2146 + if action.nargs not in [PARSER, REMAINDER]:
1.2147 + arg_strings = [s for s in arg_strings if s != '--']
1.2148 +
1.2149 + # optional argument produces a default when not present
1.2150 + if not arg_strings and action.nargs == OPTIONAL:
1.2151 + if action.option_strings:
1.2152 + value = action.const
1.2153 + else:
1.2154 + value = action.default
1.2155 + if isinstance(value, str):
1.2156 + value = self._get_value(action, value)
1.2157 + self._check_value(action, value)
1.2158 +
1.2159 + # when nargs='*' on a positional, if there were no command-line
1.2160 + # args, use the default if it is anything other than None
1.2161 + elif (not arg_strings and action.nargs == ZERO_OR_MORE and
1.2162 + not action.option_strings):
1.2163 + if action.default is not None:
1.2164 + value = action.default
1.2165 + else:
1.2166 + value = arg_strings
1.2167 + self._check_value(action, value)
1.2168 +
1.2169 + # single argument or optional argument produces a single value
1.2170 + elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
1.2171 + arg_string, = arg_strings
1.2172 + value = self._get_value(action, arg_string)
1.2173 + self._check_value(action, value)
1.2174 +
1.2175 + # REMAINDER arguments convert all values, checking none
1.2176 + elif action.nargs == REMAINDER:
1.2177 + value = [self._get_value(action, v) for v in arg_strings]
1.2178 +
1.2179 + # PARSER arguments convert all values, but check only the first
1.2180 + elif action.nargs == PARSER:
1.2181 + value = [self._get_value(action, v) for v in arg_strings]
1.2182 + self._check_value(action, value[0])
1.2183 +
1.2184 + # all other types of nargs produce a list
1.2185 + else:
1.2186 + value = [self._get_value(action, v) for v in arg_strings]
1.2187 + for v in value:
1.2188 + self._check_value(action, v)
1.2189 +
1.2190 + # return the converted value
1.2191 + return value
1.2192 +
1.2193 + def _get_value(self, action, arg_string):
1.2194 + type_func = self._registry_get('type', action.type, action.type)
1.2195 + if not _callable(type_func):
1.2196 + msg = _('%r is not callable')
1.2197 + raise ArgumentError(action, msg % type_func)
1.2198 +
1.2199 + # convert the value to the appropriate type
1.2200 + try:
1.2201 + result = type_func(arg_string)
1.2202 +
1.2203 + # ArgumentTypeErrors indicate errors
1.2204 + except ArgumentTypeError:
1.2205 + name = getattr(action.type, '__name__', repr(action.type))
1.2206 + msg = str(_sys.exc_info()[1])
1.2207 + raise ArgumentError(action, msg)
1.2208 +
1.2209 + # TypeErrors or ValueErrors also indicate errors
1.2210 + except (TypeError, ValueError):
1.2211 + name = getattr(action.type, '__name__', repr(action.type))
1.2212 + msg = _('invalid %s value: %r')
1.2213 + raise ArgumentError(action, msg % (name, arg_string))
1.2214 +
1.2215 + # return the converted value
1.2216 + return result
1.2217 +
1.2218 + def _check_value(self, action, value):
1.2219 + # converted value must be one of the choices (if specified)
1.2220 + if action.choices is not None and value not in action.choices:
1.2221 + tup = value, ', '.join(map(repr, action.choices))
1.2222 + msg = _('invalid choice: %r (choose from %s)') % tup
1.2223 + raise ArgumentError(action, msg)
1.2224 +
1.2225 + # =======================
1.2226 + # Help-formatting methods
1.2227 + # =======================
1.2228 + def format_usage(self):
1.2229 + formatter = self._get_formatter()
1.2230 + formatter.add_usage(self.usage, self._actions,
1.2231 + self._mutually_exclusive_groups)
1.2232 + return formatter.format_help()
1.2233 +
1.2234 + def format_help(self):
1.2235 + formatter = self._get_formatter()
1.2236 +
1.2237 + # usage
1.2238 + formatter.add_usage(self.usage, self._actions,
1.2239 + self._mutually_exclusive_groups)
1.2240 +
1.2241 + # description
1.2242 + formatter.add_text(self.description)
1.2243 +
1.2244 + # positionals, optionals and user-defined groups
1.2245 + for action_group in self._action_groups:
1.2246 + formatter.start_section(action_group.title)
1.2247 + formatter.add_text(action_group.description)
1.2248 + formatter.add_arguments(action_group._group_actions)
1.2249 + formatter.end_section()
1.2250 +
1.2251 + # epilog
1.2252 + formatter.add_text(self.epilog)
1.2253 +
1.2254 + # determine help from format above
1.2255 + return formatter.format_help()
1.2256 +
1.2257 + def format_version(self):
1.2258 + import warnings
1.2259 + warnings.warn(
1.2260 + 'The format_version method is deprecated -- the "version" '
1.2261 + 'argument to ArgumentParser is no longer supported.',
1.2262 + DeprecationWarning)
1.2263 + formatter = self._get_formatter()
1.2264 + formatter.add_text(self.version)
1.2265 + return formatter.format_help()
1.2266 +
1.2267 + def _get_formatter(self):
1.2268 + return self.formatter_class(prog=self.prog)
1.2269 +
1.2270 + # =====================
1.2271 + # Help-printing methods
1.2272 + # =====================
1.2273 + def print_usage(self, file=None):
1.2274 + if file is None:
1.2275 + file = _sys.stdout
1.2276 + self._print_message(self.format_usage(), file)
1.2277 +
1.2278 + def print_help(self, file=None):
1.2279 + if file is None:
1.2280 + file = _sys.stdout
1.2281 + self._print_message(self.format_help(), file)
1.2282 +
1.2283 + def print_version(self, file=None):
1.2284 + import warnings
1.2285 + warnings.warn(
1.2286 + 'The print_version method is deprecated -- the "version" '
1.2287 + 'argument to ArgumentParser is no longer supported.',
1.2288 + DeprecationWarning)
1.2289 + self._print_message(self.format_version(), file)
1.2290 +
1.2291 + def _print_message(self, message, file=None):
1.2292 + if message:
1.2293 + if file is None:
1.2294 + file = _sys.stderr
1.2295 + file.write(message)
1.2296 +
1.2297 + # ===============
1.2298 + # Exiting methods
1.2299 + # ===============
1.2300 + def exit(self, status=0, message=None):
1.2301 + if message:
1.2302 + self._print_message(message, _sys.stderr)
1.2303 + _sys.exit(status)
1.2304 +
1.2305 + def error(self, message):
1.2306 + """error(message: string)
1.2307 +
1.2308 + Prints a usage message incorporating the message to stderr and
1.2309 + exits.
1.2310 +
1.2311 + If you override this in a subclass, it should not return -- it
1.2312 + should either exit or raise an exception.
1.2313 + """
1.2314 + self.print_usage(_sys.stderr)
1.2315 + self.exit(2, _('%s: error: %s\n') % (self.prog, message))