codekingpro/portable-devtools
114k
1"""A powerful, extensible, and easy-to-use option parser.2 3By Greg Ward <gward@python.net>4 5Originally distributed as Optik.6 7For support, use the optik-users@lists.sourceforge.net mailing list8(http://lists.sourceforge.net/lists/listinfo/optik-users).9 10Simple usage example:11 12 from optparse import OptionParser13 14 parser = OptionParser()15 parser.add_option("-f", "--file", dest="filename",16 help="write report to FILE", metavar="FILE")17 parser.add_option("-q", "--quiet",18 action="store_false", dest="verbose", default=True,19 help="don't print status messages to stdout")20 21 (options, args) = parser.parse_args()22"""23 24__version__ = "1.5.3"25 26__all__ = ['Option',27 'make_option',28 'SUPPRESS_HELP',29 'SUPPRESS_USAGE',30 'Values',31 'OptionContainer',32 'OptionGroup',33 'OptionParser',34 'HelpFormatter',35 'IndentedHelpFormatter',36 'TitledHelpFormatter',37 'OptParseError',38 'OptionError',39 'OptionConflictError',40 'OptionValueError',41 'BadOptionError',42 'check_choice']43 44__copyright__ = """45Copyright (c) 2001-2006 Gregory P. Ward. All rights reserved.46Copyright (c) 2002 Python Software Foundation. All rights reserved.47 48Redistribution and use in source and binary forms, with or without49modification, are permitted provided that the following conditions are50met:51 52 * Redistributions of source code must retain the above copyright53 notice, this list of conditions and the following disclaimer.54 55 * Redistributions in binary form must reproduce the above copyright56 notice, this list of conditions and the following disclaimer in the57 documentation and/or other materials provided with the distribution.58 59 * Neither the name of the author nor the names of its60 contributors may be used to endorse or promote products derived from61 this software without specific prior written permission.62 63THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS64IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED65TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A66PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR67CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,68EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,69PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR70PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF71LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING72NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS73SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.74"""75 76import sys, os77from gettext import gettext as _, ngettext78 79 80def _repr(self):81 return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self)82 83 84# This file was generated from:85# Id: option_parser.py 527 2006-07-23 15:21:30Z greg86# Id: option.py 522 2006-06-11 16:22:03Z gward87# Id: help.py 527 2006-07-23 15:21:30Z greg88# Id: errors.py 509 2006-04-20 00:58:24Z gward89 90 91class OptParseError (Exception):92 def __init__(self, msg):93 self.msg = msg94 95 def __str__(self):96 return self.msg97 98 99class OptionError (OptParseError):100 """101 Raised if an Option instance is created with invalid or102 inconsistent arguments.103 """104 105 def __init__(self, msg, option):106 self.msg = msg107 self.option_id = str(option)108 109 def __str__(self):110 if self.option_id:111 return "option %s: %s" % (self.option_id, self.msg)112 else:113 return self.msg114 115class OptionConflictError (OptionError):116 """117 Raised if conflicting options are added to an OptionParser.118 """119 120class OptionValueError (OptParseError):121 """122 Raised if an invalid option value is encountered on the command123 line.124 """125 126class BadOptionError (OptParseError):127 """128 Raised if an invalid option is seen on the command line.129 """130 def __init__(self, opt_str):131 self.opt_str = opt_str132 133 def __str__(self):134 return _("no such option: %s") % self.opt_str135 136class AmbiguousOptionError (BadOptionError):137 """138 Raised if an ambiguous option is seen on the command line.139 """140 def __init__(self, opt_str, possibilities):141 BadOptionError.__init__(self, opt_str)142 self.possibilities = possibilities143 144 def __str__(self):145 return (_("ambiguous option: %s (%s?)")146 % (self.opt_str, ", ".join(self.possibilities)))147 148 149class HelpFormatter:150 151 """152 Abstract base class for formatting option help. OptionParser153 instances should use one of the HelpFormatter subclasses for154 formatting help; by default IndentedHelpFormatter is used.155 156 Instance attributes:157 parser : OptionParser158 the controlling OptionParser instance159 indent_increment : int160 the number of columns to indent per nesting level161 max_help_position : int162 the maximum starting column for option help text163 help_position : int164 the calculated starting column for option help text;165 initially the same as the maximum166 width : int167 total number of columns for output (pass None to constructor for168 this value to be taken from the $COLUMNS environment variable)169 level : int170 current indentation level171 current_indent : int172 current indentation level (in columns)173 help_width : int174 number of columns available for option help text (calculated)175 default_tag : str176 text to replace with each option's default value, "%default"177 by default. Set to false value to disable default value expansion.178 option_strings : { Option : str }179 maps Option instances to the snippet of help text explaining180 the syntax of that option, e.g. "-h, --help" or181 "-fFILE, --file=FILE"182 _short_opt_fmt : str183 format string controlling how short options with values are184 printed in help text. Must be either "%s%s" ("-fFILE") or185 "%s %s" ("-f FILE"), because those are the two syntaxes that186 Optik supports.187 _long_opt_fmt : str188 similar but for long options; must be either "%s %s" ("--file FILE")189 or "%s=%s" ("--file=FILE").190 """191 192 NO_DEFAULT_VALUE = "none"193 194 def __init__(self,195 indent_increment,196 max_help_position,197 width,198 short_first):199 self.parser = None200 self.indent_increment = indent_increment201 if width is None:202 try:203 width = int(os.environ['COLUMNS'])204 except (KeyError, ValueError):205 width = 80206 width -= 2207 self.width = width208 self.help_position = self.max_help_position = \209 min(max_help_position, max(width - 20, indent_increment * 2))210 self.current_indent = 0211 self.level = 0212 self.help_width = None # computed later213 self.short_first = short_first214 self.default_tag = "%default"215 self.option_strings = {}216 self._short_opt_fmt = "%s %s"217 self._long_opt_fmt = "%s=%s"218 219 def set_parser(self, parser):220 self.parser = parser221 222 def set_short_opt_delimiter(self, delim):223 if delim not in ("", " "):224 raise ValueError(225 "invalid metavar delimiter for short options: %r" % delim)226 self._short_opt_fmt = "%s" + delim + "%s"227 228 def set_long_opt_delimiter(self, delim):229 if delim not in ("=", " "):230 raise ValueError(231 "invalid metavar delimiter for long options: %r" % delim)232 self._long_opt_fmt = "%s" + delim + "%s"233 234 def indent(self):235 self.current_indent += self.indent_increment236 self.level += 1237 238 def dedent(self):239 self.current_indent -= self.indent_increment240 assert self.current_indent >= 0, "Indent decreased below 0."241 self.level -= 1242 243 def format_usage(self, usage):244 raise NotImplementedError("subclasses must implement")245 246 def format_heading(self, heading):247 raise NotImplementedError("subclasses must implement")248 249 def _format_text(self, text):250 """251 Format a paragraph of free-form text for inclusion in the252 help output at the current indentation level.253 """254 import textwrap255 text_width = max(self.width - self.current_indent, 11)256 indent = " "*self.current_indent257 return textwrap.fill(text,258 text_width,259 initial_indent=indent,260 subsequent_indent=indent)261 262 def format_description(self, description):263 if description:264 return self._format_text(description) + "\n"265 else:266 return ""267 268 def format_epilog(self, epilog):269 if epilog:270 return "\n" + self._format_text(epilog) + "\n"271 else:272 return ""273 274 275 def expand_default(self, option):276 if self.parser is None or not self.default_tag:277 return option.help278 279 default_value = self.parser.defaults.get(option.dest)280 if default_value is NO_DEFAULT or default_value is None:281 default_value = self.NO_DEFAULT_VALUE282 283 return option.help.replace(self.default_tag, str(default_value))284 285 def format_option(self, option):286 # The help for each option consists of two parts:287 # * the opt strings and metavars288 # eg. ("-x", or "-fFILENAME, --file=FILENAME")289 # * the user-supplied help string290 # eg. ("turn on expert mode", "read data from FILENAME")291 #292 # If possible, we write both of these on the same line:293 # -x turn on expert mode294 #295 # But if the opt string list is too long, we put the help296 # string on a second line, indented to the same column it would297 # start in if it fit on the first line.298 # -fFILENAME, --file=FILENAME299 # read data from FILENAME300 result = []301 opts = self.option_strings[option]302 opt_width = self.help_position - self.current_indent - 2303 if len(opts) > opt_width:304 opts = "%*s%s\n" % (self.current_indent, "", opts)305 indent_first = self.help_position306 else: # start help on same line as opts307 opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts)308 indent_first = 0309 result.append(opts)310 if option.help:311 import textwrap312 help_text = self.expand_default(option)313 help_lines = textwrap.wrap(help_text, self.help_width)314 result.append("%*s%s\n" % (indent_first, "", help_lines[0]))315 result.extend(["%*s%s\n" % (self.help_position, "", line)316 for line in help_lines[1:]])317 elif opts[-1] != "\n":318 result.append("\n")319 return "".join(result)320 321 def store_option_strings(self, parser):322 self.indent()323 max_len = 0324 for opt in parser.option_list:325 strings = self.format_option_strings(opt)326 self.option_strings[opt] = strings327 max_len = max(max_len, len(strings) + self.current_indent)328 self.indent()329 for group in parser.option_groups:330 for opt in group.option_list:331 strings = self.format_option_strings(opt)332 self.option_strings[opt] = strings333 max_len = max(max_len, len(strings) + self.current_indent)334 self.dedent()335 self.dedent()336 self.help_position = min(max_len + 2, self.max_help_position)337 self.help_width = max(self.width - self.help_position, 11)338 339 def format_option_strings(self, option):340 """Return a comma-separated list of option strings & metavariables."""341 if option.takes_value():342 metavar = option.metavar or option.dest.upper()343 short_opts = [self._short_opt_fmt % (sopt, metavar)344 for sopt in option._short_opts]345 long_opts = [self._long_opt_fmt % (lopt, metavar)346 for lopt in option._long_opts]347 else:348 short_opts = option._short_opts349 long_opts = option._long_opts350 351 if self.short_first:352 opts = short_opts + long_opts353 else:354 opts = long_opts + short_opts355 356 return ", ".join(opts)357 358class IndentedHelpFormatter (HelpFormatter):359 """Format help with indented section bodies.360 """361 362 def __init__(self,363 indent_increment=2,364 max_help_position=24,365 width=None,366 short_first=1):367 HelpFormatter.__init__(368 self, indent_increment, max_help_position, width, short_first)369 370 def format_usage(self, usage):371 return _("Usage: %s\n") % usage372 373 def format_heading(self, heading):374 return "%*s%s:\n" % (self.current_indent, "", heading)375 376 377class TitledHelpFormatter (HelpFormatter):378 """Format help with underlined section headers.379 """380 381 def __init__(self,382 indent_increment=0,383 max_help_position=24,384 width=None,385 short_first=0):386 HelpFormatter.__init__ (387 self, indent_increment, max_help_position, width, short_first)388 389 def format_usage(self, usage):390 return "%s %s\n" % (self.format_heading(_("Usage")), usage)391 392 def format_heading(self, heading):393 return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading))394 395 396def _parse_num(val, type):397 if val[:2].lower() == "0x": # hexadecimal398 radix = 16399 elif val[:2].lower() == "0b": # binary400 radix = 2401 val = val[2:] or "0" # have to remove "0b" prefix402 elif val[:1] == "0": # octal403 radix = 8404 else: # decimal405 radix = 10406 407 return type(val, radix)408 409def _parse_int(val):410 return _parse_num(val, int)411 412_builtin_cvt = { "int" : (_parse_int, _("integer")),413 "long" : (_parse_int, _("integer")),414 "float" : (float, _("floating-point")),415 "complex" : (complex, _("complex")) }416 417def check_builtin(option, opt, value):418 (cvt, what) = _builtin_cvt[option.type]419 try:420 return cvt(value)421 except ValueError:422 raise OptionValueError(423 _("option %s: invalid %s value: %r") % (opt, what, value))424 425def check_choice(option, opt, value):426 if value in option.choices:427 return value428 else:429 choices = ", ".join(map(repr, option.choices))430 raise OptionValueError(431 _("option %s: invalid choice: %r (choose from %s)")432 % (opt, value, choices))433 434# Not supplying a default is different from a default of None,435# so we need an explicit "not supplied" value.436NO_DEFAULT = ("NO", "DEFAULT")437 438 439class Option:440 """441 Instance attributes:442 _short_opts : [string]443 _long_opts : [string]444 445 action : string446 type : string447 dest : string448 default : any449 nargs : int450 const : any451 choices : [string]452 callback : function453 callback_args : (any*)454 callback_kwargs : { string : any }455 help : string456 metavar : string457 """458 459 # The list of instance attributes that may be set through460 # keyword args to the constructor.461 ATTRS = ['action',462 'type',463 'dest',464 'default',465 'nargs',466 'const',467 'choices',468 'callback',469 'callback_args',470 'callback_kwargs',471 'help',472 'metavar']473 474 # The set of actions allowed by option parsers. Explicitly listed475 # here so the constructor can validate its arguments.476 ACTIONS = ("store",477 "store_const",478 "store_true",479 "store_false",480 "append",481 "append_const",482 "count",483 "callback",484 "help",485 "version")486 487 # The set of actions that involve storing a value somewhere;488 # also listed just for constructor argument validation. (If489 # the action is one of these, there must be a destination.)490 STORE_ACTIONS = ("store",491 "store_const",492 "store_true",493 "store_false",494 "append",495 "append_const",496 "count")497 498 # The set of actions for which it makes sense to supply a value499 # type, ie. which may consume an argument from the command line.500 TYPED_ACTIONS = ("store",501 "append",502 "callback")503 504 # The set of actions which *require* a value type, ie. that505 # always consume an argument from the command line.506 ALWAYS_TYPED_ACTIONS = ("store",507 "append")508 509 # The set of actions which take a 'const' attribute.510 CONST_ACTIONS = ("store_const",511 "append_const")512 513 # The set of known types for option parsers. Again, listed here for514 # constructor argument validation.515 TYPES = ("string", "int", "long", "float", "complex", "choice")516 517 # Dictionary of argument checking functions, which convert and518 # validate option arguments according to the option type.519 #520 # Signature of checking functions is:521 # check(option : Option, opt : string, value : string) -> any522 # where523 # option is the Option instance calling the checker524 # opt is the actual option seen on the command-line525 # (eg. "-a", "--file")526 # value is the option argument seen on the command-line527 #528 # The return value should be in the appropriate Python type529 # for option.type -- eg. an integer if option.type == "int".530 #531 # If no checker is defined for a type, arguments will be532 # unchecked and remain strings.533 TYPE_CHECKER = { "int" : check_builtin,534 "long" : check_builtin,535 "float" : check_builtin,536 "complex": check_builtin,537 "choice" : check_choice,538 }539 540 541 # CHECK_METHODS is a list of unbound method objects; they are called542 # by the constructor, in order, after all attributes are543 # initialized. The list is created and filled in later, after all544 # the methods are actually defined. (I just put it here because I545 # like to define and document all class attributes in the same546 # place.) Subclasses that add another _check_*() method should547 # define their own CHECK_METHODS list that adds their check method548 # to those from this class.549 CHECK_METHODS = None550 551 552 # -- Constructor/initialization methods ----------------------------553 554 def __init__(self, *opts, **attrs):555 # Set _short_opts, _long_opts attrs from 'opts' tuple.556 # Have to be set now, in case no option strings are supplied.557 self._short_opts = []558 self._long_opts = []559 opts = self._check_opt_strings(opts)560 self._set_opt_strings(opts)561 562 # Set all other attrs (action, type, etc.) from 'attrs' dict563 self._set_attrs(attrs)564 565 # Check all the attributes we just set. There are lots of566 # complicated interdependencies, but luckily they can be farmed567 # out to the _check_*() methods listed in CHECK_METHODS -- which568 # could be handy for subclasses! The one thing these all share569 # is that they raise OptionError if they discover a problem.570 for checker in self.CHECK_METHODS:571 checker(self)572 573 def _check_opt_strings(self, opts):574 # Filter out None because early versions of Optik had exactly575 # one short option and one long option, either of which576 # could be None.577 opts = [opt for opt in opts if opt]578 if not opts:579 raise TypeError("at least one option string must be supplied")580 return opts581 582 def _set_opt_strings(self, opts):583 for opt in opts:584 if len(opt) < 2:585 raise OptionError(586 "invalid option string %r: "587 "must be at least two characters long" % opt, self)588 elif len(opt) == 2:589 if not (opt[0] == "-" and opt[1] != "-"):590 raise OptionError(591 "invalid short option string %r: "592 "must be of the form -x, (x any non-dash char)" % opt,593 self)594 self._short_opts.append(opt)595 else:596 if not (opt[0:2] == "--" and opt[2] != "-"):597 raise OptionError(598 "invalid long option string %r: "599 "must start with --, followed by non-dash" % opt,600 self)601 self._long_opts.append(opt)602 603 def _set_attrs(self, attrs):604 for attr in self.ATTRS:605 if attr in attrs:606 setattr(self, attr, attrs[attr])607 del attrs[attr]608 else:609 if attr == 'default':610 setattr(self, attr, NO_DEFAULT)611 else:612 setattr(self, attr, None)613 if attrs:614 attrs = sorted(attrs.keys())615 raise OptionError(616 "invalid keyword arguments: %s" % ", ".join(attrs),617 self)618 619 620 # -- Constructor validation methods --------------------------------621 622 def _check_action(self):623 if self.action is None:624 self.action = "store"625 elif self.action not in self.ACTIONS:626 raise OptionError("invalid action: %r" % self.action, self)627 628 def _check_type(self):629 if self.type is None:630 if self.action in self.ALWAYS_TYPED_ACTIONS:631 if self.choices is not None:632 # The "choices" attribute implies "choice" type.633 self.type = "choice"634 else:635 # No type given? "string" is the most sensible default.636 self.type = "string"637 else:638 # Allow type objects or builtin type conversion functions639 # (int, str, etc.) as an alternative to their names.640 if isinstance(self.type, type):641 self.type = self.type.__name__642 643 if self.type == "str":644 self.type = "string"645 646 if self.type not in self.TYPES:647 raise OptionError("invalid option type: %r" % self.type, self)648 if self.action not in self.TYPED_ACTIONS:649 raise OptionError(650 "must not supply a type for action %r" % self.action, self)651 652 def _check_choice(self):653 if self.type == "choice":654 if self.choices is None:655 raise OptionError(656 "must supply a list of choices for type 'choice'", self)657 elif not isinstance(self.choices, (tuple, list)):658 raise OptionError(659 "choices must be a list of strings ('%s' supplied)"660 % str(type(self.choices)).split("'")[1], self)661 elif self.choices is not None:662 raise OptionError(663 "must not supply choices for type %r" % self.type, self)664 665 def _check_dest(self):666 # No destination given, and we need one for this action. The667 # self.type check is for callbacks that take a value.668 takes_value = (self.action in self.STORE_ACTIONS or669 self.type is not None)670 if self.dest is None and takes_value:671 672 # Glean a destination from the first long option string,673 # or from the first short option string if no long options.674 if self._long_opts:675 # eg. "--foo-bar" -> "foo_bar"676 self.dest = self._long_opts[0][2:].replace('-', '_')677 else:678 self.dest = self._short_opts[0][1]679 680 def _check_const(self):681 if self.action not in self.CONST_ACTIONS and self.const is not None:682 raise OptionError(683 "'const' must not be supplied for action %r" % self.action,684 self)685 686 def _check_nargs(self):687 if self.action in self.TYPED_ACTIONS:688 if self.nargs is None:689 self.nargs = 1690 elif self.nargs is not None:691 raise OptionError(692 "'nargs' must not be supplied for action %r" % self.action,693 self)694 695 def _check_callback(self):696 if self.action == "callback":697 if not callable(self.callback):698 raise OptionError(699 "callback not callable: %r" % self.callback, self)700 if (self.callback_args is not None and701 not isinstance(self.callback_args, tuple)):702 raise OptionError(703 "callback_args, if supplied, must be a tuple: not %r"704 % self.callback_args, self)705 if (self.callback_kwargs is not None and706 not isinstance(self.callback_kwargs, dict)):707 raise OptionError(708 "callback_kwargs, if supplied, must be a dict: not %r"709 % self.callback_kwargs, self)710 else:711 if self.callback is not None:712 raise OptionError(713 "callback supplied (%r) for non-callback option"714 % self.callback, self)715 if self.callback_args is not None:716 raise OptionError(717 "callback_args supplied for non-callback option", self)718 if self.callback_kwargs is not None:719 raise OptionError(720 "callback_kwargs supplied for non-callback option", self)721 722 723 CHECK_METHODS = [_check_action,724 _check_type,725 _check_choice,726 _check_dest,727 _check_const,728 _check_nargs,729 _check_callback]730 731 732 # -- Miscellaneous methods -----------------------------------------733 734 def __str__(self):735 return "/".join(self._short_opts + self._long_opts)736 737 __repr__ = _repr738 739 def takes_value(self):740 return self.type is not None741 742 def get_opt_string(self):743 if self._long_opts:744 return self._long_opts[0]745 else:746 return self._short_opts[0]747 748 749 # -- Processing methods --------------------------------------------750 751 def check_value(self, opt, value):752 checker = self.TYPE_CHECKER.get(self.type)753 if checker is None:754 return value755 else:756 return checker(self, opt, value)757 758 def convert_value(self, opt, value):759 if value is not None:760 if self.nargs == 1:761 return self.check_value(opt, value)762 else:763 return tuple([self.check_value(opt, v) for v in value])764 765 def process(self, opt, value, values, parser):766 767 # First, convert the value(s) to the right type. Howl if any768 # value(s) are bogus.769 value = self.convert_value(opt, value)770 771 # And then take whatever action is expected of us.772 # This is a separate method to make life easier for773 # subclasses to add new actions.774 return self.take_action(775 self.action, self.dest, opt, value, values, parser)776 777 def take_action(self, action, dest, opt, value, values, parser):778 if action == "store":779 setattr(values, dest, value)780 elif action == "store_const":781 setattr(values, dest, self.const)782 elif action == "store_true":783 setattr(values, dest, True)784 elif action == "store_false":785 setattr(values, dest, False)786 elif action == "append":787 values.ensure_value(dest, []).append(value)788 elif action == "append_const":789 values.ensure_value(dest, []).append(self.const)790 elif action == "count":791 setattr(values, dest, values.ensure_value(dest, 0) + 1)792 elif action == "callback":793 args = self.callback_args or ()794 kwargs = self.callback_kwargs or {}795 self.callback(self, opt, value, parser, *args, **kwargs)796 elif action == "help":797 parser.print_help()798 parser.exit()799 elif action == "version":800 parser.print_version()801 parser.exit()802 else:803 raise ValueError("unknown action %r" % self.action)804 805 return 1806 807# class Option808 809 810SUPPRESS_HELP = "SUPPRESS"+"HELP"811SUPPRESS_USAGE = "SUPPRESS"+"USAGE"812 813class Values:814 815 def __init__(self, defaults=None):816 if defaults:817 for (attr, val) in defaults.items():818 setattr(self, attr, val)819 820 def __str__(self):821 return str(self.__dict__)822 823 __repr__ = _repr824 825 def __eq__(self, other):826 if isinstance(other, Values):827 return self.__dict__ == other.__dict__828 elif isinstance(other, dict):829 return self.__dict__ == other830 else:831 return NotImplemented832 833 def _update_careful(self, dict):834 """835 Update the option values from an arbitrary dictionary, but only836 use keys from dict that already have a corresponding attribute837 in self. Any keys in dict without a corresponding attribute838 are silently ignored.839 """840 for attr in dir(self):841 if attr in dict:842 dval = dict[attr]843 if dval is not None:844 setattr(self, attr, dval)845 846 def _update_loose(self, dict):847 """848 Update the option values from an arbitrary dictionary,849 using all keys from the dictionary regardless of whether850 they have a corresponding attribute in self or not.851 """852 self.__dict__.update(dict)853 854 def _update(self, dict, mode):855 if mode == "careful":856 self._update_careful(dict)857 elif mode == "loose":858 self._update_loose(dict)859 else:860 raise ValueError("invalid update mode: %r" % mode)861 862 def read_module(self, modname, mode="careful"):863 __import__(modname)864 mod = sys.modules[modname]865 self._update(vars(mod), mode)866 867 def read_file(self, filename, mode="careful"):868 vars = {}869 exec(open(filename).read(), vars)870 self._update(vars, mode)871 872 def ensure_value(self, attr, value):873 if not hasattr(self, attr) or getattr(self, attr) is None:874 setattr(self, attr, value)875 return getattr(self, attr)876 877 878class OptionContainer:879 880 """881 Abstract base class.882 883 Class attributes:884 standard_option_list : [Option]885 list of standard options that will be accepted by all instances886 of this parser class (intended to be overridden by subclasses).887 888 Instance attributes:889 option_list : [Option]890 the list of Option objects contained by this OptionContainer891 _short_opt : { string : Option }892 dictionary mapping short option strings, eg. "-f" or "-X",893 to the Option instances that implement them. If an Option894 has multiple short option strings, it will appear in this895 dictionary multiple times. [1]896 _long_opt : { string : Option }897 dictionary mapping long option strings, eg. "--file" or898 "--exclude", to the Option instances that implement them.899 Again, a given Option can occur multiple times in this900 dictionary. [1]901 defaults : { string : any }902 dictionary mapping option destination names to default903 values for each destination [1]904 905 [1] These mappings are common to (shared by) all components of the906 controlling OptionParser, where they are initially created.907 908 """909 910 def __init__(self, option_class, conflict_handler, description):911 # Initialize the option list and related data structures.912 # This method must be provided by subclasses, and it must913 # initialize at least the following instance attributes:914 # option_list, _short_opt, _long_opt, defaults.915 self._create_option_list()916 917 self.option_class = option_class918 self.set_conflict_handler(conflict_handler)919 self.set_description(description)920 921 def _create_option_mappings(self):922 # For use by OptionParser constructor -- create the main923 # option mappings used by this OptionParser and all924 # OptionGroups that it owns.925 self._short_opt = {} # single letter -> Option instance926 self._long_opt = {} # long option -> Option instance927 self.defaults = {} # maps option dest -> default value928 929 930 def _share_option_mappings(self, parser):931 # For use by OptionGroup constructor -- use shared option932 # mappings from the OptionParser that owns this OptionGroup.933 self._short_opt = parser._short_opt934 self._long_opt = parser._long_opt935 self.defaults = parser.defaults936 937 def set_conflict_handler(self, handler):938 if handler not in ("error", "resolve"):939 raise ValueError("invalid conflict_resolution value %r" % handler)940 self.conflict_handler = handler941 942 def set_description(self, description):943 self.description = description944 945 def get_description(self):946 return self.description947 948 949 def destroy(self):950 """see OptionParser.destroy()."""951 del self._short_opt952 del self._long_opt953 del self.defaults954 955 956 # -- Option-adding methods -----------------------------------------957 958 def _check_conflict(self, option):959 conflict_opts = []960 for opt in option._short_opts:961 if opt in self._short_opt:962 conflict_opts.append((opt, self._short_opt[opt]))963 for opt in option._long_opts:964 if opt in self._long_opt:965 conflict_opts.append((opt, self._long_opt[opt]))966 967 if conflict_opts:968 handler = self.conflict_handler969 if handler == "error":970 raise OptionConflictError(971 "conflicting option string(s): %s"972 % ", ".join([co[0] for co in conflict_opts]),973 option)974 elif handler == "resolve":975 for (opt, c_option) in conflict_opts:976 if opt.startswith("--"):977 c_option._long_opts.remove(opt)978 del self._long_opt[opt]979 else:980 c_option._short_opts.remove(opt)981 del self._short_opt[opt]982 if not (c_option._short_opts or c_option._long_opts):983 c_option.container.option_list.remove(c_option)984 985 def add_option(self, *args, **kwargs):986 """add_option(Option)987 add_option(opt_str, ..., kwarg=val, ...)988 """989 if isinstance(args[0], str):990 option = self.option_class(*args, **kwargs)991 elif len(args) == 1 and not kwargs:992 option = args[0]993 if not isinstance(option, Option):994 raise TypeError("not an Option instance: %r" % option)995 else:996 raise TypeError("invalid arguments")997 998 self._check_conflict(option)999 1000 self.option_list.append(option)1001 option.container = self1002 for opt in option._short_opts:1003 self._short_opt[opt] = option1004 for opt in option._long_opts:1005 self._long_opt[opt] = option1006 1007 if option.dest is not None: # option has a dest, we need a default1008 if option.default is not NO_DEFAULT:1009 self.defaults[option.dest] = option.default1010 elif option.dest not in self.defaults:1011 self.defaults[option.dest] = None1012 1013 return option1014 1015 def add_options(self, option_list):1016 for option in option_list:1017 self.add_option(option)1018 1019 # -- Option query/removal methods ----------------------------------1020 1021 def get_option(self, opt_str):1022 return (self._short_opt.get(opt_str) or1023 self._long_opt.get(opt_str))1024 1025 def has_option(self, opt_str):1026 return (opt_str in self._short_opt or1027 opt_str in self._long_opt)1028 1029 def remove_option(self, opt_str):1030 option = self._short_opt.get(opt_str)1031 if option is None:1032 option = self._long_opt.get(opt_str)1033 if option is None:1034 raise ValueError("no such option %r" % opt_str)1035 1036 for opt in option._short_opts:1037 del self._short_opt[opt]1038 for opt in option._long_opts:1039 del self._long_opt[opt]1040 option.container.option_list.remove(option)1041 1042 1043 # -- Help-formatting methods ---------------------------------------1044 1045 def format_option_help(self, formatter):1046 if not self.option_list:1047 return ""1048 result = []1049 for option in self.option_list:1050 if not option.help is SUPPRESS_HELP:1051 result.append(formatter.format_option(option))1052 return "".join(result)1053 1054 def format_description(self, formatter):1055 return formatter.format_description(self.get_description())1056 1057 def format_help(self, formatter):1058 result = []1059 if self.description:1060 result.append(self.format_description(formatter))1061 if self.option_list:1062 result.append(self.format_option_help(formatter))1063 return "\n".join(result)1064 1065 1066class OptionGroup (OptionContainer):1067 1068 def __init__(self, parser, title, description=None):1069 self.parser = parser1070 OptionContainer.__init__(1071 self, parser.option_class, parser.conflict_handler, description)1072 self.title = title1073 1074 def _create_option_list(self):1075 self.option_list = []1076 self._share_option_mappings(self.parser)1077 1078 def set_title(self, title):1079 self.title = title1080 1081 def destroy(self):1082 """see OptionParser.destroy()."""1083 OptionContainer.destroy(self)1084 del self.option_list1085 1086 # -- Help-formatting methods ---------------------------------------1087 1088 def format_help(self, formatter):1089 result = formatter.format_heading(self.title)1090 formatter.indent()1091 result += OptionContainer.format_help(self, formatter)1092 formatter.dedent()1093 return result1094 1095 1096class OptionParser (OptionContainer):1097 1098 """1099 Class attributes:1100 standard_option_list : [Option]1101 list of standard options that will be accepted by all instances1102 of this parser class (intended to be overridden by subclasses).1103 1104 Instance attributes:1105 usage : string1106 a usage string for your program. Before it is displayed1107 to the user, "%prog" will be expanded to the name of1108 your program (self.prog or os.path.basename(sys.argv[0])).1109 prog : string1110 the name of the current program (to override1111 os.path.basename(sys.argv[0])).1112 description : string1113 A paragraph of text giving a brief overview of your program.1114 optparse reformats this paragraph to fit the current terminal1115 width and prints it when the user requests help (after usage,1116 but before the list of options).1117 epilog : string1118 paragraph of help text to print after option help1119 1120 option_groups : [OptionGroup]1121 list of option groups in this parser (option groups are1122 irrelevant for parsing the command-line, but very useful1123 for generating help)1124 1125 allow_interspersed_args : bool = true1126 if true, positional arguments may be interspersed with options.1127 Assuming -a and -b each take a single argument, the command-line1128 -ablah foo bar -bboo baz1129 will be interpreted the same as1130 -ablah -bboo -- foo bar baz1131 If this flag were false, that command line would be interpreted as1132 -ablah -- foo bar -bboo baz1133 -- ie. we stop processing options as soon as we see the first1134 non-option argument. (This is the tradition followed by1135 Python's getopt module, Perl's Getopt::Std, and other argument-1136 parsing libraries, but it is generally annoying to users.)1137 1138 process_default_values : bool = true1139 if true, option default values are processed similarly to option1140 values from the command line: that is, they are passed to the1141 type-checking function for the option's type (as long as the1142 default value is a string). (This really only matters if you1143 have defined custom types; see SF bug #955889.) Set it to false1144 to restore the behaviour of Optik 1.4.1 and earlier.1145 1146 rargs : [string]1147 the argument list currently being parsed. Only set when1148 parse_args() is active, and continually trimmed down as1149 we consume arguments. Mainly there for the benefit of1150 callback options.1151 largs : [string]1152 the list of leftover arguments that we have skipped while1153 parsing options. If allow_interspersed_args is false, this1154 list is always empty.1155 values : Values1156 the set of option values currently being accumulated. Only1157 set when parse_args() is active. Also mainly for callbacks.1158 1159 Because of the 'rargs', 'largs', and 'values' attributes,1160 OptionParser is not thread-safe. If, for some perverse reason, you1161 need to parse command-line arguments simultaneously in different1162 threads, use different OptionParser instances.1163 1164 """1165 1166 standard_option_list = []1167 1168 def __init__(self,1169 usage=None,1170 option_list=None,1171 option_class=Option,1172 version=None,1173 conflict_handler="error",1174 description=None,1175 formatter=None,1176 add_help_option=True,1177 prog=None,1178 epilog=None):1179 OptionContainer.__init__(1180 self, option_class, conflict_handler, description)1181 self.set_usage(usage)1182 self.prog = prog1183 self.version = version1184 self.allow_interspersed_args = True1185 self.process_default_values = True1186 if formatter is None:1187 formatter = IndentedHelpFormatter()1188 self.formatter = formatter1189 self.formatter.set_parser(self)1190 self.epilog = epilog1191 1192 # Populate the option list; initial sources are the1193 # standard_option_list class attribute, the 'option_list'1194 # argument, and (if applicable) the _add_version_option() and1195 # _add_help_option() methods.1196 self._populate_option_list(option_list,1197 add_help=add_help_option)1198 1199 self._init_parsing_state()1200 