cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1682 lines · 58.8 KB · Python
RawDownload
                     "append",                     "callback")     # The set of actions which *require* a value type, ie. that    # always consume an argument from the command line.    ALWAYS_TYPED_ACTIONS = ("store",                            "append")     # The set of actions which take a 'const' attribute.    CONST_ACTIONS = ("store_const",                     "append_const")     # 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:            attrs = attrs.keys()            attrs.sort()            raise OptionError(                "invalid keyword arguments: %s" % ", ".join(attrs),                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:            if self.action in self.ALWAYS_TYPED_ACTIONS:                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:            # Allow type objects or builtin type conversion functions            # (int, str, etc.) as an alternative to their names.  (The            # complicated check of __builtin__ is only necessary for            # Python 2.1 and earlier, and is short-circuited by the            # first check on modern Pythons.)            import __builtin__            if ( type(self.type) is types.TypeType or                 (hasattr(self.type, "__name__") and                  getattr(__builtin__, self.type.__name__, None) is self.type) ):                self.type = self.type.__name__             if self.type == "str":                self.type = "string"             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):        # No destination given, and we need one for this action.  The        # self.type check is for callbacks that take a value.        takes_value = (self.action in self.STORE_ACTIONS or                       self.type is not None)        if self.dest is None and takes_value:             # 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 not in self.CONST_ACTIONS 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)     __repr__ = _repr     def takes_value(self):        return self.type is not None     def get_opt_string(self):        if self._long_opts:            return self._long_opts[0]        else:            return self._short_opts[0]      # -- 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 convert_value(self, opt, value):        if value is not None:            if self.nargs == 1:                return self.check_value(opt, value)            else:                return tuple([self.check_value(opt, v) for v in value])     def process(self, opt, value, values, parser):         # First, convert the value(s) to the right type.  Howl if any        # value(s) are bogus.        value = self.convert_value(opt, 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 == "append_const":            values.ensure_value(dest, []).append(self.const)        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()            parser.exit()        elif action == "version":            parser.print_version()            parser.exit()        else:            raise RuntimeError, "unknown action %r" % self.action         return 1 # class Option  SUPPRESS_HELP = "SUPPRESS"+"HELP"SUPPRESS_USAGE = "SUPPRESS"+"USAGE" # For compatibility with Python 2.2try:    True, Falseexcept NameError:    (True, False) = (1, 0) def isbasestring(x):    return isinstance(x, types.StringType) or isinstance(x, types.UnicodeType) class Values:     def __init__(self, defaults=None):        if defaults:            for (attr, val) in defaults.items():                setattr(self, attr, val)     def __str__(self):        return str(self.__dict__)     __repr__ = _repr     def __cmp__(self, other):        if isinstance(other, Values):            return cmp(self.__dict__, other.__dict__)        elif isinstance(other, types.DictType):            return cmp(self.__dict__, other)        else:            return -1     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 ("error", "resolve"):            raise ValueError, "invalid conflict_resolution value %r" % handler        self.conflict_handler = handler     def set_description(self, description):        self.description = description     def get_description(self):        return self.description      def destroy(self):        """see OptionParser.destroy()."""        del self._short_opt        del self._long_opt        del self.defaults      # -- 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 == "error":                raise OptionConflictError(                    "conflicting option string(s): %s"                    % ", ".join([co[0] for co in conflict_opts]),                    option)            elif handler == "resolve":                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) 

Lines 501–1000 of 1682. Previous lines