0001"""
0002**Deprecated** (13 Aug 2006)
0003"""
0004
0005# This was deprecated 13 Aug 2006
0006import warnings
0007warnings.warn('initools.configwrapper is not supported or recommended for use.',
0008              DeprecationWarning)
0009
0010
0011import os
0012import iniparser
0013
0014class _ConfigParser(iniparser.INIParser):
0015
0016    """
0017    An internal subclass of the abstract ini parser, which saves
0018    everything into one dictionary.
0019    """
0020
0021    def __init__(self, allow_empty_sections=True):
0022        self.allow_empty_sections = allow_empty_sections
0023        iniparser.INIParser.__init__(self)
0024
0025    def reset(self):
0026        self.data = {}
0027        self.key_order = {}
0028        self.section_order = []
0029        iniparser.INIParser.reset(self)
0030
0031    def assignment(self, name, content):
0032        section = self.data.setdefault(self.section, {})
0033        name = clean_name(name)
0034        section.setdefault(name, []).append(content)
0035        self.key_order.setdefault(self.section, []).append(name)
0036
0037    def new_section(self, section):
0038        section = section.strip().lower()
0039        if not section or section == 'general':
0040            section = None
0041        self.section = section
0042        if not section in self.section_order:
0043            self.section_order.append(section)
0044
0045class NoDefault:
0046    pass
0047
0048def clean_name(name):
0049    name = name.strip().lower()
0050    for char in ' \t_-':
0051        name = name.replace(char, '')
0052    return name
0053
0054class Config(object):
0055
0056    """
0057    A configuration object.  Acts a little like a dictionary, but not
0058    really.
0059
0060    Configuration can be nested with ``[section]`` markers, or can be
0061    flat (everything globally available).  If in sections then
0062    ``section.key`` is used, otherwise just ``key``.
0063    """
0064
0065    # If False, then no global sections are allowed
0066    allow_empty_sections = True
0067
0068    def __init__(self, filename, file=None,
0069                 allow_empty_sections=NoDefault):
0070        if allow_empty_sections is not NoDefault:
0071            self.allow_empty_sections = allow_empty_sections
0072        self.filename = filename
0073        p = _ConfigParser(allow_empty_sections=self.allow_empty_sections)
0074        if file is None:
0075            p.load(filename)
0076        else:
0077            p.loadfile(file)
0078        self.raw_data = p.data
0079        self._section_order = p.section_order
0080        self._key_order = p.key_order
0081        self.name = os.path.splitext(os.path.basename(filename))[0]
0082
0083    def keys(self, section=NoDefault):
0084        if section is NoDefault:
0085            all = []
0086            for section_name in self._section_order:
0087                for key_name in self._key_order[section_name]:
0088                    if section_name:
0089                        key_name = '%s|%s' % (section_name, key_name)
0090                    all.append(key_name)
0091            return all
0092        else:
0093            try:
0094                return self._key_order[section]
0095            except KeyError:
0096                raise KeyError(
0097                    "Section [%s] not found (from sections %r)"
0098                    %(section, self._key_order.keys()))
0099
0100    def sections(self):
0101        return self._section_order
0102
0103    def getraw(self, key, section=None):
0104        """
0105        Mostly for internal use, returns a list of all matching keys.
0106        """
0107        if '|' in key:
0108            assert section is None, (
0109                "Cannot have | in a key (%r) and an explicit section (%r)"
0110                % (key, section))
0111            section, key = key.split('|', 1)
0112        section = self.clean_section(section)
0113        try:
0114            return self.raw_data[section][key]
0115        except KeyError:
0116            return ()
0117
0118    def clean_section(self, section_name):
0119        if not section_name or section_name == 'general':
0120            return None
0121        return section_name.lower()
0122
0123    def get(self, key, default=None, section=None):
0124        """
0125        Get a single value, returning `default` if none found.
0126        """
0127        value = self.getraw(key, section=section)
0128        if not value:
0129            return default
0130        else:
0131            return value[0]
0132
0133    def getlist(self, key, default=(), section=None):
0134        """
0135        Get a list of all matching keys.  Example::
0136
0137          foo = bar
0138          foo = baz
0139
0140        Then::
0141
0142          >>> config.getlist('foo')
0143          ['bar', 'baz']
0144        """
0145        value = self.getraw(key, section=section)
0146        if not value:
0147            return default
0148        else:
0149            return value
0150
0151    true_values = ['t', 'true', '1', 'y', 'yes', 'on']
0152    false_values = ['f', 'false', '0', 'n', 'no', 'off']
0153
0154    def getbool(self, key, default=False, section=None):
0155        """
0156        Get a single boolean value.  Boolean values are things
0157        like ``true``, ``false``, etc.
0158        """
0159        value = self.getraw(key, section=section)
0160        if not value:
0161            return default
0162        value = value[0]
0163        if isinstance(value, (str, unicode)):
0164            value = value.lower()
0165            if value in self.true_values:
0166                return True
0167            elif value in self.false_values:
0168                return False
0169            else:
0170                raise ValueError(
0171                    "Yes/No value expected for %s (got %r)"
0172                    % (key, value))
0173        else:
0174            return value
0175
0176    def getint(self, key, default=None, section=None):
0177        """
0178        Get an integer value.
0179        """
0180        v = self.get(key, default=default, section=section)
0181        if v is None:
0182            return v
0183        else:
0184            return int(v)
0185
0186    def getinlinelist(self, key, default=(), section=None):
0187        """
0188        Get a list, where the list is defined like::
0189
0190            foo = bar, baz
0191
0192        Gives::
0193
0194            >>> config.getinlinelist('foo')
0195            ['bar', 'baz']
0196        """
0197        result = []
0198        for item in self.getlist(key, default, section):
0199            item = item.strip()
0200            if not item:
0201                continue
0202            if ',' in item:
0203                result.extend([i.strip() for i in item.split(',')])
0204            else:
0205                result.append(item)
0206        return result
0207
0208    def getstartswith(self, startswith, section):
0209        """
0210        Returns a list of ``[(key, value), ...]`` for all keys in the
0211        section that start with startswith.
0212        """
0213        result = []
0214        for key in self.keys(section=section):
0215            if not key.startswith(startswith):
0216                continue
0217            for value in self.getraw(key, section=section):
0218                result.append((key, value))
0219        return result
0220
0221    def __repr__(self):
0222        return '<%s filename=%s>' % (
0223            self.__class__.__name__, self.filename)
0224
0225    def __str__(self):
0226        data = []
0227        data.append('%s from %s:' % (
0228            self.__class__.__name__, self.filename))
0229        for name, value_list in self.raw_data.get(None, {}).items():
0230            for value in value_list:
0231                data.append('%s: %s' % (name, value))
0232        for section_name, value_dict in self.raw_data.items():
0233            if section_name is None:
0234                continue
0235            data.append('[%s]' % section_name)
0236            for name, value_list in value_dict.items():
0237                for value in value_list:
0238                    data.append('%s: %s' % (name, value))
0239        return '\n'.join(data)
0240
0241def load_options(parser, options, config, if_exists=True):
0242    """
0243    Given a parser object and the parsed options and a configuration
0244    object or filename, this will load the configuration into the
0245    parsed options.
0246    """
0247    types = {}
0248    dests = {}
0249    aliases = {}
0250    for option in parser.option_list:
0251        if not option.dest:
0252            # Some builtin options, like --help
0253            continue
0254        name = clean_name(option.dest)
0255        dests[name] = option.dest
0256        if option.action in ('store_true', 'store_false'):
0257            types[name] = 'getbool'
0258        else:
0259            types[name] = 'get'
0260        for lst in option._long_opts, option._short_opts:
0261            for opt in lst:
0262                aliases[clean_name(opt)] = name
0263    if isinstance(config, str):
0264        if if_exists and not os.path.exists(config):
0265            return
0266        config = Config(config)
0267    for config_key in config.keys():
0268        name = aliases.get(config_key, config_key)
0269        if name not in dests:
0270            raise ValueError(
0271                "Bad configuration file: option %r unexpected" % config_key)
0272        value = getattr(config, types[name])(config_key)
0273        setattr(options, dests[name], value)