Patch by Jeremy Katz (SF #1609407)
[python.git] / Lib / ConfigParser.py
blob65c8ce557db21df6db8111f1ea0afe1dd1e2840d
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
5 the style of RFC 822.
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.
10 For example:
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.
20 class:
22 ConfigParser -- responsible for parsing a list of
23 configuration files, and managing the parsed database.
25 methods:
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.
33 sections()
34 return all the configuration section names, sans DEFAULT
36 has_section(section)
37 return whether the given section exists
39 has_option(section, option)
40 return whether the given option exists in the given section
42 options(section)
43 return list of configuration options for the named section
45 read(filenames)
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
75 in the section.
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)
84 set the given option
86 write(fp)
87 write the configuration state in .ini format
88 """
90 import re
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
105 # exception classes
106 class Error(Exception):
107 """Base class for ConfigParser exceptions."""
109 def __init__(self, msg=''):
110 self.message = msg
111 Exception.__init__(self, msg)
113 def __repr__(self):
114 return self.message
116 __str__ = __repr__
118 class NoSectionError(Error):
119 """Raised when no section matches a requested option."""
121 def __init__(self, section):
122 Error.__init__(self, 'No section: %r' % (section,))
123 self.section = section
125 class DuplicateSectionError(Error):
126 """Raised when a section is multiply-created."""
128 def __init__(self, section):
129 Error.__init__(self, "Section %r already exists" % section)
130 self.section = section
132 class NoOptionError(Error):
133 """A requested option was not found."""
135 def __init__(self, option, section):
136 Error.__init__(self, "No option %r in section: %r" %
137 (option, section))
138 self.option = option
139 self.section = section
141 class InterpolationError(Error):
142 """Base class for interpolation-related exceptions."""
144 def __init__(self, option, section, msg):
145 Error.__init__(self, msg)
146 self.option = option
147 self.section = section
149 class InterpolationMissingOptionError(InterpolationError):
150 """A string substitution required a setting which was not available."""
152 def __init__(self, option, section, rawval, reference):
153 msg = ("Bad value substitution:\n"
154 "\tsection: [%s]\n"
155 "\toption : %s\n"
156 "\tkey : %s\n"
157 "\trawval : %s\n"
158 % (section, option, reference, rawval))
159 InterpolationError.__init__(self, option, section, msg)
160 self.reference = reference
162 class InterpolationSyntaxError(InterpolationError):
163 """Raised when the source text into which substitutions are made
164 does not conform to the required syntax."""
166 class InterpolationDepthError(InterpolationError):
167 """Raised when substitutions are nested too deeply."""
169 def __init__(self, option, section, rawval):
170 msg = ("Value interpolation too deeply recursive:\n"
171 "\tsection: [%s]\n"
172 "\toption : %s\n"
173 "\trawval : %s\n"
174 % (section, option, rawval))
175 InterpolationError.__init__(self, option, section, msg)
177 class ParsingError(Error):
178 """Raised when a configuration file does not follow legal syntax."""
180 def __init__(self, filename):
181 Error.__init__(self, 'File contains parsing errors: %s' % filename)
182 self.filename = filename
183 self.errors = []
185 def append(self, lineno, line):
186 self.errors.append((lineno, line))
187 self.message += '\n\t[line %2d]: %s' % (lineno, line)
189 class MissingSectionHeaderError(ParsingError):
190 """Raised when a key-value pair is found before any section header."""
192 def __init__(self, filename, lineno, line):
193 Error.__init__(
194 self,
195 'File contains no section headers.\nfile: %s, line: %d\n%r' %
196 (filename, lineno, line))
197 self.filename = filename
198 self.lineno = lineno
199 self.line = line
202 class RawConfigParser:
203 def __init__(self, defaults=None, dict_type=dict):
204 self._dict = dict_type
205 self._sections = self._dict()
206 self._defaults = self._dict()
207 if defaults:
208 for key, value in defaults.items():
209 self._defaults[self.optionxform(key)] = value
211 def defaults(self):
212 return self._defaults
214 def sections(self):
215 """Return a list of section names, excluding [DEFAULT]"""
216 # self._sections will never have [DEFAULT] in it
217 return self._sections.keys()
219 def add_section(self, section):
220 """Create a new section in the configuration.
222 Raise DuplicateSectionError if a section by the specified name
223 already exists.
225 if section in self._sections:
226 raise DuplicateSectionError(section)
227 self._sections[section] = self._dict()
229 def has_section(self, section):
230 """Indicate whether the named section is present in the configuration.
232 The DEFAULT section is not acknowledged.
234 return section in self._sections
236 def options(self, section):
237 """Return a list of option names for the given section name."""
238 try:
239 opts = self._sections[section].copy()
240 except KeyError:
241 raise NoSectionError(section)
242 opts.update(self._defaults)
243 if '__name__' in opts:
244 del opts['__name__']
245 return opts.keys()
247 def read(self, filenames):
248 """Read and parse a filename or a list of filenames.
250 Files that cannot be opened are silently ignored; this is
251 designed so that you can specify a list of potential
252 configuration file locations (e.g. current directory, user's
253 home directory, systemwide directory), and all existing
254 configuration files in the list will be read. A single
255 filename may also be given.
257 Return list of successfully read files.
259 if isinstance(filenames, basestring):
260 filenames = [filenames]
261 read_ok = []
262 for filename in filenames:
263 try:
264 fp = open(filename)
265 except IOError:
266 continue
267 self._read(fp, filename)
268 fp.close()
269 read_ok.append(filename)
270 return read_ok
272 def readfp(self, fp, filename=None):
273 """Like read() but the argument must be a file-like object.
275 The `fp' argument must have a `readline' method. Optional
276 second argument is the `filename', which if not given, is
277 taken from fp.name. If fp has no `name' attribute, `<???>' is
278 used.
281 if filename is None:
282 try:
283 filename = fp.name
284 except AttributeError:
285 filename = '<???>'
286 self._read(fp, filename)
288 def get(self, section, option):
289 opt = self.optionxform(option)
290 if section not in self._sections:
291 if section != DEFAULTSECT:
292 raise NoSectionError(section)
293 if opt in self._defaults:
294 return self._defaults[opt]
295 else:
296 raise NoOptionError(option, section)
297 elif opt in self._sections[section]:
298 return self._sections[section][opt]
299 elif opt in self._defaults:
300 return self._defaults[opt]
301 else:
302 raise NoOptionError(option, section)
304 def items(self, section):
305 try:
306 d2 = self._sections[section]
307 except KeyError:
308 if section != DEFAULTSECT:
309 raise NoSectionError(section)
310 d2 = self._dict()
311 d = self._defaults.copy()
312 d.update(d2)
313 if "__name__" in d:
314 del d["__name__"]
315 return d.items()
317 def _get(self, section, conv, option):
318 return conv(self.get(section, option))
320 def getint(self, section, option):
321 return self._get(section, int, option)
323 def getfloat(self, section, option):
324 return self._get(section, float, option)
326 _boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
327 '0': False, 'no': False, 'false': False, 'off': False}
329 def getboolean(self, section, option):
330 v = self.get(section, option)
331 if v.lower() not in self._boolean_states:
332 raise ValueError, 'Not a boolean: %s' % v
333 return self._boolean_states[v.lower()]
335 def optionxform(self, optionstr):
336 return optionstr.lower()
338 def has_option(self, section, option):
339 """Check for the existence of a given option in a given section."""
340 if not section or section == DEFAULTSECT:
341 option = self.optionxform(option)
342 return option in self._defaults
343 elif section not in self._sections:
344 return False
345 else:
346 option = self.optionxform(option)
347 return (option in self._sections[section]
348 or option in self._defaults)
350 def set(self, section, option, value):
351 """Set an option."""
352 if not section or section == DEFAULTSECT:
353 sectdict = self._defaults
354 else:
355 try:
356 sectdict = self._sections[section]
357 except KeyError:
358 raise NoSectionError(section)
359 sectdict[self.optionxform(option)] = value
361 def write(self, fp):
362 """Write an .ini-format representation of the configuration state."""
363 if self._defaults:
364 fp.write("[%s]\n" % DEFAULTSECT)
365 for (key, value) in self._defaults.items():
366 fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
367 fp.write("\n")
368 for section in self._sections:
369 fp.write("[%s]\n" % section)
370 for (key, value) in self._sections[section].items():
371 if key != "__name__":
372 fp.write("%s = %s\n" %
373 (key, str(value).replace('\n', '\n\t')))
374 fp.write("\n")
376 def remove_option(self, section, option):
377 """Remove an option."""
378 if not section or section == DEFAULTSECT:
379 sectdict = self._defaults
380 else:
381 try:
382 sectdict = self._sections[section]
383 except KeyError:
384 raise NoSectionError(section)
385 option = self.optionxform(option)
386 existed = option in sectdict
387 if existed:
388 del sectdict[option]
389 return existed
391 def remove_section(self, section):
392 """Remove a file section."""
393 existed = section in self._sections
394 if existed:
395 del self._sections[section]
396 return existed
399 # Regular expressions for parsing section headers and options.
401 SECTCRE = re.compile(
402 r'\[' # [
403 r'(?P<header>[^]]+)' # very permissive!
404 r'\]' # ]
406 OPTCRE = re.compile(
407 r'(?P<option>[^:=\s][^:=]*)' # very permissive!
408 r'\s*(?P<vi>[:=])\s*' # any number of space/tab,
409 # followed by separator
410 # (either : or =), followed
411 # by any # space/tab
412 r'(?P<value>.*)$' # everything up to eol
415 def _read(self, fp, fpname):
416 """Parse a sectioned setup file.
418 The sections in setup file contains a title line at the top,
419 indicated by a name in square brackets (`[]'), plus key/value
420 options lines, indicated by `name: value' format lines.
421 Continuations are represented by an embedded newline then
422 leading whitespace. Blank lines, lines beginning with a '#',
423 and just about everything else are ignored.
425 cursect = None # None, or a dictionary
426 optname = None
427 lineno = 0
428 e = None # None, or an exception
429 while True:
430 line = fp.readline()
431 if not line:
432 break
433 lineno = lineno + 1
434 # comment or blank line?
435 if line.strip() == '' or line[0] in '#;':
436 continue
437 if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
438 # no leading whitespace
439 continue
440 # continuation line?
441 if line[0].isspace() and cursect is not None and optname:
442 value = line.strip()
443 if value:
444 cursect[optname] = "%s\n%s" % (cursect[optname], value)
445 # a section header or option header?
446 else:
447 # is it a section header?
448 mo = self.SECTCRE.match(line)
449 if mo:
450 sectname = mo.group('header')
451 if sectname in self._sections:
452 cursect = self._sections[sectname]
453 elif sectname == DEFAULTSECT:
454 cursect = self._defaults
455 else:
456 cursect = self._dict()
457 cursect['__name__'] = sectname
458 self._sections[sectname] = cursect
459 # So sections can't start with a continuation line
460 optname = None
461 # no section header in the file?
462 elif cursect is None:
463 raise MissingSectionHeaderError(fpname, lineno, line)
464 # an option line?
465 else:
466 mo = self.OPTCRE.match(line)
467 if mo:
468 optname, vi, optval = mo.group('option', 'vi', 'value')
469 if vi in ('=', ':') and ';' in optval:
470 # ';' is a comment delimiter only if it follows
471 # a spacing character
472 pos = optval.find(';')
473 if pos != -1 and optval[pos-1].isspace():
474 optval = optval[:pos]
475 optval = optval.strip()
476 # allow empty values
477 if optval == '""':
478 optval = ''
479 optname = self.optionxform(optname.rstrip())
480 cursect[optname] = optval
481 else:
482 # a non-fatal parsing error occurred. set up the
483 # exception but keep going. the exception will be
484 # raised at the end of the file and will contain a
485 # list of all bogus lines
486 if not e:
487 e = ParsingError(fpname)
488 e.append(lineno, repr(line))
489 # if any parsing errors occurred, raise an exception
490 if e:
491 raise e
494 class ConfigParser(RawConfigParser):
496 def get(self, section, option, raw=False, vars=None):
497 """Get an option value for a given section.
499 All % interpolations are expanded in the return values, based on the
500 defaults passed into the constructor, unless the optional argument
501 `raw' is true. Additional substitutions may be provided using the
502 `vars' argument, which must be a dictionary whose contents overrides
503 any pre-existing defaults.
505 The section DEFAULT is special.
507 d = self._defaults.copy()
508 try:
509 d.update(self._sections[section])
510 except KeyError:
511 if section != DEFAULTSECT:
512 raise NoSectionError(section)
513 # Update with the entry specific variables
514 if vars:
515 for key, value in vars.items():
516 d[self.optionxform(key)] = value
517 option = self.optionxform(option)
518 try:
519 value = d[option]
520 except KeyError:
521 raise NoOptionError(option, section)
523 if raw:
524 return value
525 else:
526 return self._interpolate(section, option, value, d)
528 def items(self, section, raw=False, vars=None):
529 """Return a list of tuples with (name, value) for each option
530 in the section.
532 All % interpolations are expanded in the return values, based on the
533 defaults passed into the constructor, unless the optional argument
534 `raw' is true. Additional substitutions may be provided using the
535 `vars' argument, which must be a dictionary whose contents overrides
536 any pre-existing defaults.
538 The section DEFAULT is special.
540 d = self._defaults.copy()
541 try:
542 d.update(self._sections[section])
543 except KeyError:
544 if section != DEFAULTSECT:
545 raise NoSectionError(section)
546 # Update with the entry specific variables
547 if vars:
548 for key, value in vars.items():
549 d[self.optionxform(key)] = value
550 options = d.keys()
551 if "__name__" in options:
552 options.remove("__name__")
553 if raw:
554 return [(option, d[option])
555 for option in options]
556 else:
557 return [(option, self._interpolate(section, option, d[option], d))
558 for option in options]
560 def _interpolate(self, section, option, rawval, vars):
561 # do the string interpolation
562 value = rawval
563 depth = MAX_INTERPOLATION_DEPTH
564 while depth: # Loop through this until it's done
565 depth -= 1
566 if "%(" in value:
567 value = self._KEYCRE.sub(self._interpolation_replace, value)
568 try:
569 value = value % vars
570 except KeyError, e:
571 raise InterpolationMissingOptionError(
572 option, section, rawval, e[0])
573 else:
574 break
575 if "%(" in value:
576 raise InterpolationDepthError(option, section, rawval)
577 return value
579 _KEYCRE = re.compile(r"%\(([^)]*)\)s|.")
581 def _interpolation_replace(self, match):
582 s = match.group(1)
583 if s is None:
584 return match.group()
585 else:
586 return "%%(%s)s" % self.optionxform(s)
589 class SafeConfigParser(ConfigParser):
591 def _interpolate(self, section, option, rawval, vars):
592 # do the string interpolation
593 L = []
594 self._interpolate_some(option, L, rawval, section, vars, 1)
595 return ''.join(L)
597 _interpvar_match = re.compile(r"%\(([^)]+)\)s").match
599 def _interpolate_some(self, option, accum, rest, section, map, depth):
600 if depth > MAX_INTERPOLATION_DEPTH:
601 raise InterpolationDepthError(option, section, rest)
602 while rest:
603 p = rest.find("%")
604 if p < 0:
605 accum.append(rest)
606 return
607 if p > 0:
608 accum.append(rest[:p])
609 rest = rest[p:]
610 # p is no longer used
611 c = rest[1:2]
612 if c == "%":
613 accum.append("%")
614 rest = rest[2:]
615 elif c == "(":
616 m = self._interpvar_match(rest)
617 if m is None:
618 raise InterpolationSyntaxError(option, section,
619 "bad interpolation variable reference %r" % rest)
620 var = self.optionxform(m.group(1))
621 rest = rest[m.end():]
622 try:
623 v = map[var]
624 except KeyError:
625 raise InterpolationMissingOptionError(
626 option, section, rest, var)
627 if "%" in v:
628 self._interpolate_some(option, accum, v,
629 section, map, depth + 1)
630 else:
631 accum.append(v)
632 else:
633 raise InterpolationSyntaxError(
634 option, section,
635 "'%%' must be followed by '%%' or '(', found: %r" % (rest,))
637 def set(self, section, option, value):
638 """Set an option. Extend ConfigParser.set: check for string values."""
639 if not isinstance(value, basestring):
640 raise TypeError("option values must be strings")
641 ConfigParser.set(self, section, option, value)