19 from codecs
import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE
30 BOM_UTF8: (
'utf_8',
None),
31 BOM_UTF16_BE: (
'utf16_be',
'utf_16'),
32 BOM_UTF16_LE: (
'utf16_le',
'utf_16'),
33 BOM_UTF16: (
'utf_16',
'utf_16'),
43 'utf16_be':
'utf16_be',
44 'utf_16_be':
'utf16_be',
45 'utf-16be':
'utf16_be',
46 'utf16_le':
'utf16_le',
47 'utf_16_le':
'utf16_le',
48 'utf-16le':
'utf16_le',
60 'utf16_be': BOM_UTF16_BE,
61 'utf16_le': BOM_UTF16_LE,
67 return BOM_LIST.get(encoding.lower()) ==
'utf_8'
74 wspace_plus =
' \r\n\v\t\'"'
82 'DEFAULT_INDENT_TYPE',
83 'DEFAULT_INTERPOLATION',
92 'InterpolationLoopError',
93 'MissingInterpolationOption',
102 DEFAULT_INTERPOLATION =
'configparser'
103 DEFAULT_INDENT_TYPE =
' '
104 MAX_INTERPOL_DEPTH = 10
107 'interpolation':
True,
108 'raise_errors':
False,
110 'create_empty':
False,
117 'default_encoding':
None,
119 'write_empty_values':
False,
131 p = compiler.parse(s)
132 return p.getChildren()[1].getChildren()[0].getChildren()[1]
147 return list(map(self.
buildbuild, o.getChildren()))
154 i = iter(map(self.
buildbuild, o.getChildren()))
167 if o.name ==
'False':
174 real, imag = list(map(self.
build_Constbuild_Const, o.getChildren()))
179 if not isinstance(imag, complex)
or imag.real != 0.0:
184 parent = self.
buildbuild(o.expr)
185 return getattr(parent, o.attrname)
188 return -self.
build_Constbuild_Const(o.getChildren()[0])
191 return self.
build_Constbuild_Const(o.getChildren()[0])
206 return ast.literal_eval(s)
214 def __init__(self, message='', line_number=None, line=''):
217 SyntaxError.__init__(self, message)
240 IOError.__init__(self,
'reload failed, filename is not set.')
263 InterpolationError.__init__(
265 'interpolation loop detected in value "%s".' % option)
278 msg =
'missing option "%s" in interpolation.' % option
279 InterpolationError.__init__(self, msg)
299 _KEYCRE = re.compile(
r"%\(([^)]*)\)s")
312 if not self.
_cookie_cookie
in value:
324 def recursive_interpolate(key, value, section, backtrail):
326 if (key, section.name)
in backtrail:
330 backtrail[(key, section.name)] = 1
333 match = self.
_KEYCRE_KEYCRE.search(value)
343 replacement = recursive_interpolate(k, v, s, backtrail)
345 start, end = match.span()
346 value =
''.join((value[:start], replacement, value[end:]))
347 new_search_start = start + len(replacement)
350 match = self.
_KEYCRE_KEYCRE.search(value, new_search_start)
353 del backtrail[(key, section.name)]
359 value = recursive_interpolate(key, value, self.
sectionsection, {})
371 save_interp = self.
sectionsection.main.interpolation
372 self.
sectionsection.main.interpolation =
False
375 current_section = self.
sectionsection
378 val = current_section.get(key)
379 if val
is not None and not isinstance(val, Section):
382 val = current_section.get(
'DEFAULT', {}).get(key)
383 if val
is not None and not isinstance(val, Section):
387 if current_section.parent
is current_section:
390 current_section = current_section.parent
393 self.
sectionsection.main.interpolation = save_interp
396 return val, current_section
417 raise NotImplementedError()
429 _KEYCRE = re.compile(
r"%\(([^)]*)\)s")
433 value, section = self.
_fetch_fetch(key)
434 return key, value, section
451 _KEYCRE = re.compile(
r"""
453 (?P<escaped>\$) | # Two $ signs
454 (?P<named>[_a-z][_a-z0-9]*) | # $name format
455 {(?P<braced>[^}]*)} # ${name} format
457 """, re.IGNORECASE | re.VERBOSE)
461 key = match.group(
'named')
or match.group(
'braced')
463 value, section = self.
_fetch_fetch(key)
464 return key, value, section
466 if match.group(
'escaped')
is not None:
470 return None, match.group(),
None
473 interpolation_engines = {
474 'configparser': ConfigParserInterpolation,
475 'template': TemplateInterpolation,
481 return cls.__new__(cls, *args)
504 dict.update(self, state[0])
505 self.__dict__.
update(state[1])
508 state = (
dict(self), self.__dict__)
509 return (__newobj__, (self.__class__,), state)
518 def __init__(self, parent, depth, main, indict=None, name=None):
534 for entry, value
in indict.items():
559 except AttributeError:
561 name = self.
mainmain.interpolation
564 name = DEFAULT_INTERPOLATION
566 class_ = interpolation_engines.get(name,
None)
569 self.
mainmain.interpolation =
False
575 return engine.interpolate(key, value)
580 val = dict.__getitem__(self, key)
581 if self.
mainmain.interpolation:
582 if isinstance(val, six.string_types):
584 if isinstance(val, list):
586 if isinstance(entry, six.string_types):
589 new = [_check(entry)
for entry
in val]
609 if not isinstance(key, six.string_types):
610 raise ValueError(
'The key "%s" is not a string.' % key)
613 if key
not in self.
commentscomments:
620 if isinstance(value, Section):
623 dict.__setitem__(self, key, value)
624 elif isinstance(value, dict)
and not unrepr:
629 new_depth = self.
depthdepth + 1
641 self.
scalarsscalars.append(key)
642 if not self.
mainmain.stringify:
643 if isinstance(value, six.string_types):
645 elif isinstance(value, (list, tuple)):
647 if not isinstance(entry, six.string_types):
648 raise TypeError(
'Value is not a string "%s".' % entry)
650 raise TypeError(
'Value is not a string "%s".' % value)
651 dict.__setitem__(self, key, value)
658 self.
scalarsscalars.remove(key)
666 def get(self, key, default=None):
678 self[entry] = indict[entry]
685 def pop(self, key, default=MISSING):
689 if default
is MISSING:
701 raise KeyError(
": 'popitem(): dictionary is empty'")
747 return [self[key]
for key
in (self.
scalarsscalars + self.
sectionssections)]
752 return iter(list(self.
itemsitems()))
764 return iter(list(self.
valuesvalues()))
772 except MissingInterpolationOption:
773 return dict.__getitem__(self, key)
774 return '{%s}' %
', '.join([(
'%s: %s' % (repr(key), repr(_getval(key))))
778 __str__.__doc__ =
"x.__str__() <==> str(x)"
798 this_entry = self[entry]
799 if isinstance(this_entry, Section):
800 this_entry = this_entry.dict()
801 elif isinstance(this_entry, list):
803 this_entry = list(this_entry)
804 elif isinstance(this_entry, tuple):
806 this_entry = tuple(this_entry)
807 newdict[entry] = this_entry
830 for key, val
in list(indict.items()):
831 if (key
in self
and isinstance(self[key], dict)
and
832 isinstance(val, dict)):
847 if oldkey
in self.
scalarsscalars:
849 elif oldkey
in self.
sectionssections:
852 raise KeyError(
'Key "%s" not found.' % oldkey)
853 pos = the_list.index(oldkey)
856 dict.__delitem__(self, oldkey)
857 dict.__setitem__(self, newkey, val)
858 the_list.remove(oldkey)
859 the_list.insert(pos, newkey)
860 comm = self.
commentscomments[oldkey]
864 self.
commentscomments[newkey] = comm
913 def walk(self, function, raise_errors=True,
914 call_on_sections=False, **keywargs):
917 for i
in range(len(self.
scalarsscalars)):
920 val = function(self, entry, **keywargs)
931 for i
in range(len(self.
sectionssections)):
935 function(self, entry, **keywargs)
945 out[entry] = self[entry].
walk(
947 raise_errors=raise_errors,
948 call_on_sections=call_on_sections,
988 if not isinstance(val, six.string_types):
992 return self.
mainmain._bools[val.lower()]
994 raise ValueError(
'Value "%s" is neither True nor False' % val)
1017 return int(self[key])
1039 return float(self[key])
1059 if isinstance(result, (tuple, list)):
1074 dict.__setitem__(self, key, default)
1075 if key
not in self.
defaultsdefaults:
1093 for section
in self.
sectionssections:
1103 _keyword = re.compile(
r'''^ # line start
1106 (?:".*?")| # double quotes
1107 (?:'.*?')| # single quotes
1108 (?:[^'"=].*?) # no quotes
1111 (.*) # value (including list values and comments)
1119 _sectionmarker = re.compile(
r'''^
1120 (\s*) # 1: indentation
1121 ((?:\[\s*)+) # 2: section marker open
1122 ( # 3: section name open
1123 (?:"\s*\S.*?\s*")| # at least one non-space with double quotes
1124 (?:'\s*\S.*?\s*')| # at least one non-space with single quotes
1125 (?:[^'"\s].*?) # at least one non-space unquoted
1126 ) # section name close
1127 ((?:\s*\])+) # 4: section marker close
1128 \s*(\#.*)? # 5: optional comment
1139 _valueexp = re.compile(
r'''^
1145 (?:".*?")| # double quotes
1146 (?:'.*?')| # single quotes
1147 (?:[^'",\#][^,\#]*?) # unquoted
1150 )* # match all list items ending in a comma (if any)
1153 (?:".*?")| # double quotes
1154 (?:'.*?')| # single quotes
1155 (?:[^'",\#\s][^,]*?)| # unquoted
1156 (?:(?<!,)) # Empty value
1157 )? # last item in a list - or string value
1159 (,) # alternatively a single comma - empty list
1161 \s*(\#.*)? # optional comment
1169 _listvalueexp = re.compile(
r'''
1171 (?:".*?")| # double quotes
1172 (?:'.*?')| # single quotes
1173 (?:[^'",\#]?.*?) # unquoted
1184 _nolistvalue = re.compile(
r'''^
1186 (?:".*?")| # double quotes
1187 (?:'.*?')| # single quotes
1188 (?:[^'"\#].*?)| # unquoted
1191 \s*(\#.*)? # optional comment
1199 _single_line_single = re.compile(
r"^'''(.*?)'''\s*(#.*)?$")
1203 _single_line_double = re.compile(
r'^"""(.*?)"""\s*(#.*)?$')
1207 _multi_line_single = re.compile(
r"^(.*?)'''\s*(#.*)?$")
1211 _multi_line_double = re.compile(
r'^(.*?)"""\s*(#.*)?$')
1217 "'''": (_single_line_single, _multi_line_single),
1218 '"""': (_single_line_double, _multi_line_double),
1226 'yes':
True,
'no':
False,
1227 'on':
True,
'off':
False,
1228 '1':
True,
'0':
False,
1229 'true':
True,
'false':
False,
1242 def __init__(self, infile=None, options=None, configspec=None, encoding=None,
1243 interpolation=True, raise_errors=False, list_values=True,
1244 create_empty=False, file_error=False, stringify=True,
1245 indent_type=None, default_encoding=None, unrepr=False,
1246 write_empty_values=False, _inspec=False):
1249 Section.__init__(self, self, 0, self)
1251 infile = infile
or []
1256 _options = {
'configspec': configspec,
1257 'encoding': encoding,
'interpolation': interpolation,
1258 'raise_errors': raise_errors,
'list_values': list_values,
1259 'create_empty': create_empty,
'file_error': file_error,
1260 'stringify': stringify,
'indent_type': indent_type,
1261 'default_encoding': default_encoding,
'unrepr': unrepr,
1262 'write_empty_values': write_empty_values}
1268 warnings.warn(
'Passing in an options dictionary to ConfigObj() is '
1269 'deprecated. Use **options instead.',
1270 DeprecationWarning, stacklevel=2)
1273 for entry
in options:
1274 if entry
not in OPTION_DEFAULTS:
1275 raise TypeError(
'Unrecognised option "%s".' % entry)
1276 for entry, value
in list(OPTION_DEFAULTS.items()):
1277 if entry
not in options:
1278 options[entry] = value
1279 keyword_value = _options[entry]
1280 if value != keyword_value:
1281 options[entry] = keyword_value
1286 options[
'list_values'] =
False
1289 configspec = options[
'configspec']
1291 self.
_load_load(infile, configspec)
1295 if isinstance(infile, six.string_types):
1297 if os.path.isfile(infile):
1298 with open(infile,
'rb')
as h:
1299 content = h.readlines()
or []
1308 with open(infile,
'w')
as h:
1312 elif isinstance(infile, (list, tuple)):
1313 content = list(infile)
1315 elif isinstance(infile, dict):
1318 if isinstance(infile, ConfigObj):
1320 def set_section(in_section, this_section):
1321 for entry
in in_section.scalars:
1322 this_section[entry] = in_section[entry]
1323 for section
in in_section.sections:
1324 this_section[section] = {}
1325 set_section(in_section[section], this_section[section])
1326 set_section(infile, self)
1329 for entry
in infile:
1330 self[entry] = infile[entry]
1333 if configspec
is not None:
1339 elif getattr(infile,
'read', MISSING)
is not MISSING:
1341 content = infile.read()
or []
1345 raise TypeError(
'infile must be a filename, file like object, or list of lines.')
1354 for line
in content:
1355 if (
not line)
or (line[-1]
not in (
'\r',
'\n')):
1357 for end
in (
'\r\n',
'\n',
'\r'):
1358 if line.endswith(end):
1363 assert all(isinstance(line, six.string_types)
for line
in content), repr(content)
1364 content = [line.rstrip(
'\r\n')
for line
in content]
1366 self.
_parse_parse(content)
1369 info =
"at line %s." % self.
_errors_errors[0].line_number
1370 if len(self.
_errors_errors) > 1:
1371 msg =
"Parsing failed with several errors.\nFirst error %s" % info
1374 error = self.
_errors_errors[0]
1377 error.errors = self.
_errors_errors
1384 if configspec
is None:
1392 options = OPTION_DEFAULTS
1419 Section._initialise(self)
1426 except MissingInterpolationOption:
1427 return dict.__getitem__(self, key)
1428 return (
'ConfigObj({%s})' %
1429 ', '.join([(
'%s: %s' % (repr(key), repr(_getval(key))))
1458 if ((self.
encodingencoding
is not None)
and
1465 if isinstance(infile, (list, tuple)):
1470 if isinstance(line, six.text_type):
1476 if self.
encodingencoding
is not None:
1484 for BOM, (encoding, final_encoding)
in list(BOMS.items()):
1485 if not final_encoding:
1488 if infile.startswith(BOM):
1492 return self.
_decode_decode(infile, encoding)
1500 if not line.startswith(BOM):
1503 newline = line[len(BOM):]
1506 if isinstance(infile, (list, tuple)):
1514 for BOM, (encoding, final_encoding)
in list(BOMS.items()):
1515 if not isinstance(line, six.binary_type)
or not line.startswith(BOM):
1520 self.
encodingencoding = final_encoding
1521 if not final_encoding:
1525 newline = line[len(BOM):]
1526 if isinstance(infile, (list, tuple)):
1531 if isinstance(infile, six.text_type):
1532 return infile.splitlines(
True)
1533 elif isinstance(infile, six.binary_type):
1534 return infile.decode(
'utf-8').splitlines(
True)
1536 return self.
_decode_decode(infile,
'utf-8')
1538 return self.
_decode_decode(infile, encoding)
1541 if six.PY2
and isinstance(line, str):
1544 return self.
_decode_decode(infile,
None)
1546 if isinstance(infile, six.binary_type):
1547 return infile.decode(
'utf-8').splitlines(
True)
1549 return self.
_decode_decode(infile,
'utf-8')
1556 if isinstance(aString, six.binary_type)
and self.
encodingencoding:
1557 return aString.decode(self.
encodingencoding)
1570 if isinstance(infile, six.string_types):
1571 return infile.splitlines(
True)
1572 if isinstance(infile, six.binary_type):
1575 return infile.decode(encoding).splitlines(
True)
1577 return infile.splitlines(
True)
1580 for i, line
in enumerate(infile):
1581 if isinstance(line, six.binary_type):
1585 infile[i] = line.decode(encoding)
1593 if isinstance(line, six.binary_type)
and self.
default_encodingdefault_encoding:
1607 if not isinstance(value, six.string_types):
1626 maxline = len(infile) - 1
1628 reset_comment =
False
1630 while cur_index < maxline:
1634 line = infile[cur_index]
1635 sline = line.strip()
1637 if not sline
or sline.startswith(
'#'):
1638 reset_comment =
False
1639 comment_list.append(line)
1648 reset_comment =
True
1653 (indent, sect_open, sect_name, sect_close, comment) = mat.groups()
1654 if indent
and (self.
indent_typeindent_type
is None):
1656 cur_depth = sect_open.count(
'[')
1657 if cur_depth != sect_close.count(
']'):
1658 self.
_handle_error_handle_error(
"Cannot compute the section depth",
1659 NestingError, infile, cur_index)
1662 if cur_depth < this_section.depth:
1668 self.
_handle_error_handle_error(
"Cannot compute nesting level",
1669 NestingError, infile, cur_index)
1671 elif cur_depth == this_section.depth:
1673 parent = this_section.parent
1674 elif cur_depth == this_section.depth + 1:
1676 parent = this_section
1679 NestingError, infile, cur_index)
1682 sect_name = self.
_unquote_unquote(sect_name)
1683 if sect_name
in parent:
1685 DuplicateError, infile, cur_index)
1694 parent[sect_name] = this_section
1695 parent.inline_comments[sect_name] = comment
1696 parent.comments[sect_name] = comment_list
1701 mat = self.
_keyword_keyword.match(line)
1704 'Invalid line ({0!r}) (matched as neither section nor keyword)'.format(line),
1705 ParseError, infile, cur_index)
1709 (indent, key, value) = mat.groups()
1710 if indent
and (self.
indent_typeindent_type
is None):
1713 if value[:3]
in [
'"""',
"'''"]:
1715 value, comment, cur_index = self.
_multiline_multiline(
1716 value, infile, cur_index, maxline)
1719 'Parse error in multiline value',
1720 ParseError, infile, cur_index)
1727 except Exception
as e:
1728 if type(e) == UnknownType:
1729 msg =
'Unknown name or type in value'
1731 msg =
'Parse error from unrepr-ing multiline value'
1740 except Exception
as e:
1741 if isinstance(e, UnknownType):
1742 msg =
'Unknown name or type in value'
1744 msg =
'Parse error from unrepr-ing value'
1754 'Parse error in value',
1755 ParseError, infile, cur_index)
1759 if key
in this_section:
1761 'Duplicate keyword name',
1762 DuplicateError, infile, cur_index)
1767 this_section.__setitem__(key, value, unrepr=
True)
1768 this_section.inline_comments[key] = comment
1769 this_section.comments[key] = comment_list
1779 elif not reset_comment:
1794 while depth < sect.depth:
1795 if sect
is sect.parent:
1799 if sect.depth == depth:
1814 line = infile[cur_index]
1816 message =
'{0} at line {1}.'.format(text, cur_index)
1817 error = ErrorClass(message, cur_index, line)
1823 self.
_errors_errors.append(error)
1833 if (value[0] == value[-1])
and (value[0]
in (
'"',
"'")):
1864 if multiline
and isinstance(value, (list, tuple)):
1867 elif len(value) == 1:
1868 return self.
_quote_quote(value[0], multiline=
False) +
','
1869 return ', '.join([self.
_quote_quote(val, multiline=
False)
1871 if not isinstance(value, six.string_types):
1877 raise TypeError(
'Value "%s" is not a string.' % value)
1882 no_lists_no_quotes =
not self.
list_valueslist_values
and '\n' not in value
and '#' not in value
1883 need_triple = multiline
and (((
"'" in value)
and (
'"' in value))
or (
'\n' in value ))
1884 hash_triple_quote = multiline
and not need_triple
and (
"'" in value)
and (
'"' in value)
and (
'#' in value)
1885 check_for_single = (no_lists_no_quotes
or not need_triple)
and not hash_triple_quote
1887 if check_for_single:
1894 raise ConfigObjError(
'Value "%s" cannot be safely quoted.' % value)
1895 elif ((value[0]
not in wspace_plus)
and
1896 (value[-1]
not in wspace_plus)
and
1897 (
',' not in value)):
1905 if quot == noquot
and '#' in value
and self.
list_valueslist_values:
1912 if (
"'" in value)
and (
'"' in value):
1913 raise ConfigObjError(
'Value "%s" cannot be safely quoted.' % value)
1922 if (value.find(
'"""') != -1)
and (value.find(
"'''") != -1):
1923 raise ConfigObjError(
'Value "%s" cannot be safely quoted.' % value)
1924 if value.find(
'"""') == -1:
1949 mat = self.
_valueexp_valueexp.match(value)
1954 (list_values, single, empty_list, comment) = mat.groups()
1955 if (list_values ==
'')
and (single
is None):
1960 if empty_list
is not None:
1962 return ([], comment)
1963 if single
is not None:
1965 if list_values
and not single:
1970 single = single
or '""'
1971 single = self.
_unquote_unquote(single)
1972 if list_values ==
'':
1974 return (single, comment)
1975 the_list = self.
_listvalueexp_listvalueexp.findall(list_values)
1976 the_list = [self.
_unquote_unquote(val)
for val
in the_list]
1977 if single
is not None:
1978 the_list += [single]
1979 return (the_list, comment)
1987 newvalue = value[3:]
1990 mat = single_line.match(value)
1992 retval = list(mat.groups())
1993 retval.append(cur_index)
1995 elif newvalue.find(quot) != -1:
1999 while cur_index < maxline:
2002 line = infile[cur_index]
2003 if line.find(quot) == -1:
2011 mat = multi_line.match(line)
2015 (value, comment) = mat.groups()
2016 return (newvalue + value, comment, cur_index)
2025 if not isinstance(configspec, ConfigObj):
2031 except ConfigObjError
as e:
2035 except IOError
as e:
2036 raise IOError(
'Reading configspec failed: %s' % e)
2049 configspec = section.configspec
2050 many = configspec.get(
'__many__')
2051 if isinstance(many, dict):
2052 for entry
in section.sections:
2053 if entry
not in configspec:
2054 section[entry].configspec = many
2056 for entry
in configspec.sections:
2057 if entry ==
'__many__':
2059 if entry
not in section:
2061 section[entry]._created =
True
2064 section.comments[entry] = configspec.comments.get(entry, [])
2065 section.inline_comments[entry] = configspec.inline_comments.get(entry,
'')
2068 if isinstance(section[entry], Section):
2069 section[entry].configspec = configspec[entry]
2077 if not self.
unreprunrepr:
2080 val = repr(this_entry)
2081 return '%s%s%s%s%s' % (indent_string,
2092 return '%s%s%s%s%s' % (indent_string,
2093 self.
_a_to_u_a_to_u(
'[' * depth),
2095 self.
_a_to_u_a_to_u(
']' * depth),
2106 if not comment.startswith(
'#'):
2107 start += self.
_a_to_u_a_to_u(
' # ')
2108 return (start + comment)
2127 def write(self, outfile=None, section=None):
2134 csp = self.
_a_to_u_a_to_u(
'# ')
2141 stripped_line = line.strip()
2142 if stripped_line
and not stripped_line.startswith(cs):
2146 indent_string = self.
indent_typeindent_type * section.depth
2147 for entry
in (section.scalars + section.sections):
2148 if entry
in section.defaults:
2151 for comment_line
in section.comments[entry]:
2152 comment_line = self.
_decode_element_decode_element(comment_line.lstrip())
2153 if comment_line
and not comment_line.startswith(cs):
2154 comment_line = csp + comment_line
2155 out.append(indent_string + comment_line)
2156 this_entry = section[entry]
2157 comment = self.
_handle_comment_handle_comment(section.inline_comments[entry])
2159 if isinstance(this_entry, Section):
2166 out.extend(self.
writewrite(section=this_entry))
2177 stripped_line = line.strip()
2178 if stripped_line
and not stripped_line.startswith(cs):
2183 if section
is not self:
2186 if (self.
filenamefilename
is None)
and (outfile
is None):
2191 out = [l.encode(self.
encodingencoding)
for l
in out]
2192 if (self.
BOMBOM
and ((self.
encodingencoding
is None)
or
2197 out[0] = BOM_UTF8 + out[0]
2201 newline = self.
newlinesnewlines
or os.linesep
2202 if (getattr(outfile,
'mode',
None)
is not None and outfile.mode ==
'w'
2203 and sys.platform ==
'win32' and newline ==
'\r\n'):
2206 output = self.
_a_to_u_a_to_u(newline).join(out)
2207 if not output.endswith(newline):
2210 if isinstance(output, six.binary_type):
2211 output_bytes = output
2213 output_bytes = output.encode(self.
encodingencoding
or
2220 output_bytes = BOM_UTF8 + output_bytes
2222 if outfile
is not None:
2223 outfile.write(output_bytes)
2225 with open(self.
filenamefilename,
'wb')
as h:
2226 h.write(output_bytes)
2262 def validate(self, validator, preserve_errors=False, copy=False,
2266 raise ValueError(
'No configspec supplied.')
2270 from validate
import VdtMissingValue
2276 section.initial_comment = section.configspec.initial_comment
2277 section.final_comment = section.configspec.final_comment
2278 section.encoding = section.configspec.encoding
2279 section.BOM = section.configspec.BOM
2280 section.newlines = section.configspec.newlines
2281 section.indent_type = section.configspec.indent_type
2285 configspec = section.configspec
2289 def validate_entry(entry, spec, val, missing, ret_true, ret_false):
2290 section.default_values.pop(entry,
None)
2293 section.default_values[entry] = validator.get_default_value(configspec[entry])
2294 except (KeyError, AttributeError, validator.baseErrorClass):
2300 check = validator.check(spec,
2304 except validator.baseErrorClass
as e:
2305 if not preserve_errors
or isinstance(e, self.
_vdtMissingValue_vdtMissingValue):
2319 if isinstance(check, (list, tuple)):
2321 check = [self.
_str_str(item)
for item
in check]
2322 elif missing
and check
is None:
2326 check = self.
_str_str(check)
2327 if (check != val)
or missing:
2328 section[entry] = check
2329 if not copy
and missing
and entry
not in section.defaults:
2330 section.defaults.append(entry)
2331 return ret_true, ret_false
2338 unvalidated = [k
for k
in section.scalars
if k
not in configspec]
2339 incorrect_sections = [k
for k
in configspec.sections
if k
in section.scalars]
2340 incorrect_scalars = [k
for k
in configspec.scalars
if k
in section.sections]
2342 for entry
in configspec.scalars:
2343 if entry
in (
'__many__',
'___many___'):
2346 if (
not entry
in section.scalars)
or (entry
in section.defaults):
2351 if copy
and entry
not in section.scalars:
2353 section.comments[entry] = (
2354 configspec.comments.get(entry, []))
2355 section.inline_comments[entry] = (
2356 configspec.inline_comments.get(entry,
''))
2360 val = section[entry]
2362 ret_true, ret_false = validate_entry(entry, configspec[entry], val,
2363 missing, ret_true, ret_false)
2366 if '__many__' in configspec.scalars:
2367 many = configspec[
'__many__']
2368 elif '___many___' in configspec.scalars:
2369 many = configspec[
'___many___']
2371 if many
is not None:
2372 for entry
in unvalidated:
2373 val = section[entry]
2374 ret_true, ret_false = validate_entry(entry, many, val,
False,
2375 ret_true, ret_false)
2378 for entry
in incorrect_scalars:
2380 if not preserve_errors:
2384 msg =
'Value %r was provided as a section' % entry
2385 out[entry] = validator.baseErrorClass(msg)
2386 for entry
in incorrect_sections:
2388 if not preserve_errors:
2392 msg =
'Section %r was provided as a single value' % entry
2393 out[entry] = validator.baseErrorClass(msg)
2397 for entry
in section.sections:
2399 if section
is self
and entry ==
'DEFAULT':
2401 if section[entry].configspec
is None:
2402 unvalidated.append(entry)
2405 section.comments[entry] = configspec.comments.get(entry, [])
2406 section.inline_comments[entry] = configspec.inline_comments.get(entry,
'')
2407 check = self.
validatevalidate(validator, preserve_errors=preserve_errors, copy=copy, section=section[entry])
2416 section.extra_values = unvalidated
2417 if preserve_errors
and not section._created:
2422 if ret_false
and preserve_errors
and out:
2427 ret_false =
not any(out.values())
2453 if not isinstance(self.
filenamefilename, six.string_types):
2457 current_options = {}
2458 for entry
in OPTION_DEFAULTS:
2459 if entry ==
'configspec':
2461 current_options[entry] = getattr(self, entry)
2464 current_options[
'configspec'] = configspec
2468 self.
_load_load(filename, configspec)
2487 def check(self, check, member, missing=False):
2530 return sorted(results)
2531 if res ==
False or isinstance(res, Exception):
2532 results.append((levels[:],
None, res))
2535 return sorted(results)
2536 for (key, val)
in list(res.items()):
2539 if isinstance(cfg.get(key), dict):
2544 results.append((levels[:], key, val))
2550 return sorted(results)
2572 out.extend([(_prepend, name)
for name
in conf.extra_values])
2573 for name
in conf.sections:
2574 if name
not in conf.extra_values:
2579 """*A programming language is a medium of expression.* - Paul Graham"""
def build_UnarySub(self, o)
def build_Getattr(self, o)
def build_UnaryAdd(self, o)
This is the base class for all errors that ConfigObj raises.
def __init__(self, message='', line_number=None, line='')
An object to read, create, and write config files.
def write(self, outfile=None, section=None)
Write the current ConfigObj as a file.
def _handle_error(self, text, ErrorClass, infile, cur_index)
def reset(self)
Clear ConfigObj instance and restore to 'freshly created' state.
def __repr__(self)
x.__repr__() <==> repr(x)
def _decode_element(self, line)
Decode element to unicode if necessary.
def _decode(self, infile, encoding)
def _write_marker(self, indent_string, depth, entry, comment)
Write a section marker line.
def _set_configspec(self, section, copy)
def _match_depth(self, sect, depth)
def _a_to_u(self, aString)
Decode ASCII strings to unicode if a self.encoding is specified.
BOM
BOM discovered self.BOM = True Don't need to remove BOM.
def _multiline(self, value, infile, cur_index, maxline)
Extract the value, where we are in a multiline situation.
def _handle_comment(self, comment)
Deal with a comment.
def _handle_bom(self, infile)
def _handle_value(self, value)
def validate(self, validator, preserve_errors=False, copy=False, section=None)
Test the ConfigObj against a configspec.
def _get_triple_quote(self, value)
def _get_single_quote(self, value)
def _quote(self, value, multiline=True)
def _initialise(self, options=None)
def reload(self)
Reload a ConfigObj from file.
def _parse(self, infile)
Actually parse the config file.
def _handle_configspec(self, configspec)
Parse the configspec.
def _write_line(self, indent_string, entry, this_entry, comment)
Write an individual line, for the write method.
def __init__(self, infile=None, options=None, configspec=None, encoding=None, interpolation=True, raise_errors=False, list_values=True, create_empty=False, file_error=False, stringify=True, indent_type=None, default_encoding=None, unrepr=False, write_empty_values=False, _inspec=False)
Parse a config file or create a config file object.
def _load(self, infile, configspec)
def _unquote(self, value)
Return an unquoted version of a value.
Behaves like ConfigParser.
def _parse_match(self, match)
Implementation-dependent helper function.
Base class for the two interpolation errors.
The keyword or section specified already exists.
def __init__(self, section)
def _fetch(self, key)
Helper function to fetch values from owning section.
def interpolate(self, key, value)
def _parse_match(self, match)
Implementation-dependent helper function.
Maximum interpolation depth exceeded in string interpolation.
def __init__(self, option)
def __init__(self, option)
This error indicates a level of nesting that doesn't match.
A 'reload' operation failed.
This error indicates additional sections in a section with a __many__ (repeated) section.
A dictionary-like object that represents a section in a config file.
def setdefault(self, key, default=None)
A version of setdefault that sets sequence if appropriate.
def as_int(self, key)
A convenience method which coerces the specified value to an integer.
def iteritems(self)
D.iteritems() -> an iterator over the (key, value) items of D.
def iterkeys(self)
D.iterkeys() -> an iterator over the keys of D.
def __init__(self, parent, depth, main, indict=None, name=None)
def update(self, indict)
A version of update that uses our __setitem__.
def popitem(self)
Pops the first (key,val)
def clear(self)
A version of clear that also affects scalars/sections Also clears comments and configspec.
def __setitem__(self, key, value, unrepr=False)
Correctly set a value.
def restore_default(self, key)
Restore (and return) default value for the specified key.
def dict(self)
Return a deepcopy of self as a dictionary.
def keys(self)
D.keys() -> list of D's keys.
def pop(self, key, default=MISSING)
'D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
def itervalues(self)
D.itervalues() -> an iterator over the values of D.
def restore_defaults(self)
Recursively restore default values to all members that have them.
def rename(self, oldkey, newkey)
Change a keyname to another, without changing position in sequence.
def merge(self, indict)
A recursive update - useful for merging config files.
def values(self)
D.values() -> list of D's values.
def get(self, key, default=None)
A version of get that doesn't bypass string interpolation.
def walk(self, function, raise_errors=True, call_on_sections=False, **keywargs)
Walk every member and call a function on the keyword and value.
def as_bool(self, key)
Accepts a key as input.
def __delitem__(self, key)
Remove items from the sequence when deleting.
def items(self)
D.items() -> list of D's (key, value) pairs, as 2-tuples.
def __repr__(self)
x.__repr__() <==> repr(x)
def as_float(self, key)
A convenience method which coerces the specified value to a float.
def __getitem__(self, key)
Fetch the item and do string interpolation.
def __setstate__(self, state)
def as_list(self, key)
A convenience method which fetches the specified value, guaranteeing that it is a list.
def _interpolate(self, key, value)
def check(self, check, member, missing=False)
A dummy check method, always returns the value unchanged.
Behaves like string.Template.
def _parse_match(self, match)
Implementation-dependent helper function.
An error parsing in unrepr mode.
def __newobj__(cls, *args)
def get_extra_values(conf, _prepend=())
Find all the values and sections not in the configspec from a validated ConfigObj.
def flatten_errors(cfg, res, levels=None, results=None)
An example function that will turn a nested dictionary of results (as returned by ConfigObj....