1
"""Configuration file parser.
3
A setup file consists of sections, lead by a "[section]" header,
4
and followed by "name: value" entries, with continuations and such in
7
The option values can contain format strings which refer to other values in
8
the same section, or values in a special [DEFAULT] section.
12
something: %(dir)s/whatever
14
would resolve the "%(dir)s" to the value of dir. All reference
15
expansions are done late, on demand.
17
Intrinsic defaults can be specified by passing them into the
18
ConfigParser constructor as a dictionary.
22
ConfigParser -- responsible for parsing a list of
23
configuration files, and managing the parsed database.
27
__init__(defaults=None)
28
create the parser and specify a dictionary of intrinsic defaults. The
29
keys must be strings, the values must be appropriate for %()s string
30
interpolation. Note that `__name__' is always an intrinsic default;
31
its value is the section's name.
34
return all the configuration section names, sans DEFAULT
37
return whether the given section exists
39
has_option(section, option)
40
return whether the given option exists in the given section
43
return list of configuration options for the named section
46
read and parse the list of named configuration files, given by
47
name. A single filename is also allowed. Non-existing files
48
are ignored. Return list of successfully read files.
50
readfp(fp, filename=None)
51
read and parse one configuration file, given as a file object.
52
The filename defaults to fp.name; it is only used in error
53
messages (if fp has no `name' attribute, the string `<???>' is used).
55
get(section, option, raw=False, vars=None)
56
return a string value for the named option. All % interpolations are
57
expanded in the return values, based on the defaults passed into the
58
constructor and the DEFAULT section. Additional substitutions may be
59
provided using the `vars' argument, which must be a dictionary whose
60
contents override any pre-existing defaults.
62
getint(section, options)
63
like get(), but convert value to an integer
65
getfloat(section, options)
66
like get(), but convert value to a float
68
getboolean(section, options)
69
like get(), but convert value to a boolean (currently case
70
insensitively defined as 0, false, no, off for False, and 1, true,
71
yes, on for True). Returns False or True.
73
items(section, raw=False, vars=None)
74
return a list of tuples with (name, value) for each option
77
remove_section(section)
78
remove the given file section and all its options
80
remove_option(section, option)
81
remove the given option from the given section
83
set(section, option, value)
87
write the configuration state in .ini format
92
__all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError",
93
"InterpolationError", "InterpolationDepthError",
94
"InterpolationSyntaxError", "ParsingError",
95
"MissingSectionHeaderError",
96
"ConfigParser", "SafeConfigParser", "RawConfigParser",
97
"DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
99
DEFAULTSECT = "DEFAULT"
101
MAX_INTERPOLATION_DEPTH = 10
106
class Error(Exception):
107
"""Base class for ConfigParser exceptions."""
109
def _get_message(self):
110
"""Getter for 'message'; needed only to override deprecation in
112
return self.__message
114
def _set_message(self, value):
115
"""Setter for 'message'; needed only to override deprecation in
117
self.__message = value
119
# BaseException.message has been deprecated since Python 2.6. To prevent
120
# DeprecationWarning from popping up over this pre-existing attribute, use
121
# a new property that takes lookup precedence.
122
message = property(_get_message, _set_message)
124
def __init__(self, msg=''):
126
Exception.__init__(self, msg)
133
class NoSectionError(Error):
134
"""Raised when no section matches a requested option."""
136
def __init__(self, section):
137
Error.__init__(self, 'No section: %r' % (section,))
138
self.section = section
140
class DuplicateSectionError(Error):
141
"""Raised when a section is multiply-created."""
143
def __init__(self, section):
144
Error.__init__(self, "Section %r already exists" % section)
145
self.section = section
147
class NoOptionError(Error):
148
"""A requested option was not found."""
150
def __init__(self, option, section):
151
Error.__init__(self, "No option %r in section: %r" %
154
self.section = section
156
class InterpolationError(Error):
157
"""Base class for interpolation-related exceptions."""
159
def __init__(self, option, section, msg):
160
Error.__init__(self, msg)
162
self.section = section
164
class InterpolationMissingOptionError(InterpolationError):
165
"""A string substitution required a setting which was not available."""
167
def __init__(self, option, section, rawval, reference):
168
msg = ("Bad value substitution:\n"
173
% (section, option, reference, rawval))
174
InterpolationError.__init__(self, option, section, msg)
175
self.reference = reference
177
class InterpolationSyntaxError(InterpolationError):
178
"""Raised when the source text into which substitutions are made
179
does not conform to the required syntax."""
181
class InterpolationDepthError(InterpolationError):
182
"""Raised when substitutions are nested too deeply."""
184
def __init__(self, option, section, rawval):
185
msg = ("Value interpolation too deeply recursive:\n"
189
% (section, option, rawval))
190
InterpolationError.__init__(self, option, section, msg)
192
class ParsingError(Error):
193
"""Raised when a configuration file does not follow legal syntax."""
195
def __init__(self, filename):
196
Error.__init__(self, 'File contains parsing errors: %s' % filename)
197
self.filename = filename
200
def append(self, lineno, line):
201
self.errors.append((lineno, line))
202
self.message += '\n\t[line %2d]: %s' % (lineno, line)
204
class MissingSectionHeaderError(ParsingError):
205
"""Raised when a key-value pair is found before any section header."""
207
def __init__(self, filename, lineno, line):
210
'File contains no section headers.\nfile: %s, line: %d\n%r' %
211
(filename, lineno, line))
212
self.filename = filename
217
class RawConfigParser:
218
def __init__(self, defaults=None, dict_type=dict):
219
self._dict = dict_type
220
self._sections = self._dict()
221
self._defaults = self._dict()
223
for key, value in defaults.items():
224
self._defaults[self.optionxform(key)] = value
227
return self._defaults
230
"""Return a list of section names, excluding [DEFAULT]"""
231
# self._sections will never have [DEFAULT] in it
232
return self._sections.keys()
234
def add_section(self, section):
235
"""Create a new section in the configuration.
237
Raise DuplicateSectionError if a section by the specified name
238
already exists. Raise ValueError if name is DEFAULT or any of it's
239
case-insensitive variants.
241
if section.lower() == "default":
242
raise ValueError, 'Invalid section name: %s' % section
244
if section in self._sections:
245
raise DuplicateSectionError(section)
246
self._sections[section] = self._dict()
248
def has_section(self, section):
249
"""Indicate whether the named section is present in the configuration.
251
The DEFAULT section is not acknowledged.
253
return section in self._sections
255
def options(self, section):
256
"""Return a list of option names for the given section name."""
258
opts = self._sections[section].copy()
260
raise NoSectionError(section)
261
opts.update(self._defaults)
262
if '__name__' in opts:
266
def read(self, filenames):
267
"""Read and parse a filename or a list of filenames.
269
Files that cannot be opened are silently ignored; this is
270
designed so that you can specify a list of potential
271
configuration file locations (e.g. current directory, user's
272
home directory, systemwide directory), and all existing
273
configuration files in the list will be read. A single
274
filename may also be given.
276
Return list of successfully read files.
278
if isinstance(filenames, basestring):
279
filenames = [filenames]
281
for filename in filenames:
286
self._read(fp, filename)
288
read_ok.append(filename)
291
def readfp(self, fp, filename=None):
292
"""Like read() but the argument must be a file-like object.
294
The `fp' argument must have a `readline' method. Optional
295
second argument is the `filename', which if not given, is
296
taken from fp.name. If fp has no `name' attribute, `<???>' is
303
except AttributeError:
305
self._read(fp, filename)
307
def get(self, section, option):
308
opt = self.optionxform(option)
309
if section not in self._sections:
310
if section != DEFAULTSECT:
311
raise NoSectionError(section)
312
if opt in self._defaults:
313
return self._defaults[opt]
315
raise NoOptionError(option, section)
316
elif opt in self._sections[section]:
317
return self._sections[section][opt]
318
elif opt in self._defaults:
319
return self._defaults[opt]
321
raise NoOptionError(option, section)
323
def items(self, section):
325
d2 = self._sections[section]
327
if section != DEFAULTSECT:
328
raise NoSectionError(section)
330
d = self._defaults.copy()
336
def _get(self, section, conv, option):
337
return conv(self.get(section, option))
339
def getint(self, section, option):
340
return self._get(section, int, option)
342
def getfloat(self, section, option):
343
return self._get(section, float, option)
345
_boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
346
'0': False, 'no': False, 'false': False, 'off': False}
348
def getboolean(self, section, option):
349
v = self.get(section, option)
350
if v.lower() not in self._boolean_states:
351
raise ValueError, 'Not a boolean: %s' % v
352
return self._boolean_states[v.lower()]
354
def optionxform(self, optionstr):
355
return optionstr.lower()
357
def has_option(self, section, option):
358
"""Check for the existence of a given option in a given section."""
359
if not section or section == DEFAULTSECT:
360
option = self.optionxform(option)
361
return option in self._defaults
362
elif section not in self._sections:
365
option = self.optionxform(option)
366
return (option in self._sections[section]
367
or option in self._defaults)
369
def set(self, section, option, value):
371
if not section or section == DEFAULTSECT:
372
sectdict = self._defaults
375
sectdict = self._sections[section]
377
raise NoSectionError(section)
378
sectdict[self.optionxform(option)] = value
381
"""Write an .ini-format representation of the configuration state."""
383
fp.write("[%s]\n" % DEFAULTSECT)
384
for (key, value) in self._defaults.items():
385
fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
387
for section in self._sections:
388
fp.write("[%s]\n" % section)
389
for (key, value) in self._sections[section].items():
390
if key != "__name__":
391
fp.write("%s = %s\n" %
392
(key, str(value).replace('\n', '\n\t')))
395
def remove_option(self, section, option):
396
"""Remove an option."""
397
if not section or section == DEFAULTSECT:
398
sectdict = self._defaults
401
sectdict = self._sections[section]
403
raise NoSectionError(section)
404
option = self.optionxform(option)
405
existed = option in sectdict
410
def remove_section(self, section):
411
"""Remove a file section."""
412
existed = section in self._sections
414
del self._sections[section]
418
# Regular expressions for parsing section headers and options.
420
SECTCRE = re.compile(
422
r'(?P<header>[^]]+)' # very permissive!
426
r'(?P<option>[^:=\s][^:=]*)' # very permissive!
427
r'\s*(?P<vi>[:=])\s*' # any number of space/tab,
428
# followed by separator
429
# (either : or =), followed
431
r'(?P<value>.*)$' # everything up to eol
434
def _read(self, fp, fpname):
435
"""Parse a sectioned setup file.
437
The sections in setup file contains a title line at the top,
438
indicated by a name in square brackets (`[]'), plus key/value
439
options lines, indicated by `name: value' format lines.
440
Continuations are represented by an embedded newline then
441
leading whitespace. Blank lines, lines beginning with a '#',
442
and just about everything else are ignored.
444
cursect = None # None, or a dictionary
447
e = None # None, or an exception
453
# comment or blank line?
454
if line.strip() == '' or line[0] in '#;':
456
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
457
# no leading whitespace
460
if line[0].isspace() and cursect is not None and optname:
463
cursect[optname] = "%s\n%s" % (cursect[optname], value)
464
# a section header or option header?
466
# is it a section header?
467
mo = self.SECTCRE.match(line)
469
sectname = mo.group('header')
470
if sectname in self._sections:
471
cursect = self._sections[sectname]
472
elif sectname == DEFAULTSECT:
473
cursect = self._defaults
475
cursect = self._dict()
476
cursect['__name__'] = sectname
477
self._sections[sectname] = cursect
478
# So sections can't start with a continuation line
480
# no section header in the file?
481
elif cursect is None:
482
raise MissingSectionHeaderError(fpname, lineno, line)
485
mo = self.OPTCRE.match(line)
487
optname, vi, optval = mo.group('option', 'vi', 'value')
488
if vi in ('=', ':') and ';' in optval:
489
# ';' is a comment delimiter only if it follows
490
# a spacing character
491
pos = optval.find(';')
492
if pos != -1 and optval[pos-1].isspace():
493
optval = optval[:pos]
494
optval = optval.strip()
498
optname = self.optionxform(optname.rstrip())
499
cursect[optname] = optval
501
# a non-fatal parsing error occurred. set up the
502
# exception but keep going. the exception will be
503
# raised at the end of the file and will contain a
504
# list of all bogus lines
506
e = ParsingError(fpname)
507
e.append(lineno, repr(line))
508
# if any parsing errors occurred, raise an exception
513
class ConfigParser(RawConfigParser):
515
def get(self, section, option, raw=False, vars=None):
516
"""Get an option value for a given section.
518
All % interpolations are expanded in the return values, based on the
519
defaults passed into the constructor, unless the optional argument
520
`raw' is true. Additional substitutions may be provided using the
521
`vars' argument, which must be a dictionary whose contents overrides
522
any pre-existing defaults.
524
The section DEFAULT is special.
526
d = self._defaults.copy()
528
d.update(self._sections[section])
530
if section != DEFAULTSECT:
531
raise NoSectionError(section)
532
# Update with the entry specific variables
534
for key, value in vars.items():
535
d[self.optionxform(key)] = value
536
option = self.optionxform(option)
540
raise NoOptionError(option, section)
545
return self._interpolate(section, option, value, d)
547
def items(self, section, raw=False, vars=None):
548
"""Return a list of tuples with (name, value) for each option
551
All % interpolations are expanded in the return values, based on the
552
defaults passed into the constructor, unless the optional argument
553
`raw' is true. Additional substitutions may be provided using the
554
`vars' argument, which must be a dictionary whose contents overrides
555
any pre-existing defaults.
557
The section DEFAULT is special.
559
d = self._defaults.copy()
561
d.update(self._sections[section])
563
if section != DEFAULTSECT:
564
raise NoSectionError(section)
565
# Update with the entry specific variables
567
for key, value in vars.items():
568
d[self.optionxform(key)] = value
570
if "__name__" in options:
571
options.remove("__name__")
573
return [(option, d[option])
574
for option in options]
576
return [(option, self._interpolate(section, option, d[option], d))
577
for option in options]
579
def _interpolate(self, section, option, rawval, vars):
580
# do the string interpolation
582
depth = MAX_INTERPOLATION_DEPTH
583
while depth: # Loop through this until it's done
586
value = self._KEYCRE.sub(self._interpolation_replace, value)
590
raise InterpolationMissingOptionError(
591
option, section, rawval, e[0])
595
raise InterpolationDepthError(option, section, rawval)
598
_KEYCRE = re.compile(r"%\(([^)]*)\)s|.")
600
def _interpolation_replace(self, match):
605
return "%%(%s)s" % self.optionxform(s)
608
class SafeConfigParser(ConfigParser):
610
def _interpolate(self, section, option, rawval, vars):
611
# do the string interpolation
613
self._interpolate_some(option, L, rawval, section, vars, 1)
616
_interpvar_re = re.compile(r"%\(([^)]+)\)s")
617
_badpercent_re = re.compile(r"%[^%]|%$")
619
def _interpolate_some(self, option, accum, rest, section, map, depth):
620
if depth > MAX_INTERPOLATION_DEPTH:
621
raise InterpolationDepthError(option, section, rest)
628
accum.append(rest[:p])
630
# p is no longer used
636
m = self._interpvar_re.match(rest)
638
raise InterpolationSyntaxError(option, section,
639
"bad interpolation variable reference %r" % rest)
640
var = self.optionxform(m.group(1))
641
rest = rest[m.end():]
645
raise InterpolationMissingOptionError(
646
option, section, rest, var)
648
self._interpolate_some(option, accum, v,
649
section, map, depth + 1)
653
raise InterpolationSyntaxError(
655
"'%%' must be followed by '%%' or '(', found: %r" % (rest,))
657
def set(self, section, option, value):
658
"""Set an option. Extend ConfigParser.set: check for string values."""
659
if not isinstance(value, basestring):
660
raise TypeError("option values must be strings")
661
# check for bad percent signs:
662
# first, replace all "good" interpolations
663
tmp_value = self._interpvar_re.sub('', value)
664
# then, check if there's a lone percent sign left
665
m = self._badpercent_re.search(tmp_value)
667
raise ValueError("invalid interpolation syntax in %r at "
668
"position %d" % (value, m.start()))
669
ConfigParser.set(self, section, option, value)