aboutsummaryrefslogtreecommitdiffstats
path: root/bin/utils/optparse.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/utils/optparse.py')
-rw-r--r--bin/utils/optparse.py1399
1 files changed, 0 insertions, 1399 deletions
diff --git a/bin/utils/optparse.py b/bin/utils/optparse.py
deleted file mode 100644
index f8e3394c9..000000000
--- a/bin/utils/optparse.py
+++ /dev/null
@@ -1,1399 +0,0 @@
-"""optparse - a powerful, extensible, and easy-to-use option parser.
-
-By Greg Ward <gward@python.net>
-
-Originally distributed as Optik; see http://optik.sourceforge.net/ .
-
-If you have problems with this module, please do not file bugs,
-patches, or feature requests with Python; instead, use Optik's
-SourceForge project page:
- http://sourceforge.net/projects/optik
-
-For support, use the optik-users@lists.sourceforge.net mailing list
-(http://lists.sourceforge.net/lists/listinfo/optik-users).
-"""
-
-# Python developers: please do not make changes to this file, since
-# it is automatically generated from the Optik source code.
-
-__version__ = "1.4.1+"
-
-__all__ = ['Option',
- 'SUPPRESS_HELP',
- 'SUPPRESS_USAGE',
- 'STD_HELP_OPTION',
- 'STD_VERSION_OPTION',
- 'Values',
- 'OptionContainer',
- 'OptionGroup',
- 'OptionParser',
- 'HelpFormatter',
- 'IndentedHelpFormatter',
- 'TitledHelpFormatter',
- 'OptParseError',
- 'OptionError',
- 'OptionConflictError',
- 'OptionValueError',
- 'BadOptionError']
-
-__copyright__ = """
-Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the author nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""
-
-import sys, os
-import types
-import textwrap
-
-class OptParseError (Exception):
- def __init__ (self, msg):
- self.msg = msg
-
- def __str__ (self):
- return self.msg
-
-
-class OptionError (OptParseError):
- """
- Raised if an Option instance is created with invalid or
- inconsistent arguments.
- """
-
- def __init__ (self, msg, option):
- self.msg = msg
- self.option_id = str(option)
-
- def __str__ (self):
- if self.option_id:
- return "option %s: %s" % (self.option_id, self.msg)
- else:
- return self.msg
-
-class OptionConflictError (OptionError):
- """
- Raised if conflicting options are added to an OptionParser.
- """
-
-class OptionValueError (OptParseError):
- """
- Raised if an invalid option value is encountered on the command
- line.
- """
-
-class BadOptionError (OptParseError):
- """
- Raised if an invalid or ambiguous option is seen on the command-line.
- """
-
-
-class HelpFormatter:
-
- """
- Abstract base class for formatting option help. OptionParser
- instances should use one of the HelpFormatter subclasses for
- formatting help; by default IndentedHelpFormatter is used.
-
- Instance attributes:
- indent_increment : int
- the number of columns to indent per nesting level
- max_help_position : int
- the maximum starting column for option help text
- help_position : int
- the calculated starting column for option help text;
- initially the same as the maximum
- width : int
- total number of columns for output
- level : int
- current indentation level
- current_indent : int
- current indentation level (in columns)
- help_width : int
- number of columns available for option help text (calculated)
- """
-
- def __init__ (self,
- indent_increment,
- max_help_position,
- width,
- short_first):
- self.indent_increment = indent_increment
- self.help_position = self.max_help_position = max_help_position
- self.width = width
- self.current_indent = 0
- self.level = 0
- self.help_width = width - max_help_position
- self.short_first = short_first
-
- def indent (self):
- self.current_indent += self.indent_increment
- self.level += 1
-
- def dedent (self):
- self.current_indent -= self.indent_increment
- assert self.current_indent >= 0, "Indent decreased below 0."
- self.level -= 1
-
- def format_usage (self, usage):
- raise NotImplementedError, "subclasses must implement"
-
- def format_heading (self, heading):
- raise NotImplementedError, "subclasses must implement"
-
- def format_description (self, description):
- desc_width = self.width - self.current_indent
- indent = " "*self.current_indent
- return textwrap.fill(description, desc_width,
- initial_indent=indent,
- subsequent_indent=indent)
-
- def format_option (self, option):
- # The help for each option consists of two parts:
- # * the opt strings and metavars
- # eg. ("-x", or "-fFILENAME, --file=FILENAME")
- # * the user-supplied help string
- # eg. ("turn on expert mode", "read data from FILENAME")
- #
- # If possible, we write both of these on the same line:
- # -x turn on expert mode
- #
- # But if the opt string list is too long, we put the help
- # string on a second line, indented to the same column it would
- # start in if it fit on the first line.
- # -fFILENAME, --file=FILENAME
- # read data from FILENAME
- result = []
- opts = option.option_strings
- opt_width = self.help_position - self.current_indent - 2
- if len(opts) > opt_width:
- opts = "%*s%s\n" % (self.current_indent, "", opts)
- indent_first = self.help_position
- else: # start help on same line as opts
- opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts)
- indent_first = 0
- result.append(opts)
- if option.help:
- help_lines = textwrap.wrap(option.help, self.help_width)
- result.append("%*s%s\n" % (indent_first, "", help_lines[0]))
- result.extend(["%*s%s\n" % (self.help_position, "", line)
- for line in help_lines[1:]])
- elif opts[-1] != "\n":
- result.append("\n")
- return "".join(result)
-
- def store_option_strings (self, parser):
- self.indent()
- max_len = 0
- for opt in parser.option_list:
- strings = self.format_option_strings(opt)
- opt.option_strings = strings
- max_len = max(max_len, len(strings) + self.current_indent)
- self.indent()
- for group in parser.option_groups:
- for opt in group.option_list:
- strings = self.format_option_strings(opt)
- opt.option_strings = strings
- max_len = max(max_len, len(strings) + self.current_indent)
- self.dedent()
- self.dedent()
- self.help_position = min(max_len + 2, self.max_help_position)
-
- def format_option_strings (self, option):
- """Return a comma-separated list of option strings & metavariables."""
- if option.takes_value():
- metavar = option.metavar or option.dest.upper()
- short_opts = [sopt + metavar for sopt in option._short_opts]
- long_opts = [lopt + "=" + metavar for lopt in option._long_opts]
- else:
- short_opts = option._short_opts
- long_opts = option._long_opts
-
- if self.short_first:
- opts = short_opts + long_opts
- else:
- opts = long_opts + short_opts
-
- return ", ".join(opts)
-
-class IndentedHelpFormatter (HelpFormatter):
- """Format help with indented section bodies.
- """
-
- def __init__ (self,
- indent_increment=2,
- max_help_position=24,
- width=80,
- short_first=1):
- HelpFormatter.__init__(
- self, indent_increment, max_help_position, width, short_first)
-
- def format_usage (self, usage):
- return "usage: %s\n" % usage
-
- def format_heading (self, heading):
- return "%*s%s:\n" % (self.current_indent, "", heading)
-
-
-class TitledHelpFormatter (HelpFormatter):
- """Format help with underlined section headers.
- """
-
- def __init__ (self,
- indent_increment=0,
- max_help_position=24,
- width=80,
- short_first=0):
- HelpFormatter.__init__ (
- self, indent_increment, max_help_position, width, short_first)
-
- def format_usage (self, usage):
- return "%s %s\n" % (self.format_heading("Usage"), usage)
-
- def format_heading (self, heading):
- return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading))
-
-
-_builtin_cvt = { "int" : (int, "integer"),
- "long" : (long, "long integer"),
- "float" : (float, "floating-point"),
- "complex" : (complex, "complex") }
-
-def check_builtin (option, opt, value):
- (cvt, what) = _builtin_cvt[option.type]
- try:
- return cvt(value)
- except ValueError:
- raise OptionValueError(
- #"%s: invalid %s argument %r" % (opt, what, value))
- "option %s: invalid %s value: %r" % (opt, what, value))
-
-def check_choice(option, opt, value):
- if value in option.choices:
- return value
- else:
- choices = ", ".join(map(repr, option.choices))
- raise OptionValueError(
- "option %s: invalid choice: %r (choose from %s)"
- % (opt, value, choices))
-
-# Not supplying a default is different from a default of None,
-# so we need an explicit "not supplied" value.
-NO_DEFAULT = "NO"+"DEFAULT"
-
-
-class Option:
- """
- Instance attributes:
- _short_opts : [string]
- _long_opts : [string]
-
- action : string
- type : string
- dest : string
- default : any
- nargs : int
- const : any
- choices : [string]
- callback : function
- callback_args : (any*)
- callback_kwargs : { string : any }
- help : string
- metavar : string
- """
-
- # The list of instance attributes that may be set through
- # keyword args to the constructor.
- ATTRS = ['action',
- 'type',
- 'dest',
- 'default',
- 'nargs',
- 'const',
- 'choices',
- 'callback',
- 'callback_args',
- 'callback_kwargs',
- 'help',
- 'metavar']
-
- # The set of actions allowed by option parsers. Explicitly listed
- # here so the constructor can validate its arguments.
- ACTIONS = ("store",
- "store_const",
- "store_true",
- "store_false",
- "append",
- "count",
- "callback",
- "help",
- "version")
-
- # The set of actions that involve storing a value somewhere;
- # also listed just for constructor argument validation. (If
- # the action is one of these, there must be a destination.)
- STORE_ACTIONS = ("store",
- "store_const",
- "store_true",
- "store_false",
- "append",
- "count")
-
- # The set of actions for which it makes sense to supply a value
- # type, ie. where we expect an argument to this option.
- TYPED_ACTIONS = ("store",
- "append",
- "callback")
-
- # The set of known types for option parsers. Again, listed here for
- # constructor argument validation.
- TYPES = ("string", "int", "long", "float", "complex", "choice")
-
- # Dictionary of argument checking functions, which convert and
- # validate option arguments according to the option type.
- #
- # Signature of checking functions is:
- # check(option : Option, opt : string, value : string) -> any
- # where
- # option is the Option instance calling the checker
- # opt is the actual option seen on the command-line
- # (eg. "-a", "--file")
- # value is the option argument seen on the command-line
- #
- # The return value should be in the appropriate Python type
- # for option.type -- eg. an integer if option.type == "int".
- #
- # If no checker is defined for a type, arguments will be
- # unchecked and remain strings.
- TYPE_CHECKER = { "int" : check_builtin,
- "long" : check_builtin,
- "float" : check_builtin,
- "complex" : check_builtin,
- "choice" : check_choice,
- }
-
-
- # CHECK_METHODS is a list of unbound method objects; they are called
- # by the constructor, in order, after all attributes are
- # initialized. The list is created and filled in later, after all
- # the methods are actually defined. (I just put it here because I
- # like to define and document all class attributes in the same
- # place.) Subclasses that add another _check_*() method should
- # define their own CHECK_METHODS list that adds their check method
- # to those from this class.
- CHECK_METHODS = None
-
-
- # -- Constructor/initialization methods ----------------------------
-
- def __init__ (self, *opts, **attrs):
- # Set _short_opts, _long_opts attrs from 'opts' tuple.
- # Have to be set now, in case no option strings are supplied.
- self._short_opts = []
- self._long_opts = []
- opts = self._check_opt_strings(opts)
- self._set_opt_strings(opts)
-
- # Set all other attrs (action, type, etc.) from 'attrs' dict
- self._set_attrs(attrs)
-
- # Check all the attributes we just set. There are lots of
- # complicated interdependencies, but luckily they can be farmed
- # out to the _check_*() methods listed in CHECK_METHODS -- which
- # could be handy for subclasses! The one thing these all share
- # is that they raise OptionError if they discover a problem.
- for checker in self.CHECK_METHODS:
- checker(self)
-
- def _check_opt_strings (self, opts):
- # Filter out None because early versions of Optik had exactly
- # one short option and one long option, either of which
- # could be None.
- opts = filter(None, opts)
- if not opts:
- raise TypeError("at least one option string must be supplied")
- return opts
-
- def _set_opt_strings (self, opts):
- for opt in opts:
- if len(opt) < 2:
- raise OptionError(
- "invalid option string %r: "
- "must be at least two characters long" % opt, self)
- elif len(opt) == 2:
- if not (opt[0] == "-" and opt[1] != "-"):
- raise OptionError(
- "invalid short option string %r: "
- "must be of the form -x, (x any non-dash char)" % opt,
- self)
- self._short_opts.append(opt)
- else:
- if not (opt[0:2] == "--" and opt[2] != "-"):
- raise OptionError(
- "invalid long option string %r: "
- "must start with --, followed by non-dash" % opt,
- self)
- self._long_opts.append(opt)
-
- def _set_attrs (self, attrs):
- for attr in self.ATTRS:
- if attrs.has_key(attr):
- setattr(self, attr, attrs[attr])
- del attrs[attr]
- else:
- if attr == 'default':
- setattr(self, attr, NO_DEFAULT)
- else:
- setattr(self, attr, None)
- if attrs:
- raise OptionError(
- "invalid keyword arguments: %s" % ", ".join(attrs.keys()),
- self)
-
-
- # -- Constructor validation methods --------------------------------
-
- def _check_action (self):
- if self.action is None:
- self.action = "store"
- elif self.action not in self.ACTIONS:
- raise OptionError("invalid action: %r" % self.action, self)
-
- def _check_type (self):
- if self.type is None:
- # XXX should factor out another class attr here: list of
- # actions that *require* a type
- if self.action in ("store", "append"):
- if self.choices is not None:
- # The "choices" attribute implies "choice" type.
- self.type = "choice"
- else:
- # No type given? "string" is the most sensible default.
- self.type = "string"
- else:
- if self.type not in self.TYPES:
- raise OptionError("invalid option type: %r" % self.type, self)
- if self.action not in self.TYPED_ACTIONS:
- raise OptionError(
- "must not supply a type for action %r" % self.action, self)
-
- def _check_choice(self):
- if self.type == "choice":
- if self.choices is None:
- raise OptionError(
- "must supply a list of choices for type 'choice'", self)
- elif type(self.choices) not in (types.TupleType, types.ListType):
- raise OptionError(
- "choices must be a list of strings ('%s' supplied)"
- % str(type(self.choices)).split("'")[1], self)
- elif self.choices is not None:
- raise OptionError(
- "must not supply choices for type %r" % self.type, self)
-
- def _check_dest (self):
- if self.action in self.STORE_ACTIONS and self.dest is None:
- # No destination given, and we need one for this action.
- # Glean a destination from the first long option string,
- # or from the first short option string if no long options.
- if self._long_opts:
- # eg. "--foo-bar" -> "foo_bar"
- self.dest = self._long_opts[0][2:].replace('-', '_')
- else:
- self.dest = self._short_opts[0][1]
-
- def _check_const (self):
- if self.action != "store_const" and self.const is not None:
- raise OptionError(
- "'const' must not be supplied for action %r" % self.action,
- self)
-
- def _check_nargs (self):
- if self.action in self.TYPED_ACTIONS:
- if self.nargs is None:
- self.nargs = 1
- elif self.nargs is not None:
- raise OptionError(
- "'nargs' must not be supplied for action %r" % self.action,
- self)
-
- def _check_callback (self):
- if self.action == "callback":
- if not callable(self.callback):
- raise OptionError(
- "callback not callable: %r" % self.callback, self)
- if (self.callback_args is not None and
- type(self.callback_args) is not types.TupleType):
- raise OptionError(
- "callback_args, if supplied, must be a tuple: not %r"
- % self.callback_args, self)
- if (self.callback_kwargs is not None and
- type(self.callback_kwargs) is not types.DictType):
- raise OptionError(
- "callback_kwargs, if supplied, must be a dict: not %r"
- % self.callback_kwargs, self)
- else:
- if self.callback is not None:
- raise OptionError(
- "callback supplied (%r) for non-callback option"
- % self.callback, self)
- if self.callback_args is not None:
- raise OptionError(
- "callback_args supplied for non-callback option", self)
- if self.callback_kwargs is not None:
- raise OptionError(
- "callback_kwargs supplied for non-callback option", self)
-
-
- CHECK_METHODS = [_check_action,
- _check_type,
- _check_choice,
- _check_dest,
- _check_const,
- _check_nargs,
- _check_callback]
-
-
- # -- Miscellaneous methods -----------------------------------------
-
- def __str__ (self):
- return "/".join(self._short_opts + self._long_opts)
-
- def takes_value (self):
- return self.type is not None
-
-
- # -- Processing methods --------------------------------------------
-
- def check_value (self, opt, value):
- checker = self.TYPE_CHECKER.get(self.type)
- if checker is None:
- return value
- else:
- return checker(self, opt, value)
-
- def process (self, opt, value, values, parser):
-
- # First, convert the value(s) to the right type. Howl if any
- # value(s) are bogus.
- if value is not None:
- if self.nargs == 1:
- value = self.check_value(opt, value)
- else:
- value = tuple([self.check_value(opt, v) for v in value])
-
- # And then take whatever action is expected of us.
- # This is a separate method to make life easier for
- # subclasses to add new actions.
- return self.take_action(
- self.action, self.dest, opt, value, values, parser)
-
- def take_action (self, action, dest, opt, value, values, parser):
- if action == "store":
- setattr(values, dest, value)
- elif action == "store_const":
- setattr(values, dest, self.const)
- elif action == "store_true":
- setattr(values, dest, True)
- elif action == "store_false":
- setattr(values, dest, False)
- elif action == "append":
- values.ensure_value(dest, []).append(value)
- elif action == "count":
- setattr(values, dest, values.ensure_value(dest, 0) + 1)
- elif action == "callback":
- args = self.callback_args or ()
- kwargs = self.callback_kwargs or {}
- self.callback(self, opt, value, parser, *args, **kwargs)
- elif action == "help":
- parser.print_help()
- sys.exit(0)
- elif action == "version":
- parser.print_version()
- sys.exit(0)
- else:
- raise RuntimeError, "unknown action %r" % self.action
-
- return 1
-
-# class Option
-
-
-def get_prog_name ():
- return os.path.basename(sys.argv[0])
-
-
-SUPPRESS_HELP = "SUPPRESS"+"HELP"
-SUPPRESS_USAGE = "SUPPRESS"+"USAGE"
-
-STD_HELP_OPTION = Option("-h", "--help",
- action="help",
- help="show this help message and exit")
-STD_VERSION_OPTION = Option("--version",
- action="version",
- help="show program's version number and exit")
-
-
-class Values:
-
- def __init__ (self, defaults=None):
- if defaults:
- for (attr, val) in defaults.items():
- setattr(self, attr, val)
-
- def __repr__ (self):
- return ("<%s at 0x%x: %r>"
- % (self.__class__.__name__, id(self), self.__dict__))
-
- def _update_careful (self, dict):
- """
- Update the option values from an arbitrary dictionary, but only
- use keys from dict that already have a corresponding attribute
- in self. Any keys in dict without a corresponding attribute
- are silently ignored.
- """
- for attr in dir(self):
- if dict.has_key(attr):
- dval = dict[attr]
- if dval is not None:
- setattr(self, attr, dval)
-
- def _update_loose (self, dict):
- """
- Update the option values from an arbitrary dictionary,
- using all keys from the dictionary regardless of whether
- they have a corresponding attribute in self or not.
- """
- self.__dict__.update(dict)
-
- def _update (self, dict, mode):
- if mode == "careful":
- self._update_careful(dict)
- elif mode == "loose":
- self._update_loose(dict)
- else:
- raise ValueError, "invalid update mode: %r" % mode
-
- def read_module (self, modname, mode="careful"):
- __import__(modname)
- mod = sys.modules[modname]
- self._update(vars(mod), mode)
-
- def read_file (self, filename, mode="careful"):
- vars = {}
- execfile(filename, vars)
- self._update(vars, mode)
-
- def ensure_value (self, attr, value):
- if not hasattr(self, attr) or getattr(self, attr) is None:
- setattr(self, attr, value)
- return getattr(self, attr)
-
-
-class OptionContainer:
-
- """
- Abstract base class.
-
- Class attributes:
- standard_option_list : [Option]
- list of standard options that will be accepted by all instances
- of this parser class (intended to be overridden by subclasses).
-
- Instance attributes:
- option_list : [Option]
- the list of Option objects contained by this OptionContainer
- _short_opt : { string : Option }
- dictionary mapping short option strings, eg. "-f" or "-X",
- to the Option instances that implement them. If an Option
- has multiple short option strings, it will appears in this
- dictionary multiple times. [1]
- _long_opt : { string : Option }
- dictionary mapping long option strings, eg. "--file" or
- "--exclude", to the Option instances that implement them.
- Again, a given Option can occur multiple times in this
- dictionary. [1]
- defaults : { string : any }
- dictionary mapping option destination names to default
- values for each destination [1]
-
- [1] These mappings are common to (shared by) all components of the
- controlling OptionParser, where they are initially created.
-
- """
-
- def __init__ (self, option_class, conflict_handler, description):
- # Initialize the option list and related data structures.
- # This method must be provided by subclasses, and it must
- # initialize at least the following instance attributes:
- # option_list, _short_opt, _long_opt, defaults.
- self._create_option_list()
-
- self.option_class = option_class
- self.set_conflict_handler(conflict_handler)
- self.set_description(description)
-
- def _create_option_mappings (self):
- # For use by OptionParser constructor -- create the master
- # option mappings used by this OptionParser and all
- # OptionGroups that it owns.
- self._short_opt = {} # single letter -> Option instance
- self._long_opt = {} # long option -> Option instance
- self.defaults = {} # maps option dest -> default value
-
-
- def _share_option_mappings (self, parser):
- # For use by OptionGroup constructor -- use shared option
- # mappings from the OptionParser that owns this OptionGroup.
- self._short_opt = parser._short_opt
- self._long_opt = parser._long_opt
- self.defaults = parser.defaults
-
- def set_conflict_handler (self, handler):
- if handler not in ("ignore", "error", "resolve"):
- raise ValueError, "invalid conflict_resolution value %r" % handler
- self.conflict_handler = handler
-
- def set_description (self, description):
- self.description = description
-
-
- # -- Option-adding methods -----------------------------------------
-
- def _check_conflict (self, option):
- conflict_opts = []
- for opt in option._short_opts:
- if self._short_opt.has_key(opt):
- conflict_opts.append((opt, self._short_opt[opt]))
- for opt in option._long_opts:
- if self._long_opt.has_key(opt):
- conflict_opts.append((opt, self._long_opt[opt]))
-
- if conflict_opts:
- handler = self.conflict_handler
- if handler == "ignore": # behaviour for Optik 1.0, 1.1
- pass
- elif handler == "error": # new in 1.2
- raise OptionConflictError(
- "conflicting option string(s): %s"
- % ", ".join([co[0] for co in conflict_opts]),
- option)
- elif handler == "resolve": # new in 1.2
- for (opt, c_option) in conflict_opts:
- if opt.startswith("--"):
- c_option._long_opts.remove(opt)
- del self._long_opt[opt]
- else:
- c_option._short_opts.remove(opt)
- del self._short_opt[opt]
- if not (c_option._short_opts or c_option._long_opts):
- c_option.container.option_list.remove(c_option)
-
- def add_option (self, *args, **kwargs):
- """add_option(Option)
- add_option(opt_str, ..., kwarg=val, ...)
- """
- if type(args[0]) is types.StringType:
- option = self.option_class(*args, **kwargs)
- elif len(args) == 1 and not kwargs:
- option = args[0]
- if not isinstance(option, Option):
- raise TypeError, "not an Option instance: %r" % option
- else:
- raise TypeError, "invalid arguments"
-
- self._check_conflict(option)
-
- self.option_list.append(option)
- option.container = self
- for opt in option._short_opts:
- self._short_opt[opt] = option
- for opt in option._long_opts:
- self._long_opt[opt] = option
-
- if option.dest is not None: # option has a dest, we need a default
- if option.default is not NO_DEFAULT:
- self.defaults[option.dest] = option.default
- elif not self.defaults.has_key(option.dest):
- self.defaults[option.dest] = None
-
- return option
-
- def add_options (self, option_list):
- for option in option_list:
- self.add_option(option)
-
- # -- Option query/removal methods ----------------------------------
-
- def get_option (self, opt_str):
- return (self._short_opt.get(opt_str) or
- self._long_opt.get(opt_str))
-
- def has_option (self, opt_str):
- return (self._short_opt.has_key(opt_str) or
- self._long_opt.has_key(opt_str))
-
- def remove_option (self, opt_str):
- option = self._short_opt.get(opt_str)
- if option is None:
- option = self._long_opt.get(opt_str)
- if option is None:
- raise ValueError("no such option %r" % opt_str)
-
- for opt in option._short_opts:
- del self._short_opt[opt]
- for opt in option._long_opts:
- del self._long_opt[opt]
- option.container.option_list.remove(option)
-
-
- # -- Help-formatting methods ---------------------------------------
-
- def format_option_help (self, formatter):
- if not self.option_list:
- return ""
- result = []
- for option in self.option_list:
- if not option.help is SUPPRESS_HELP:
- result.append(formatter.format_option(option))
- return "".join(result)
-
- def format_description (self, formatter):
- if self.description:
- return formatter.format_description(self.description)
- else:
- return ""
-
- def format_help (self, formatter):
- if self.description:
- desc = self.format_description(formatter) + "\n"
- else:
- desc = ""
- return desc + self.format_option_help(formatter)
-
-
-class OptionGroup (OptionContainer):
-
- def __init__ (self, parser, title, description=None):
- self.parser = parser
- OptionContainer.__init__(
- self, parser.option_class, parser.conflict_handler, description)
- self.title = title
-
- def _create_option_list (self):
- self.option_list = []
- self._share_option_mappings(self.parser)
-
- def set_title (self, title):
- self.title = title
-
- # -- Help-formatting methods ---------------------------------------
-
- def format_help (self, formatter):
- result = formatter.format_heading(self.title)
- formatter.indent()
- result += OptionContainer.format_help(self, formatter)
- formatter.dedent()
- return result
-
-
-class OptionParser (OptionContainer):
-
- """
- Class attributes:
- standard_option_list : [Option]
- list of standard options that will be accepted by all instances
- of this parser class (intended to be overridden by subclasses).
-
- Instance attributes:
- usage : string
- a usage string for your program. Before it is displayed
- to the user, "%prog" will be expanded to the name of
- your program (self.prog or os.path.basename(sys.argv[0])).
- prog : string
- the name of the current program (to override
- os.path.basename(sys.argv[0])).
-
- allow_interspersed_args : boolean = true
- if true, positional arguments may be interspersed with options.
- Assuming -a and -b each take a single argument, the command-line
- -ablah foo bar -bboo baz
- will be interpreted the same as
- -ablah -bboo -- foo bar baz
- If this flag were false, that command line would be interpreted as
- -ablah -- foo bar -bboo baz
- -- ie. we stop processing options as soon as we see the first
- non-option argument. (This is the tradition followed by
- Python's getopt module, Perl's Getopt::Std, and other argument-
- parsing libraries, but it is generally annoying to users.)
-
- rargs : [string]
- the argument list currently being parsed. Only set when
- parse_args() is active, and continually trimmed down as
- we consume arguments. Mainly there for the benefit of
- callback options.
- largs : [string]
- the list of leftover arguments that we have skipped while
- parsing options. If allow_interspersed_args is false, this
- list is always empty.
- values : Values
- the set of option values currently being accumulated. Only
- set when parse_args() is active. Also mainly for callbacks.
-
- Because of the 'rargs', 'largs', and 'values' attributes,
- OptionParser is not thread-safe. If, for some perverse reason, you
- need to parse command-line arguments simultaneously in different
- threads, use different OptionParser instances.
-
- """
-
- standard_option_list = []
-
- def __init__ (self,
- usage=None,
- option_list=None,
- option_class=Option,
- version=None,
- conflict_handler="error",
- description=None,
- formatter=None,
- add_help_option=1,
- prog=None):
- OptionContainer.__init__(
- self, option_class, conflict_handler, description)
- self.set_usage(usage)
- self.prog = prog
- self.version = version
- self.allow_interspersed_args = 1
- if formatter is None:
- formatter = IndentedHelpFormatter()
- self.formatter = formatter
-
- # Populate the option list; initial sources are the
- # standard_option_list class attribute, the 'option_list'
- # argument, and the STD_VERSION_OPTION (if 'version' supplied)
- # and STD_HELP_OPTION globals.
- self._populate_option_list(option_list,
- add_help=add_help_option)
-
- self._init_parsing_state()
-
- # -- Private methods -----------------------------------------------
- # (used by our or OptionContainer's constructor)
-
- def _create_option_list (self):
- self.option_list = []
- self.option_groups = []
- self._create_option_mappings()
-
- def _populate_option_list (self, option_list, add_help=1):
- if self.standard_option_list:
- self.add_options(self.standard_option_list)
- if option_list:
- self.add_options(option_list)
- if self.version:
- self.add_option(STD_VERSION_OPTION)
- if add_help:
- self.add_option(STD_HELP_OPTION)
-
- def _init_parsing_state (self):
- # These are set in parse_args() for the convenience of callbacks.
- self.rargs = None
- self.largs = None
- self.values = None
-
-
- # -- Simple modifier methods ---------------------------------------
-
- def set_usage (self, usage):
- if usage is None:
- self.usage = "%prog [options]"
- elif usage is SUPPRESS_USAGE:
- self.usage = None
- elif usage.startswith("usage: "):
- # for backwards compatibility with Optik 1.3 and earlier
- self.usage = usage[7:]
- else:
- self.usage = usage
-
- def enable_interspersed_args (self):
- self.allow_interspersed_args = 1
-
- def disable_interspersed_args (self):
- self.allow_interspersed_args = 0
-
- def set_default (self, dest, value):
- self.defaults[dest] = value
-
- def set_defaults (self, **kwargs):
- self.defaults.update(kwargs)
-
- def get_default_values (self):
- return Values(self.defaults)
-
-
- # -- OptionGroup methods -------------------------------------------
-
- def add_option_group (self, *args, **kwargs):
- # XXX lots of overlap with OptionContainer.add_option()
- if type(args[0]) is types.StringType:
- group = OptionGroup(self, *args, **kwargs)
- elif len(args) == 1 and not kwargs:
- group = args[0]
- if not isinstance(group, OptionGroup):
- raise TypeError, "not an OptionGroup instance: %r" % group
- if group.parser is not self:
- raise ValueError, "invalid OptionGroup (wrong parser)"
- else:
- raise TypeError, "invalid arguments"
-
- self.option_groups.append(group)
- return group
-
- def get_option_group (self, opt_str):
- option = (self._short_opt.get(opt_str) or
- self._long_opt.get(opt_str))
- if option and option.container is not self:
- return option.container
- return None
-
-
- # -- Option-parsing methods ----------------------------------------
-
- def _get_args (self, args):
- if args is None:
- return sys.argv[1:]
- else:
- return args[:] # don't modify caller's list
-
- def parse_args (self, args=None, values=None):
- """
- parse_args(args : [string] = sys.argv[1:],
- values : Values = None)
- -> (values : Values, args : [string])
-
- Parse the command-line options found in 'args' (default:
- sys.argv[1:]). Any errors result in a call to 'error()', which
- by default prints the usage message to stderr and calls
- sys.exit() with an error message. On success returns a pair
- (values, args) where 'values' is an Values instance (with all
- your option values) and 'args' is the list of arguments left
- over after parsing options.
- """
- rargs = self._get_args(args)
- if values is None:
- values = self.get_default_values()
-
- # Store the halves of the argument list as attributes for the
- # convenience of callbacks:
- # rargs
- # the rest of the command-line (the "r" stands for
- # "remaining" or "right-hand")
- # largs
- # the leftover arguments -- ie. what's left after removing
- # options and their arguments (the "l" stands for "leftover"
- # or "left-hand")
- self.rargs = rargs
- self.largs = largs = []
- self.values = values
-
- try:
- stop = self._process_args(largs, rargs, values)
- except (BadOptionError, OptionValueError), err:
- self.error(err.msg)
-
- args = largs + rargs
- return self.check_values(values, args)
-
- def check_values (self, values, args):
- """
- check_values(values : Values, args : [string])
- -> (values : Values, args : [string])
-
- Check that the supplied option values and leftover arguments are
- valid. Returns the option values and leftover arguments
- (possibly adjusted, possibly completely new -- whatever you
- like). Default implementation just returns the passed-in
- values; subclasses may override as desired.
- """
- return (values, args)
-
- def _process_args (self, largs, rargs, values):
- """_process_args(largs : [string],
- rargs : [string],
- values : Values)
-
- Process command-line arguments and populate 'values', consuming
- options and arguments from 'rargs'. If 'allow_interspersed_args' is
- false, stop at the first non-option argument. If true, accumulate any
- interspersed non-option arguments in 'largs'.
- """
- while rargs:
- arg = rargs[0]
- # We handle bare "--" explicitly, and bare "-" is handled by the
- # standard arg handler since the short arg case ensures that the
- # len of the opt string is greater than 1.
- if arg == "--":
- del rargs[0]
- return
- elif arg[0:2] == "--":
- # process a single long option (possibly with value(s))
- self._process_long_opt(rargs, values)
- elif arg[:1] == "-" and len(arg) > 1:
- # process a cluster of short options (possibly with
- # value(s) for the last one only)
- self._process_short_opts(rargs, values)
- elif self.allow_interspersed_args:
- largs.append(arg)
- del rargs[0]
- else:
- return # stop now, leave this arg in rargs
-
- # Say this is the original argument list:
- # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)]
- # ^
- # (we are about to process arg(i)).
- #
- # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of
- # [arg0, ..., arg(i-1)] (any options and their arguments will have
- # been removed from largs).
- #
- # The while loop will usually consume 1 or more arguments per pass.
- # If it consumes 1 (eg. arg is an option that takes no arguments),
- # then after _process_arg() is done the situation is:
- #
- # largs = subset of [arg0, ..., arg(i)]
- # rargs = [arg(i+1), ..., arg(N-1)]
- #
- # If allow_interspersed_args is false, largs will always be
- # *empty* -- still a subset of [arg0, ..., arg(i-1)], but
- # not a very interesting subset!
-
- def _match_long_opt (self, opt):
- """_match_long_opt(opt : string) -> string
-
- Determine which long option string 'opt' matches, ie. which one
- it is an unambiguous abbrevation for. Raises BadOptionError if
- 'opt' doesn't unambiguously match any long option string.
- """
- return _match_abbrev(opt, self._long_opt)
-
- def _process_long_opt (self, rargs, values):
- arg = rargs.pop(0)
-
- # Value explicitly attached to arg? Pretend it's the next
- # argument.
- if "=" in arg:
- (opt, next_arg) = arg.split("=", 1)
- rargs.insert(0, next_arg)
- had_explicit_value = 1
- else:
- opt = arg
- had_explicit_value = 0
-
- opt = self._match_long_opt(opt)
- option = self._long_opt[opt]
- if option.takes_value():
- nargs = option.nargs
- if len(rargs) < nargs:
- if nargs == 1:
- self.error("%s option requires a value" % opt)
- else:
- self.error("%s option requires %d values"
- % (opt, nargs))
- elif nargs == 1:
- value = rargs.pop(0)
- else:
- value = tuple(rargs[0:nargs])
- del rargs[0:nargs]
-
- elif had_explicit_value:
- self.error("%s option does not take a value" % opt)
-
- else:
- value = None
-
- option.process(opt, value, values, self)
-
- def _process_short_opts (self, rargs, values):
- arg = rargs.pop(0)
- stop = 0
- i = 1
- for ch in arg[1:]:
- opt = "-" + ch
- option = self._short_opt.get(opt)
- i += 1 # we have consumed a character
-
- if not option:
- self.error("no such option: %s" % opt)
- if option.takes_value():
- # Any characters left in arg? Pretend they're the
- # next arg, and stop consuming characters of arg.
- if i < len(arg):
- rargs.insert(0, arg[i:])
- stop = 1
-
- nargs = option.nargs
- if len(rargs) < nargs:
- if nargs == 1:
- self.error("%s option requires a value" % opt)
- else:
- self.error("%s option requires %s values"
- % (opt, nargs))
- elif nargs == 1:
- value = rargs.pop(0)
- else:
- value = tuple(rargs[0:nargs])
- del rargs[0:nargs]
-
- else: # option doesn't take a value
- value = None
-
- option.process(opt, value, values, self)
-
- if stop:
- break
-
-
- # -- Feedback methods ----------------------------------------------
-
- def error (self, msg):
- """error(msg : string)
-
- Print a usage message incorporating 'msg' to stderr and exit.
- If you override this in a subclass, it should not return -- it
- should either exit or raise an exception.
- """
- self.print_usage(sys.stderr)
- sys.exit("%s: error: %s" % (get_prog_name(), msg))
-
- def get_usage (self):
- if self.usage:
- return self.formatter.format_usage(
- self.usage.replace("%prog", get_prog_name()))
- else:
- return ""
-
- def print_usage (self, file=None):
- """print_usage(file : file = stdout)
-
- Print the usage message for the current program (self.usage) to
- 'file' (default stdout). Any occurence of the string "%prog" in
- self.usage is replaced with the name of the current program
- (basename of sys.argv[0]). Does nothing if self.usage is empty
- or not defined.
- """
- if self.usage:
- print >>file, self.get_usage()
-
- def get_version (self):
- if self.version:
- return self.version.replace("%prog", get_prog_name())
- else:
- return ""
-
- def print_version (self, file=None):
- """print_version(file : file = stdout)
-
- Print the version message for this program (self.version) to
- 'file' (default stdout). As with print_usage(), any occurence
- of "%prog" in self.version is replaced by the current program's
- name. Does nothing if self.version is empty or undefined.
- """
- if self.version:
- print >>file, self.get_version()
-
- def format_option_help (self, formatter=None):
- if formatter is None:
- formatter = self.formatter
- formatter.store_option_strings(self)
- result = []
- result.append(formatter.format_heading("options"))
- formatter.indent()
- if self.option_list:
- result.append(OptionContainer.format_option_help(self, formatter))
- result.append("\n")
- for group in self.option_groups:
- result.append(group.format_help(formatter))
- result.append("\n")
- formatter.dedent()
- # Drop the last "\n", or the header if no options or option groups:
- return "".join(result[:-1])
-
- def format_help (self, formatter=None):
- if formatter is None:
- formatter = self.formatter
- result = []
- if self.usage:
- result.append(self.get_usage() + "\n")
- if self.description:
- result.append(self.format_description(formatter) + "\n")
- result.append(self.format_option_help(formatter))
- return "".join(result)
-
- def print_help (self, file=None):
- """print_help(file : file = stdout)
-
- Print an extended help message, listing all options and any
- help text provided with them, to 'file' (default stdout).
- """
- if file is None:
- file = sys.stdout
- file.write(self.format_help())
-
-# class OptionParser
-
-
-def _match_abbrev (s, wordmap):
- """_match_abbrev(s : string, wordmap : {string : Option}) -> string
-
- Return the string key in 'wordmap' for which 's' is an unambiguous
- abbreviation. If 's' is found to be ambiguous or doesn't match any of
- 'words', raise BadOptionError.
- """
- # Is there an exact match?
- if wordmap.has_key(s):
- return s
- else:
- # Isolate all words with s as a prefix.
- possibilities = [word for word in wordmap.keys()
- if word.startswith(s)]
- # No exact match, so there had better be just one possibility.
- if len(possibilities) == 1:
- return possibilities[0]
- elif not possibilities:
- raise BadOptionError("no such option: %s" % s)
- else:
- # More than one possible completion: ambiguous prefix.
- raise BadOptionError("ambiguous option: %s (%s?)"
- % (s, ", ".join(possibilities)))
-
-
-# Some day, there might be many Option classes. As of Optik 1.3, the
-# preferred way to instantiate Options is indirectly, via make_option(),
-# which will become a factory function when there are many Option
-# classes.
-make_option = Option