Remove Barry's love of deprecated syntax to silence warnings in the email
[python.git] / Lib / ConfigParser.py
blobb6af6f9bab916a4eb24de35dcddb7f6f60ccdb08
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 _get_message(self):
110 """Getter for 'message'; needed only to override deprecation in
111 BaseException."""
112 return self.__message
114 def _set_message(self, value):
115 """Setter for 'message'; needed only to override deprecation in
116 BaseException."""
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=''):
125 self.message = msg
126 Exception.__init__(self, msg)
128 def __repr__(self):
129 return self.message
131 __str__ = __repr__
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" %
152 (option, section))
153 self.option = option
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)
161 self.option = option
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"
169 "\tsection: [%s]\n"
170 "\toption : %s\n"
171 "\tkey : %s\n"
172 "\trawval : %s\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"
186 "\tsection: [%s]\n"
187 "\toption : %s\n"
188 "\trawval : %s\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
198 self.errors = []
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):
208 Error.__init__(
209 self,
210 'File contains no section headers.\nfile: %s, line: %d\n%r' %
211 (filename, lineno, line))
212 self.filename = filename
213 self.lineno = lineno
214 self.line = line
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()
222 if defaults:
223 for key, value in defaults.items():
224 self._defaults[self.optionxform(key)] = value
226 def defaults(self):
227 return self._defaults
229 def sections(self):
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."""
257 try:
258 opts = self._sections[section].copy()
259 except KeyError:
260 raise NoSectionError(section)
261 opts.update(self._defaults)
262 if '__name__' in opts:
263 del opts['__name__']
264 return opts.keys()
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]
280 read_ok = []
281 for filename in filenames:
282 try:
283 fp = open(filename)
284 except IOError:
285 continue
286 self._read(fp, filename)
287 fp.close()
288 read_ok.append(filename)
289 return read_ok
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
297 used.
300 if filename is None:
301 try:
302 filename = fp.name
303 except AttributeError:
304 filename = '<???>'
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]
314 else:
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]
320 else:
321 raise NoOptionError(option, section)
323 def items(self, section):
324 try:
325 d2 = self._sections[section]
326 except KeyError:
327 if section != DEFAULTSECT:
328 raise NoSectionError(section)
329 d2 = self._dict()
330 d = self._defaults.copy()
331 d.update(d2)
332 if "__name__" in d:
333 del d["__name__"]
334 return d.items()
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:
363 return False
364 else:
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):
370 """Set an option."""
371 if not section or section == DEFAULTSECT:
372 sectdict = self._defaults
373 else:
374 try:
375 sectdict = self._sections[section]
376 except KeyError:
377 raise NoSectionError(section)
378 sectdict[self.optionxform(option)] = value
380 def write(self, fp):
381 """Write an .ini-format representation of the configuration state."""
382 if self._defaults:
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')))
386 fp.write("\n")
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')))
393 fp.write("\n")
395 def remove_option(self, section, option):
396 """Remove an option."""
397 if not section or section == DEFAULTSECT:
398 sectdict = self._defaults
399 else:
400 try:
401 sectdict = self._sections[section]
402 except KeyError:
403 raise NoSectionError(section)
404 option = self.optionxform(option)
405 existed = option in sectdict
406 if existed:
407 del sectdict[option]
408 return existed
410 def remove_section(self, section):
411 """Remove a file section."""
412 existed = section in self._sections
413 if existed:
414 del self._sections[section]
415 return existed
418 # Regular expressions for parsing section headers and options.
420 SECTCRE = re.compile(
421 r'\[' # [
422 r'(?P<header>[^]]+)' # very permissive!
423 r'\]' # ]
425 OPTCRE = re.compile(
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
430 # by any # space/tab
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
445 optname = None
446 lineno = 0
447 e = None # None, or an exception
448 while True:
449 line = fp.readline()
450 if not line:
451 break
452 lineno = lineno + 1
453 # comment or blank line?
454 if line.strip() == '' or line[0] in '#;':
455 continue
456 if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
457 # no leading whitespace
458 continue
459 # continuation line?
460 if line[0].isspace() and cursect is not None and optname:
461 value = line.strip()
462 if value:
463 cursect[optname] = "%s\n%s" % (cursect[optname], value)
464 # a section header or option header?
465 else:
466 # is it a section header?
467 mo = self.SECTCRE.match(line)
468 if mo:
469 sectname = mo.group('header')
470 if sectname in self._sections:
471 cursect = self._sections[sectname]
472 elif sectname == DEFAULTSECT:
473 cursect = self._defaults
474 else:
475 cursect = self._dict()
476 cursect['__name__'] = sectname
477 self._sections[sectname] = cursect
478 # So sections can't start with a continuation line
479 optname = None
480 # no section header in the file?
481 elif cursect is None:
482 raise MissingSectionHeaderError(fpname, lineno, line)
483 # an option line?
484 else:
485 mo = self.OPTCRE.match(line)
486 if mo:
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()
495 # allow empty values
496 if optval == '""':
497 optval = ''
498 optname = self.optionxform(optname.rstrip())
499 cursect[optname] = optval
500 else:
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
505 if not e:
506 e = ParsingError(fpname)
507 e.append(lineno, repr(line))
508 # if any parsing errors occurred, raise an exception
509 if e:
510 raise e
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()
527 try:
528 d.update(self._sections[section])
529 except KeyError:
530 if section != DEFAULTSECT:
531 raise NoSectionError(section)
532 # Update with the entry specific variables
533 if vars:
534 for key, value in vars.items():
535 d[self.optionxform(key)] = value
536 option = self.optionxform(option)
537 try:
538 value = d[option]
539 except KeyError:
540 raise NoOptionError(option, section)
542 if raw:
543 return value
544 else:
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
549 in the section.
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()
560 try:
561 d.update(self._sections[section])
562 except KeyError:
563 if section != DEFAULTSECT:
564 raise NoSectionError(section)
565 # Update with the entry specific variables
566 if vars:
567 for key, value in vars.items():
568 d[self.optionxform(key)] = value
569 options = d.keys()
570 if "__name__" in options:
571 options.remove("__name__")
572 if raw:
573 return [(option, d[option])
574 for option in options]
575 else:
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
581 value = rawval
582 depth = MAX_INTERPOLATION_DEPTH
583 while depth: # Loop through this until it's done
584 depth -= 1
585 if "%(" in value:
586 value = self._KEYCRE.sub(self._interpolation_replace, value)
587 try:
588 value = value % vars
589 except KeyError, e:
590 raise InterpolationMissingOptionError(
591 option, section, rawval, e.args[0])
592 else:
593 break
594 if "%(" in value:
595 raise InterpolationDepthError(option, section, rawval)
596 return value
598 _KEYCRE = re.compile(r"%\(([^)]*)\)s|.")
600 def _interpolation_replace(self, match):
601 s = match.group(1)
602 if s is None:
603 return match.group()
604 else:
605 return "%%(%s)s" % self.optionxform(s)
608 class SafeConfigParser(ConfigParser):
610 def _interpolate(self, section, option, rawval, vars):
611 # do the string interpolation
612 L = []
613 self._interpolate_some(option, L, rawval, section, vars, 1)
614 return ''.join(L)
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)
622 while rest:
623 p = rest.find("%")
624 if p < 0:
625 accum.append(rest)
626 return
627 if p > 0:
628 accum.append(rest[:p])
629 rest = rest[p:]
630 # p is no longer used
631 c = rest[1:2]
632 if c == "%":
633 accum.append("%")
634 rest = rest[2:]
635 elif c == "(":
636 m = self._interpvar_re.match(rest)
637 if m is None:
638 raise InterpolationSyntaxError(option, section,
639 "bad interpolation variable reference %r" % rest)
640 var = self.optionxform(m.group(1))
641 rest = rest[m.end():]
642 try:
643 v = map[var]
644 except KeyError:
645 raise InterpolationMissingOptionError(
646 option, section, rest, var)
647 if "%" in v:
648 self._interpolate_some(option, accum, v,
649 section, map, depth + 1)
650 else:
651 accum.append(v)
652 else:
653 raise InterpolationSyntaxError(
654 option, section,
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)
666 if m:
667 raise ValueError("invalid interpolation syntax in %r at "
668 "position %d" % (value, m.start()))
669 ConfigParser.set(self, section, option, value)