home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) from __future__ import generators import sys INTP_VER = sys.version_info[:2] if INTP_VER < (2, 2): raise RuntimeError('Python v.2.2 or later needed') INTP_VER < (2, 2) import os import re compiler = None try: import compiler except ImportError: pass from types import StringTypes from warnings import warn try: from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE except ImportError: BOM_UTF8 = '\xef\xbb\xbf' BOM_UTF16_LE = '\xff\xfe' BOM_UTF16_BE = '\xfe\xff' if sys.byteorder == 'little': BOM_UTF16 = BOM_UTF16_LE else: BOM_UTF16 = BOM_UTF16_BE except: sys.byteorder == 'little' BOMS = { BOM_UTF8: ('utf_8', None), BOM_UTF16_BE: ('utf16_be', 'utf_16'), BOM_UTF16_LE: ('utf16_le', 'utf_16'), BOM_UTF16: ('utf_16', 'utf_16') } BOM_LIST = { 'utf_16': 'utf_16', 'u16': 'utf_16', 'utf16': 'utf_16', 'utf-16': 'utf_16', 'utf16_be': 'utf16_be', 'utf_16_be': 'utf16_be', 'utf-16be': 'utf16_be', 'utf16_le': 'utf16_le', 'utf_16_le': 'utf16_le', 'utf-16le': 'utf16_le', 'utf_8': 'utf_8', 'u8': 'utf_8', 'utf': 'utf_8', 'utf8': 'utf_8', 'utf-8': 'utf_8' } BOM_SET = { 'utf_8': BOM_UTF8, 'utf_16': BOM_UTF16, 'utf16_be': BOM_UTF16_BE, 'utf16_le': BOM_UTF16_LE, None: BOM_UTF8 } def match_utf8(encoding): return BOM_LIST.get(encoding.lower()) == 'utf_8' squot = "'%s'" dquot = '"%s"' noquot = '%s' wspace_plus = ' \r\t\n\x0b\t\'"' tsquot = '"""%s"""' tdquot = "'''%s'''" try: enumerate except NameError: def enumerate(obj): i = -1 for item in obj: i += 1 yield (i, item) try: (True, False) except NameError: (True, False) = (1, 0) __version__ = '4.5.2' __revision__ = '$Id: configobj.py 156 2006-01-31 14:57:08Z fuzzyman $' __docformat__ = 'restructuredtext en' __all__ = ('__version__', 'DEFAULT_INDENT_TYPE', 'DEFAULT_INTERPOLATION', 'ConfigObjError', 'NestingError', 'ParseError', 'DuplicateError', 'ConfigspecError', 'ConfigObj', 'SimpleVal', 'InterpolationError', 'InterpolationLoopError', 'MissingInterpolationOption', 'RepeatSectionError', 'ReloadError', 'UnreprError', 'UnknownType', '__docformat__', 'flatten_errors') DEFAULT_INTERPOLATION = 'configparser' DEFAULT_INDENT_TYPE = ' ' MAX_INTERPOL_DEPTH = 10 OPTION_DEFAULTS = { 'interpolation': True, 'raise_errors': False, 'list_values': True, 'create_empty': False, 'file_error': False, 'configspec': None, 'stringify': True, 'indent_type': None, 'encoding': None, 'default_encoding': None, 'unrepr': False, 'write_empty_values': False } def getObj(s): s = 'a=' + s if compiler is None: raise ImportError('compiler module not available') compiler is None p = compiler.parse(s) return p.getChildren()[1].getChildren()[0].getChildren()[1] class UnknownType(Exception): pass class Builder(object): def build(self, o): m = getattr(self, 'build_' + o.__class__.__name__, None) if m is None: raise UnknownType(o.__class__.__name__) m is None return m(o) def build_List(self, o): return map(self.build, o.getChildren()) def build_Const(self, o): return o.value def build_Dict(self, o): d = { } i = iter(map(self.build, o.getChildren())) for el in i: d[el] = i.next() return d def build_Tuple(self, o): return tuple(self.build_List(o)) def build_Name(self, o): if o.name == 'None': return None if o.name == 'True': return True if o.name == 'False': return False raise UnknownType('Undefined Name') def build_Add(self, o): (real, imag) = map(self.build_Const, o.getChildren()) try: real = float(real) except TypeError: raise UnknownType('Add') if not isinstance(imag, complex) or imag.real != 0: raise UnknownType('Add') imag.real != 0 return real + imag def build_Getattr(self, o): parent = self.build(o.expr) return getattr(parent, o.attrname) def build_UnarySub(self, o): return -self.build_Const(o.getChildren()[0]) def build_UnaryAdd(self, o): return self.build_Const(o.getChildren()[0]) _builder = Builder() def unrepr(s): if not s: return s return _builder.build(getObj(s)) class ConfigObjError(SyntaxError): def __init__(self, message = '', line_number = None, line = ''): self.line = line self.line_number = line_number self.message = message SyntaxError.__init__(self, message) class NestingError(ConfigObjError): pass class ParseError(ConfigObjError): pass class ReloadError(IOError): def __init__(self): IOError.__init__(self, 'reload failed, filename is not set.') class DuplicateError(ConfigObjError): pass class ConfigspecError(ConfigObjError): pass class InterpolationError(ConfigObjError): pass class InterpolationLoopError(InterpolationError): def __init__(self, option): InterpolationError.__init__(self, 'interpolation loop detected in value "%s".' % option) class RepeatSectionError(ConfigObjError): pass class MissingInterpolationOption(InterpolationError): def __init__(self, option): InterpolationError.__init__(self, 'missing option "%s" in interpolation.' % option) class UnreprError(ConfigObjError): pass class InterpolationEngine(object): _KEYCRE = re.compile('%\\(([^)]*)\\)s') def __init__(self, section): self.section = section def interpolate(self, key, value): def recursive_interpolate(key, value, section, backtrail): if backtrail.has_key((key, section.name)): raise InterpolationLoopError(key) backtrail.has_key((key, section.name)) backtrail[(key, section.name)] = 1 match = self._KEYCRE.search(value) while match: (k, v, s) = self._parse_match(match) if k is None: replacement = v else: replacement = recursive_interpolate(k, v, s, backtrail) (start, end) = match.span() value = ''.join((value[:start], replacement, value[end:])) new_search_start = start + len(replacement) match = self._KEYCRE.search(value, new_search_start) del backtrail[(key, section.name)] return value value = recursive_interpolate(key, value, self.section, { }) return value def _fetch(self, key): save_interp = self.section.main.interpolation self.section.main.interpolation = False current_section = self.section while True: val = current_section.get(key) if val is not None: break val = current_section.get('DEFAULT', { }).get(key) if val is not None: break if current_section.parent is current_section: break current_section = current_section.parent self.section.main.interpolation = save_interp if val is None: raise MissingInterpolationOption(key) val is None return (val, current_section) def _parse_match(self, match): raise NotImplementedError() class ConfigParserInterpolation(InterpolationEngine): _KEYCRE = re.compile('%\\(([^)]*)\\)s') def _parse_match(self, match): key = match.group(1) (value, section) = self._fetch(key) return (key, value, section) class TemplateInterpolation(InterpolationEngine): _delimiter = '$' _KEYCRE = re.compile('\n \\$(?:\n (?P<escaped>\\$) | # Two $ signs\n (?P<named>[_a-z][_a-z0-9]*) | # $name format\n {(?P<braced>[^}]*)} # ${name} format\n )\n ', re.IGNORECASE | re.VERBOSE) def _parse_match(self, match): if not match.group('named'): pass key = match.group('braced') if key is not None: (value, section) = self._fetch(key) return (key, value, section) if match.group('escaped') is not None: return (None, self._delimiter, None) return (None, match.group(), None) interpolation_engines = { 'configparser': ConfigParserInterpolation, 'template': TemplateInterpolation } class Section(dict): def __init__(self, parent, depth, main, indict = None, name = None): if indict is None: indict = { } dict.__init__(self) self.parent = parent self.main = main self.depth = depth self.name = name self._initialise() for entry, value in indict.iteritems(): self[entry] = value def _initialise(self): self.scalars = [] self.sections = [] self.comments = { } self.inline_comments = { } self.configspec = { } self._order = [] self._configspec_comments = { } self._configspec_inline_comments = { } self._cs_section_comments = { } self._cs_section_inline_comments = { } self.defaults = [] self.default_values = { } def _interpolate(self, key, value): try: engine = self._interpolation_engine except AttributeError: name = self.main.interpolation if name == True: name = DEFAULT_INTERPOLATION name = name.lower() class_ = interpolation_engines.get(name, None) if class_ is None: self.main.interpolation = False return value except: engine = self._interpolation_engine = class_(self) return engine.interpolate(key, value) def __getitem__(self, key): val = dict.__getitem__(self, key) if self.main.interpolation and isinstance(val, StringTypes): return self._interpolate(key, val) return val def __setitem__(self, key, value, unrepr = False): if not isinstance(key, StringTypes): raise ValueError('The key "%s" is not a string.' % key) isinstance(key, StringTypes) if not self.comments.has_key(key): self.comments[key] = [] self.inline_comments[key] = '' if key in self.defaults: self.defaults.remove(key) if isinstance(value, Section): if not self.has_key(key): self.sections.append(key) dict.__setitem__(self, key, value) elif isinstance(value, dict) and not unrepr: if not self.has_key(key): self.sections.append(key) new_depth = self.depth + 1 dict.__setitem__(self, key, Section(self, new_depth, self.main, indict = value, name = key)) elif not self.has_key(key): self.scalars.append(key) if not self.main.stringify: if isinstance(value, StringTypes): pass elif isinstance(value, (list, tuple)): for entry in value: if not isinstance(entry, StringTypes): raise TypeError('Value is not a string "%s".' % entry) isinstance(entry, StringTypes) else: raise TypeError('Value is not a string "%s".' % value) isinstance(value, StringTypes) dict.__setitem__(self, key, value) def __delitem__(self, key): dict.__delitem__(self, key) if key in self.scalars: self.scalars.remove(key) else: self.sections.remove(key) del self.comments[key] del self.inline_comments[key] def get(self, key, default = None): try: return self[key] except KeyError: return default def update(self, indict): for entry in indict: self[entry] = indict[entry] def pop(self, key, *args): val = dict.pop(self, key, *args) if key in self.scalars: del self.comments[key] del self.inline_comments[key] self.scalars.remove(key) elif key in self.sections: del self.comments[key] del self.inline_comments[key] self.sections.remove(key) if self.main.interpolation and isinstance(val, StringTypes): return self._interpolate(key, val) return val def popitem(self): sequence = self.scalars + self.sections if not sequence: raise KeyError(": 'popitem(): dictionary is empty'") sequence key = sequence[0] val = self[key] del self[key] return (key, val) def clear(self): dict.clear(self) self.scalars = [] self.sections = [] self.comments = { } self.inline_comments = { } self.configspec = { } def setdefault(self, key, default = None): try: return self[key] except KeyError: self[key] = default return self[key] def items(self): return zip(self.scalars + self.sections, self.values()) def keys(self): return self.scalars + self.sections def values(self): return [ self[key] for key in self.scalars + self.sections ] def iteritems(self): return iter(self.items()) def iterkeys(self): return iter(self.scalars + self.sections) __iter__ = iterkeys def itervalues(self): return iter(self.values()) def __repr__(self): return [] % []([ '%s: %s' % (repr(key), repr(self[key])) for key in self.scalars + self.sections ]) __str__ = __repr__ __str__.__doc__ = 'x.__str__() <==> str(x)' def dict(self): newdict = { } for entry in self: this_entry = self[entry] if isinstance(this_entry, Section): this_entry = this_entry.dict() elif isinstance(this_entry, list): this_entry = list(this_entry) elif isinstance(this_entry, tuple): this_entry = tuple(this_entry) newdict[entry] = this_entry return newdict def merge(self, indict): for key, val in indict.items(): if key in self and isinstance(self[key], dict) and isinstance(val, dict): self[key].merge(val) continue self[key] = val def rename(self, oldkey, newkey): if oldkey in self.scalars: the_list = self.scalars elif oldkey in self.sections: the_list = self.sections else: raise KeyError('Key "%s" not found.' % oldkey) pos = (oldkey in self.scalars).index(oldkey) val = self[oldkey] dict.__delitem__(self, oldkey) dict.__setitem__(self, newkey, val) the_list.remove(oldkey) the_list.insert(pos, newkey) comm = self.comments[oldkey] inline_comment = self.inline_comments[oldkey] del self.comments[oldkey] del self.inline_comments[oldkey] self.comments[newkey] = comm self.inline_comments[newkey] = inline_comment def walk(self, function, raise_errors = True, call_on_sections = False, **keywargs): out = { } for i in range(len(self.scalars)): entry = self.scalars[i] try: val = function(self, entry, **keywargs) entry = self.scalars[i] out[entry] = val continue except Exception: if raise_errors: raise raise_errors entry = self.scalars[i] out[entry] = False continue for i in range(len(self.sections)): entry = self.sections[i] if call_on_sections: try: function(self, entry, **keywargs) except Exception: None<EXCEPTION MATCH>Exception None<EXCEPTION MATCH>Exception if raise_errors: raise raise_errors entry = self.sections[i] out[entry] = False except: None<EXCEPTION MATCH>Exception entry = self.sections[i] out[entry] = self[entry].walk(function, raise_errors = raise_errors, call_on_sections = call_on_sections, **keywargs) return out def decode(self, encoding): warn('use of ``decode`` is deprecated.', DeprecationWarning) def decode(section, key, encoding = encoding, warn = True): val = section[key] if isinstance(val, (list, tuple)): newval = [] for entry in val: newval.append(entry.decode(encoding)) elif isinstance(val, dict): newval = val else: newval = val.decode(encoding) newkey = key.decode(encoding) section.rename(key, newkey) section[newkey] = newval self.walk(decode, call_on_sections = True) def encode(self, encoding): warn('use of ``encode`` is deprecated.', DeprecationWarning) def encode(section, key, encoding = encoding): val = section[key] if isinstance(val, (list, tuple)): newval = [] for entry in val: newval.append(entry.encode(encoding)) elif isinstance(val, dict): newval = val else: newval = val.encode(encoding) newkey = key.encode(encoding) section.rename(key, newkey) section[newkey] = newval self.walk(encode, call_on_sections = True) def istrue(self, key): warn('use of ``istrue`` is deprecated. Use ``as_bool`` method instead.', DeprecationWarning) return self.as_bool(key) def as_bool(self, key): val = self[key] if val == True: return True if val == False: return False try: if not isinstance(val, StringTypes): raise KeyError() isinstance(val, StringTypes) return self.main._bools[val.lower()] except KeyError: val == False val == False val == True raise ValueError('Value "%s" is neither True nor False' % val) except: val == False def as_int(self, key): return int(self[key]) def as_float(self, key): return float(self[key]) def restore_default(self, key): default = self.default_values[key] dict.__setitem__(self, key, default) if key not in self.defaults: self.defaults.append(key) return default def restore_defaults(self): for key in self.default_values: self.restore_default(key) for section in self.sections: self[section].restore_defaults() class ConfigObj(Section): _keyword = re.compile('^ # line start\n (\\s*) # indentation\n ( # keyword\n (?:".*?")| # double quotes\n (?:\'.*?\')| # single quotes\n (?:[^\'"=].*?) # no quotes\n )\n \\s*=\\s* # divider\n (.*) # value (including list values and comments)\n $ # line end\n ', re.VERBOSE) _sectionmarker = re.compile('^\n (\\s*) # 1: indentation\n ((?:\\[\\s*)+) # 2: section marker open\n ( # 3: section name open\n (?:"\\s*\\S.*?\\s*")| # at least one non-space with double quotes\n (?:\'\\s*\\S.*?\\s*\')| # at least one non-space with single quotes\n (?:[^\'"\\s].*?) # at least one non-space unquoted\n ) # section name close\n ((?:\\s*\\])+) # 4: section marker close\n \\s*(\\#.*)? # 5: optional comment\n $', re.VERBOSE) _valueexp = re.compile('^\n (?:\n (?:\n (\n (?:\n (?:\n (?:".*?")| # double quotes\n (?:\'.*?\')| # single quotes\n (?:[^\'",\\#][^,\\#]*?) # unquoted\n )\n \\s*,\\s* # comma\n )* # match all list items ending in a comma (if any)\n )\n (\n (?:".*?")| # double quotes\n (?:\'.*?\')| # single quotes\n (?:[^\'",\\#\\s][^,]*?)| # unquoted\n (?:(?<!,)) # Empty value\n )? # last item in a list - or string value\n )|\n (,) # alternatively a single comma - empty list\n )\n \\s*(\\#.*)? # optional comment\n $', re.VERBOSE) _listvalueexp = re.compile('\n (\n (?:".*?")| # double quotes\n (?:\'.*?\')| # single quotes\n (?:[^\'",\\#].*?) # unquoted\n )\n \\s*,\\s* # comma\n ', re.VERBOSE) _nolistvalue = re.compile('^\n (\n (?:".*?")| # double quotes\n (?:\'.*?\')| # single quotes\n (?:[^\'"\\#].*?)| # unquoted\n (?:) # Empty value\n )\n \\s*(\\#.*)? # optional comment\n $', re.VERBOSE) _single_line_single = re.compile("^'''(.*?)'''\\s*(#.*)?$") _single_line_double = re.compile('^"""(.*?)"""\\s*(#.*)?$') _multi_line_single = re.compile("^(.*?)'''\\s*(#.*)?$") _multi_line_double = re.compile('^(.*?)"""\\s*(#.*)?$') _triple_quote = { "'''": (_single_line_single, _multi_line_single), '"""': (_single_line_double, _multi_line_double) } _bools = { 'yes': True, 'no': False, 'on': True, 'off': False, '1': True, '0': False, 'true': True, 'false': False } def __init__(self, infile = None, options = None, **kwargs): Section.__init__(self, self, 0, self) if infile is None: infile = [] if options is None: options = { } else: options = dict(options) options.update(kwargs) defaults = OPTION_DEFAULTS.copy() for entry in options: if entry not in defaults: raise TypeError('Unrecognised option "%s".' % entry) entry not in defaults defaults.update(options) self._initialise(defaults) configspec = defaults['configspec'] self._original_configspec = configspec self._load(infile, configspec) def _load(self, infile, configspec): if isinstance(infile, StringTypes): self.filename = infile if os.path.isfile(infile): h = open(infile, 'rb') if not h.read(): pass infile = [] h.close() elif self.file_error: raise IOError('Config file not found: "%s".' % self.filename) elif self.create_empty: h = open(infile, 'w') h.write('') h.close() infile = [] elif isinstance(infile, (list, tuple)): infile = list(infile) elif isinstance(infile, dict): if isinstance(infile, ConfigObj): infile = infile.dict() for entry in infile: self[entry] = infile[entry] del self._errors if configspec is not None: self._handle_configspec(configspec) else: self.configspec = None return None if hasattr(infile, 'read'): if not infile.read(): pass infile = [] else: raise TypeError('infile must be a filename, file like object, or list of lines.') self._parse(infile) if self._errors: info = 'at line %s.' % self._errors[0].line_number if len(self._errors) > 1: msg = 'Parsing failed with several errors.\nFirst error %s' % info error = ConfigObjError(msg) else: error = self._errors[0] error.errors = self._errors error.config = self raise error self._errors del self._errors if configspec is None: self.configspec = None else: self._handle_configspec(configspec) def _initialise(self, options = None): if options is None: options = OPTION_DEFAULTS self.filename = None self._errors = [] self.raise_errors = options['raise_errors'] self.interpolation = options['interpolation'] self.list_values = options['list_values'] self.create_empty = options['create_empty'] self.file_error = options['file_error'] self.stringify = options['stringify'] self.indent_type = options['indent_type'] self.encoding = options['encoding'] self.default_encoding = options['default_encoding'] self.BOM = False self.newlines = None self.write_empty_values = options['write_empty_values'] self.unrepr = options['unrepr'] self.initial_comment = [] self.final_comment = [] self.configspec = { } Section._initialise(self) def __repr__(self): return [] % []([ '%s: %s' % (repr(key), repr(self[key])) for key in self.scalars + self.sections ]) def _handle_bom(self, infile): if self.encoding is not None and self.encoding.lower() not in BOM_LIST: return self._decode(infile, self.encoding) if isinstance(infile, (list, tuple)): line = infile[0] else: line = infile if self.encoding is not None: enc = BOM_LIST[self.encoding.lower()] if enc == 'utf_16': for encoding, final_encoding in BOMS.items(): if not final_encoding: continue if infile.startswith(BOM): return self._decode(infile, encoding) return self._decode(infile, self.encoding) BOM = BOM_SET[enc] if not line.startswith(BOM): return self._decode(infile, self.encoding) newline = line[len(BOM):] self.BOM = True return self._decode(infile, self.encoding) for encoding, final_encoding in BOMS.items(): if not line.startswith(BOM): continue continue self.encoding = final_encoding if not final_encoding: self.BOM = True newline = line[len(BOM):] if isinstance(infile, (list, tuple)): infile[0] = newline else: infile = newline if isinstance(infile, StringTypes): return infile.splitlines(True) return infile final_encoding return self._decode(infile, encoding) if isinstance(infile, StringTypes): return infile.splitlines(True) return infile def _a_to_u(self, aString): if self.encoding: return aString.decode('ascii') return aString def _decode(self, infile, encoding): if isinstance(infile, StringTypes): return infile.decode(encoding).splitlines(True) for i, line in enumerate(infile): if not isinstance(line, unicode): infile[i] = line.decode(encoding) continue isinstance(infile, StringTypes) return infile def _decode_element(self, line): if not self.encoding: return line if isinstance(line, str) and self.default_encoding: return line.decode(self.default_encoding) return line def _str(self, value): if not isinstance(value, StringTypes): return str(value) return value def _parse(self, infile): temp_list_values = self.list_values if self.unrepr: self.list_values = False comment_list = [] done_start = False this_section = self maxline = len(infile) - 1 cur_index = -1 reset_comment = False while cur_index < maxline: if reset_comment: comment_list = [] cur_index += 1 line = infile[cur_index] sline = line.strip() if not sline or sline.startswith('#'): reset_comment = False comment_list.append(line) continue if not done_start: self.initial_comment = comment_list comment_list = [] done_start = True reset_comment = True mat = self._sectionmarker.match(line) if mat is not None: (indent, sect_open, sect_name, sect_close, comment) = mat.groups() if indent and self.indent_type is None: self.indent_type = indent cur_depth = sect_open.count('[') if cur_depth != sect_close.count(']'): self._handle_error('Cannot compute the section depth at line %s.', NestingError, infile, cur_index) continue if cur_depth < this_section.depth: try: parent = self._match_depth(this_section, cur_depth).parent except SyntaxError: self._handle_error('Cannot compute nesting level at line %s.', NestingError, infile, cur_index) continue except: None<EXCEPTION MATCH>SyntaxError None<EXCEPTION MATCH>SyntaxError if cur_depth == this_section.depth: parent = this_section.parent elif cur_depth == this_section.depth + 1: parent = this_section else: self._handle_error('Section too nested at line %s.', NestingError, infile, cur_index) sect_name = self._unquote(sect_name) if parent.has_key(sect_name): self._handle_error('Duplicate section name at line %s.', DuplicateError, infile, cur_index) continue this_section = Section(parent, cur_depth, self, name = sect_name) parent[sect_name] = this_section parent.inline_comments[sect_name] = comment parent.comments[sect_name] = comment_list continue mat = self._keyword.match(line) if mat is None: self._handle_error('Invalid line at line "%s".', ParseError, infile, cur_index) continue (indent, key, value) = mat.groups() if indent and self.indent_type is None: self.indent_type = indent if value[:3] in ('"""', "'''"): try: (value, comment, cur_index) = self._multiline(value, infile, cur_index, maxline) except SyntaxError: self._handle_error('Parse error in value at line %s.', ParseError, infile, cur_index) continue if self.unrepr: comment = '' try: value = unrepr(value) except Exception: e = None if type(e) == UnknownType: msg = 'Unknown name or type in value at line %s.' else: msg = 'Parse error in value at line %s.' self._handle_error(msg, UnreprError, infile, cur_index) continue except: None<EXCEPTION MATCH>Exception None<EXCEPTION MATCH>Exception elif self.unrepr: comment = '' try: value = unrepr(value) except Exception: e = None if isinstance(e, UnknownType): msg = 'Unknown name or type in value at line %s.' else: msg = 'Parse error in value at line %s.' self._handle_error(msg, UnreprError, infile, cur_index) continue except: None<EXCEPTION MATCH>Exception None<EXCEPTION MATCH>Exception try: (value, comment) = self._handle_value(value) except SyntaxError: self._handle_error('Parse error in value at line %s.', ParseError, infile, cur_index) continue key = self._unquote(key) if this_section.has_key(key): self._handle_error('Duplicate keyword name at line %s.', DuplicateError, infile, cur_index) continue this_section.__setitem__(key, value, unrepr = True) this_section.inline_comments[key] = comment this_section.comments[key] = comment_list continue if self.indent_type is None: self.indent_type = '' if not self and not (self.initial_comment): self.initial_comment = comment_list elif not reset_comment: self.final_comment = comment_list self.list_values = temp_list_values def _match_depth(self, sect, depth): while depth < sect.depth: if sect is sect.parent: raise SyntaxError() sect is sect.parent sect = sect.parent if sect.depth == depth: return sect raise SyntaxError() def _handle_error(self, text, ErrorClass, infile, cur_index): line = infile[cur_index] cur_index += 1 message = text % cur_index error = ErrorClass(message, cur_index, line) if self.raise_errors: raise error self.raise_errors self._errors.append(error) def _unquote(self, value): if value[0] == value[-1] and value[0] in ('"', "'"): value = value[1:-1] return value def _quote(self, value, multiline = True): if multiline and self.write_empty_values and value == '': return '' if multiline and isinstance(value, (list, tuple)): if not value: return ',' if len(value) == 1: return self._quote(value[0], multiline = False) + ',' return []([ self._quote(val, multiline = False) for val in value ]) if not isinstance(value, StringTypes): if self.stringify: value = str(value) else: raise TypeError('Value "%s" is not a string.' % value) self.stringify if not value: return '""' if not (self.list_values) and '\n' not in value: pass no_lists_no_quotes = '#' not in value if multiline: if not "'" in value or '"' in value: pass need_triple = '\n' in value if multiline and not need_triple and "'" in value and '"' in value: pass hash_triple_quote = '#' in value if no_lists_no_quotes or not need_triple: pass check_for_single = not hash_triple_quote if quot == noquot and '#' in value and self.list_values: quot = self._get_single_quote(value) return quot % value def _get_single_quote(self, value): if "'" in value and '"' in value: raise ConfigObjError('Value "%s" cannot be safely quoted.' % value) '"' in value if '"' in value: quot = squot else: quot = dquot return quot def _get_triple_quote(self, value): if value.find('"""') != -1 and value.find("'''") != -1: raise ConfigObjError('Value "%s" cannot be safely quoted.' % value) value.find("'''") != -1 if value.find('"""') == -1: quot = tdquot else: quot = tsquot return quot def _handle_value(self, value): if not self.list_values: mat = self._nolistvalue.match(value) if mat is None: raise SyntaxError() mat is None return mat.groups() mat = self._valueexp.match(value) if mat is None: raise SyntaxError() mat is None (list_values, single, empty_list, comment) = mat.groups() if list_values == '' and single is None: raise SyntaxError() single is None if empty_list is not None: return ([], comment) if list_values == '': return (single, comment) the_list = self._listvalueexp.findall(list_values) the_list = [ self._unquote(val) for val in the_list ] return (the_list, comment) def _multiline(self, value, infile, cur_index, maxline): quot = value[:3] newvalue = value[3:] single_line = self._triple_quote[quot][0] multi_line = self._triple_quote[quot][1] mat = single_line.match(value) if mat is not None: retval = list(mat.groups()) retval.append(cur_index) return retval if newvalue.find(quot) != -1: raise SyntaxError() newvalue.find(quot) != -1 while cur_index < maxline: cur_index += 1 newvalue += '\n' line = infile[cur_index] if line.find(quot) == -1: newvalue += line continue mat is not None break raise SyntaxError() mat = multi_line.match(line) if mat is None: raise SyntaxError() mat is None (value, comment) = mat.groups() return (newvalue + value, comment, cur_index) def _handle_configspec(self, configspec): if not isinstance(configspec, ConfigObj): try: configspec = ConfigObj(configspec, raise_errors = True, file_error = True, list_values = False) except ConfigObjError: e = None raise ConfigspecError('Parsing configspec failed: %s' % e) except IOError: e = None raise IOError('Reading configspec failed: %s' % e) except: None<EXCEPTION MATCH>ConfigObjError None<EXCEPTION MATCH>ConfigObjError self._set_configspec_value(configspec, self) def _set_configspec_value(self, configspec, section): if '__many__' in configspec.sections: section.configspec['__many__'] = configspec['__many__'] if len(configspec.sections) > 1: raise RepeatSectionError() len(configspec.sections) > 1 if hasattr(configspec, 'initial_comment'): section._configspec_initial_comment = configspec.initial_comment section._configspec_final_comment = configspec.final_comment section._configspec_encoding = configspec.encoding section._configspec_BOM = configspec.BOM section._configspec_newlines = configspec.newlines section._configspec_indent_type = configspec.indent_type for entry in configspec.scalars: section._configspec_comments[entry] = configspec.comments[entry] section._configspec_inline_comments[entry] = configspec.inline_comments[entry] section.configspec[entry] = configspec[entry] section._order.append(entry) for entry in configspec.sections: if entry == '__many__': continue section._cs_section_comments[entry] = configspec.comments[entry] section._cs_section_inline_comments[entry] = configspec.inline_comments[entry] if not section.has_key(entry): section[entry] = { } self._set_configspec_value(configspec[entry], section[entry]) def _handle_repeat(self, section, configspec): try: section_keys = configspec.sections scalar_keys = configspec.scalars except AttributeError: section_keys = _[1] scalar_keys = _[2] except: [] if '__many__' in section_keys and len(section_keys) > 1: raise RepeatSectionError() len(section_keys) > 1 scalars = { } sections = { } for entry in scalar_keys: val = configspec[entry] scalars[entry] = val for entry in section_keys: val = configspec[entry] sections[entry] = val section.configspec = scalars for entry in sections: self._handle_repeat(section[entry], sections[entry]) def _write_line(self, indent_string, entry, this_entry, comment): if not self.unrepr: val = self._decode_element(self._quote(this_entry)) else: val = repr(this_entry) return '%s%s%s%s%s' % (indent_string, self._decode_element(self._quote(entry, multiline = False)), self._a_to_u(' = '), val, self._decode_element(comment)) def _write_marker(self, indent_string, depth, entry, comment): return '%s%s%s%s%s' % (indent_string, self._a_to_u('[' * depth), self._quote(self._decode_element(entry), multiline = False), self._a_to_u(']' * depth), self._decode_element(comment)) def _handle_comment(self, comment): if not comment: return '' start = self.indent_type if not comment.startswith('#'): start += self._a_to_u(' # ') return start + comment def write(self, outfile = None, section = None): if self.indent_type is None: self.indent_type = DEFAULT_INDENT_TYPE out = [] cs = self._a_to_u('#') csp = self._a_to_u('# ') if section is None: int_val = self.interpolation self.interpolation = False section = self for line in self.initial_comment: line = self._decode_element(line) stripped_line = line.strip() if stripped_line and not stripped_line.startswith(cs): line = csp + line out.append(line) indent_string = self.indent_type * section.depth for entry in section.scalars + section.sections: if entry in section.defaults: continue for comment_line in section.comments[entry]: comment_line = self._decode_element(comment_line.lstrip()) if comment_line and not comment_line.startswith(cs): comment_line = csp + comment_line out.append(indent_string + comment_line) this_entry = section[entry] comment = self._handle_comment(section.inline_comments[entry]) if isinstance(this_entry, dict): out.append(self._write_marker(indent_string, this_entry.depth, entry, comment)) out.extend(self.write(section = this_entry)) continue out.append(self._write_line(indent_string, entry, this_entry, comment)) if section is self: for line in self.final_comment: line = self._decode_element(line) stripped_line = line.strip() if stripped_line and not stripped_line.startswith(cs): line = csp + line out.append(line) self.interpolation = int_val if section is not self: return out if self.filename is None and outfile is None: if self.BOM: pass return out if not self.newlines: pass newline = os.linesep output = self._a_to_u(newline).join(out) if self.BOM: if self.encoding is None or match_utf8(self.encoding): output = BOM_UTF8 + output if not output.endswith(newline): output += newline if outfile is not None: outfile.write(output) else: h = open(self.filename, 'wb') h.write(output) h.close() def validate(self, validator, preserve_errors = False, copy = False, section = None): if section is None: if self.configspec is None: raise ValueError('No configspec supplied.') self.configspec is None if preserve_errors: VdtMissingValue = VdtMissingValue import validate self._vdtMissingValue = VdtMissingValue section = self spec_section = section.configspec if copy and hasattr(section, '_configspec_initial_comment'): section.initial_comment = section._configspec_initial_comment section.final_comment = section._configspec_final_comment section.encoding = section._configspec_encoding section.BOM = section._configspec_BOM section.newlines = section._configspec_newlines section.indent_type = section._configspec_indent_type if '__many__' in section.configspec: many = spec_section['__many__'] for entry in section.sections: self._handle_repeat(section[entry], many) out = { } ret_true = True ret_false = True order = _[1] [] += _[2] for entry in order: try: check = validator.check(spec_section[entry], val, missing = missing) except validator.baseErrorClass: None if entry not in section.scalars or entry in section.defaults else [] e = None if entry not in section.scalars or entry in section.defaults else [] if not preserve_errors or isinstance(e, self._vdtMissingValue): out[entry] = False else: out[entry] = e ret_false = False ret_true = False continue try: section.default_values.pop(entry, None) except AttributeError: None if entry not in section.scalars or entry in section.defaults else [] None if entry not in section.scalars or entry in section.defaults else [] try: del section.default_values[entry] except KeyError: pass except: None<EXCEPTION MATCH>KeyError None<EXCEPTION MATCH>KeyError if hasattr(validator, 'get_default_value'): try: section.default_values[entry] = validator.get_default_value(spec_section[entry]) except KeyError: None if entry not in section.scalars or entry in section.defaults else [] None if entry not in section.scalars or entry in section.defaults else [] except: None if entry not in section.scalars or entry in section.defaults else []<EXCEPTION MATCH>KeyError None if entry not in section.scalars or entry in section.defaults else [] ret_false = False out[entry] = True if self.stringify or missing: if not self.stringify: if isinstance(check, (list, tuple)): check = [ self._str(item) for item in check ] elif missing and check is None: check = '' else: check = self._str(check) if check != val or missing: section[entry] = check if not copy and missing and entry not in section.defaults: section.defaults.append(entry) continue for entry in section.sections: if section is self and entry == 'DEFAULT': continue if copy: section.comments[entry] = section._cs_section_comments[entry] section.inline_comments[entry] = section._cs_section_inline_comments[entry] check = self.validate(validator, preserve_errors = preserve_errors, copy = copy, section = section[entry]) out[entry] = check if check == False: ret_true = False continue if check == True: ret_false = False continue ret_true = False ret_false = False if ret_true: return True if ret_false: return False return out def reset(self): self.clear() self._initialise() self.configspec = None self._original_configspec = None def reload(self): if not isinstance(self.filename, StringTypes): raise ReloadError() isinstance(self.filename, StringTypes) filename = self.filename current_options = { } for entry in OPTION_DEFAULTS: if entry == 'configspec': continue current_options[entry] = getattr(self, entry) configspec = self._original_configspec current_options['configspec'] = configspec self.clear() self._initialise(current_options) self._load(filename, configspec) class SimpleVal(object): def __init__(self): self.baseErrorClass = ConfigObjError def check(self, check, member, missing = False): if missing: raise self.baseErrorClass() missing return member def flatten_errors(cfg, res, levels = None, results = None): if levels is None: levels = [] results = [] if res is True: return results if res is False: results.append((levels[:], None, False)) if levels: levels.pop() return results for key, val in res.items(): if isinstance(cfg.get(key), dict): levels.append(key) flatten_errors(cfg[key], val, levels, results) continue results.append((levels[:], key, val)) if levels: levels.pop() return results