1 """Configuration file parser. 2 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. 6 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. 9 10 For example: 11 12 something: %(dir)s/whatever 13 14 would resolve the "%(dir)s" to the value of dir. All reference 15 expansions are done late, on demand. 16 17 Intrinsic defaults can be specified by passing them into the 18 ConfigParser constructor as a dictionary. 19 20 class: 21 22 ConfigParser -- responsible for parsing a list of 23 configuration files, and managing the parsed database. 24 25 methods: 26 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. 32 33 sections() 34 return all the configuration section names, sans DEFAULT 35 36 has_section(section) 37 return whether the given section exists 38 39 has_option(section, option) 40 return whether the given option exists in the given section 41 42 options(section) 43 return list of configuration options for the named section 44 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. 49 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). 54 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. 61 62 getint(section, options) 63 like get(), but convert value to an integer 64 65 getfloat(section, options) 66 like get(), but convert value to a float 67 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. 72 73 items(section, raw=False, vars=None) 74 return a list of tuples with (name, value) for each option 75 in the section. 76 77 remove_section(section) 78 remove the given file section and all its options 79 80 remove_option(section, option) 81 remove the given option from the given section 82 83 set(section, option, value) 84 set the given option 85 86 write(fp) 87 write the configuration state in .ini format 88 """ 89 90 try: 91 from collections import OrderedDict as _default_dict 92 except ImportError: 93 # fallback for setup.py which hasn't yet built _collections 94 _default_dict = dict 95 96 import re 97 98 __all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError", 99 "InterpolationError", "InterpolationDepthError", 100 "InterpolationSyntaxError", "ParsingError", 101 "MissingSectionHeaderError", 102 "ConfigParser", "SafeConfigParser", "RawConfigParser", 103 "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"] 104 105 DEFAULTSECT = "DEFAULT" 106 107 MAX_INTERPOLATION_DEPTH = 10 108 109 110 111 # exception classes 112 class Error(Exception): 113 """Base class for ConfigParser exceptions.""" 114 115 def _get_message(self): 116 """Getter for 'message'; needed only to override deprecation in 117 BaseException.""" 118 return self.__message 119 120 def _set_message(self, value): 121 """Setter for 'message'; needed only to override deprecation in 122 BaseException.""" 123 self.__message = value 124 125 # BaseException.message has been deprecated since Python 2.6. To prevent 126 # DeprecationWarning from popping up over this pre-existing attribute, use 127 # a new property that takes lookup precedence. 128 message = property(_get_message, _set_message) 129 130 def __init__(self, msg=''): 131 self.message = msg 132 Exception.__init__(self, msg) 133 134 def __repr__(self): 135 return self.message 136 137 __str__ = __repr__ 138 139 class NoSectionError(Error): 140 """Raised when no section matches a requested option.""" 141 142 def __init__(self, section): 143 Error.__init__(self, 'No section: %r' % (section,)) 144 self.section = section 145 self.args = (section, ) 146 147 class DuplicateSectionError(Error): 148 """Raised when a section is multiply-created.""" 149 150 def __init__(self, section): 151 Error.__init__(self, "Section %r already exists" % section) 152 self.section = section 153 self.args = (section, ) 154 155 class NoOptionError(Error): 156 """A requested option was not found.""" 157 158 def __init__(self, option, section): 159 Error.__init__(self, "No option %r in section: %r" % 160 (option, section)) 161 self.option = option 162 self.section = section 163 self.args = (option, section) 164 165 class InterpolationError(Error): 166 """Base class for interpolation-related exceptions.""" 167 168 def __init__(self, option, section, msg): 169 Error.__init__(self, msg) 170 self.option = option 171 self.section = section 172 self.args = (option, section, msg) 173 174 class InterpolationMissingOptionError(InterpolationError): 175 """A string substitution required a setting which was not available.""" 176 177 def __init__(self, option, section, rawval, reference): 178 msg = ("Bad value substitution:\n" 179 "\tsection: [%s]\n" 180 "\toption : %s\n" 181 "\tkey : %s\n" 182 "\trawval : %s\n" 183 % (section, option, reference, rawval)) 184 InterpolationError.__init__(self, option, section, msg) 185 self.reference = reference 186 self.args = (option, section, rawval, reference) 187 188 class InterpolationSyntaxError(InterpolationError): 189 """Raised when the source text into which substitutions are made 190 does not conform to the required syntax.""" 191 192 class InterpolationDepthError(InterpolationError): 193 """Raised when substitutions are nested too deeply.""" 194 195 def __init__(self, option, section, rawval): 196 msg = ("Value interpolation too deeply recursive:\n" 197 "\tsection: [%s]\n" 198 "\toption : %s\n" 199 "\trawval : %s\n" 200 % (section, option, rawval)) 201 InterpolationError.__init__(self, option, section, msg) 202 self.args = (option, section, rawval) 203 204 class ParsingError(Error): 205 """Raised when a configuration file does not follow legal syntax.""" 206 207 def __init__(self, filename): 208 Error.__init__(self, 'File contains parsing errors: %s' % filename) 209 self.filename = filename 210 self.errors = [] 211 self.args = (filename, ) 212 213 def append(self, lineno, line): 214 self.errors.append((lineno, line)) 215 self.message += '\n\t[line %2d]: %s' % (lineno, line) 216 217 class MissingSectionHeaderError(ParsingError): 218 """Raised when a key-value pair is found before any section header.""" 219 220 def __init__(self, filename, lineno, line): 221 Error.__init__( 222 self, 223 'File contains no section headers.\nfile: %s, line: %d\n%r' % 224 (filename, lineno, line)) 225 self.filename = filename 226 self.lineno = lineno 227 self.line = line 228 self.args = (filename, lineno, line) 229 230 231 class RawConfigParser: 232 def __init__(self, defaults=None, dict_type=_default_dict, 233 allow_no_value=False): 234 self._dict = dict_type 235 self._sections = self._dict() 236 self._defaults = self._dict() 237 if allow_no_value: 238 self._optcre = self.OPTCRE_NV 239 else: 240 self._optcre = self.OPTCRE 241 if defaults: 242 for key, value in defaults.items(): 243 self._defaults[self.optionxform(key)] = value 244 245 def defaults(self): 246 return self._defaults 247 248 def sections(self): 249 """Return a list of section names, excluding [DEFAULT]""" 250 # self._sections will never have [DEFAULT] in it 251 return self._sections.keys() 252 253 def add_section(self, section): 254 """Create a new section in the configuration. 255 256 Raise DuplicateSectionError if a section by the specified name 257 already exists. Raise ValueError if name is DEFAULT or any of it's 258 case-insensitive variants. 259 """ 260 if section.lower() == "default": 261 raise ValueError, 'Invalid section name: %s' % section 262 263 if section in self._sections: 264 raise DuplicateSectionError(section) 265 self._sections[section] = self._dict() 266 267 def has_section(self, section): 268 """Indicate whether the named section is present in the configuration. 269 270 The DEFAULT section is not acknowledged. 271 """ 272 return section in self._sections 273 274 def options(self, section): 275 """Return a list of option names for the given section name.""" 276 try: 277 opts = self._sections[section].copy() 278 except KeyError: 279 raise NoSectionError(section) 280 opts.update(self._defaults) 281 if '__name__' in opts: 282 del opts['__name__'] 283 return opts.keys() 284 285 def read(self, filenames): 286 """Read and parse a filename or a list of filenames. 287 288 Files that cannot be opened are silently ignored; this is 289 designed so that you can specify a list of potential 290 configuration file locations (e.g. current directory, user's 291 home directory, systemwide directory), and all existing 292 configuration files in the list will be read. A single 293 filename may also be given. 294 295 Return list of successfully read files. 296 """ 297 if isinstance(filenames, basestring): 298 filenames = [filenames] 299 read_ok = [] 300 for filename in filenames: 301 try: 302 fp = open(filename) 303 except IOError: 304 continue 305 self._read(fp, filename) 306 fp.close() 307 read_ok.append(filename) 308 return read_ok 309 310 def readfp(self, fp, filename=None): 311 """Like read() but the argument must be a file-like object. 312 313 The `fp' argument must have a `readline' method. Optional 314 second argument is the `filename', which if not given, is 315 taken from fp.name. If fp has no `name' attribute, `<???>' is 316 used. 317 318 """ 319 if filename is None: 320 try: 321 filename = fp.name 322 except AttributeError: 323 filename = '<???>' 324 self._read(fp, filename) 325 326 def get(self, section, option): 327 opt = self.optionxform(option) 328 if section not in self._sections: 329 if section != DEFAULTSECT: 330 raise NoSectionError(section) 331 if opt in self._defaults: 332 return self._defaults[opt] 333 else: 334 raise NoOptionError(option, section) 335 elif opt in self._sections[section]: 336 return self._sections[section][opt] 337 elif opt in self._defaults: 338 return self._defaults[opt] 339 else: 340 raise NoOptionError(option, section) 341 342 def items(self, section): 343 try: 344 d2 = self._sections[section] 345 except KeyError: 346 if section != DEFAULTSECT: 347 raise NoSectionError(section) 348 d2 = self._dict() 349 d = self._defaults.copy() 350 d.update(d2) 351 if "__name__" in d: 352 del d["__name__"] 353 return d.items() 354 355 def _get(self, section, conv, option): 356 return conv(self.get(section, option)) 357 358 def getint(self, section, option): 359 return self._get(section, int, option) 360 361 def getfloat(self, section, option): 362 return self._get(section, float, option) 363 364 _boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True, 365 '0': False, 'no': False, 'false': False, 'off': False} 366 367 def getboolean(self, section, option): 368 v = self.get(section, option) 369 if v.lower() not in self._boolean_states: 370 raise ValueError, 'Not a boolean: %s' % v 371 return self._boolean_states[v.lower()] 372 373 def optionxform(self, optionstr): 374 return optionstr.lower() 375 376 def has_option(self, section, option): 377 """Check for the existence of a given option in a given section.""" 378 if not section or section == DEFAULTSECT: 379 option = self.optionxform(option) 380 return option in self._defaults 381 elif section not in self._sections: 382 return False 383 else: 384 option = self.optionxform(option) 385 return (option in self._sections[section] 386 or option in self._defaults) 387 388 def set(self, section, option, value=None): 389 """Set an option.""" 390 if not section or section == DEFAULTSECT: 391 sectdict = self._defaults 392 else: 393 try: 394 sectdict = self._sections[section] 395 except KeyError: 396 raise NoSectionError(section) 397 sectdict[self.optionxform(option)] = value 398 399 def write(self, fp): 400 """Write an .ini-format representation of the configuration state.""" 401 if self._defaults: 402 fp.write("[%s]\n" % DEFAULTSECT) 403 for (key, value) in self._defaults.items(): 404 fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t'))) 405 fp.write("\n") 406 for section in self._sections: 407 fp.write("[%s]\n" % section) 408 for (key, value) in self._sections[section].items(): 409 if key == "__name__": 410 continue 411 if (value is not None) or (self._optcre == self.OPTCRE): 412 key = " = ".join((key, str(value).replace('\n', '\n\t'))) 413 fp.write("%s\n" % (key)) 414 fp.write("\n") 415 416 def remove_option(self, section, option): 417 """Remove an option.""" 418 if not section or section == DEFAULTSECT: 419 sectdict = self._defaults 420 else: 421 try: 422 sectdict = self._sections[section] 423 except KeyError: 424 raise NoSectionError(section) 425 option = self.optionxform(option) 426 existed = option in sectdict 427 if existed: 428 del sectdict[option] 429 return existed 430 431 def remove_section(self, section): 432 """Remove a file section.""" 433 existed = section in self._sections 434 if existed: 435 del self._sections[section] 436 return existed 437 438 # 439 # Regular expressions for parsing section headers and options. 440 # 441 SECTCRE = re.compile( 442 r'\[' # [ 443 r'(?P<header>[^]]+)' # very permissive! 444 r'\]' # ] 445 ) 446 OPTCRE = re.compile( 447 r'(?P<option>[^:=\s][^:=]*)' # very permissive! 448 r'\s*(?P<vi>[:=])\s*' # any number of space/tab, 449 # followed by separator 450 # (either : or =), followed 451 # by any # space/tab 452 r'(?P<value>.*)$' # everything up to eol 453 ) 454 OPTCRE_NV = re.compile( 455 r'(?P<option>[^:=\s][^:=]*)' # very permissive! 456 r'\s*(?:' # any number of space/tab, 457 r'(?P<vi>[:=])\s*' # optionally followed by 458 # separator (either : or 459 # =), followed by any # 460 # space/tab 461 r'(?P<value>.*))?$' # everything up to eol 462 ) 463 464 def _read(self, fp, fpname): 465 """Parse a sectioned setup file. 466 467 The sections in setup file contains a title line at the top, 468 indicated by a name in square brackets (`[]'), plus key/value 469 options lines, indicated by `name: value' format lines. 470 Continuations are represented by an embedded newline then 471 leading whitespace. Blank lines, lines beginning with a '#', 472 and just about everything else are ignored. 473 """ 474 cursect = None # None, or a dictionary 475 optname = None 476 lineno = 0 477 e = None # None, or an exception 478 while True: 479 line = fp.readline() 480 if not line: 481 break 482 lineno = lineno + 1 483 # comment or blank line? 484 if line.strip() == '' or line[0] in '#;': 485 continue 486 if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": 487 # no leading whitespace 488 continue 489 # continuation line? 490 if line[0].isspace() and cursect is not None and optname: 491 value = line.strip() 492 if value: 493 cursect[optname].append(value) 494 # a section header or option header? 495 else: 496 # is it a section header? 497 mo = self.SECTCRE.match(line) 498 if mo: 499 sectname = mo.group('header') 500 if sectname in self._sections: 501 cursect = self._sections[sectname] 502 elif sectname == DEFAULTSECT: 503 cursect = self._defaults 504 else: 505 cursect = self._dict() 506 cursect['__name__'] = sectname 507 self._sections[sectname] = cursect 508 # So sections can't start with a continuation line 509 optname = None 510 # no section header in the file? 511 elif cursect is None: 512 raise MissingSectionHeaderError(fpname, lineno, line) 513 # an option line? 514 else: 515 mo = self._optcre.match(line) 516 if mo: 517 optname, vi, optval = mo.group('option', 'vi', 'value') 518 optname = self.optionxform(optname.rstrip()) 519 # This check is fine because the OPTCRE cannot 520 # match if it would set optval to None 521 if optval is not None: 522 if vi in ('=', ':') and ';' in optval: 523 # ';' is a comment delimiter only if it follows 524 # a spacing character 525 pos = optval.find(';') 526 if pos != -1 and optval[pos-1].isspace(): 527 optval = optval[:pos] 528 optval = optval.strip() 529 # allow empty values 530 if optval == '""': 531 optval = '' 532 cursect[optname] = [optval] 533 else: 534 # valueless option handling 535 cursect[optname] = optval 536 else: 537 # a non-fatal parsing error occurred. set up the 538 # exception but keep going. the exception will be 539 # raised at the end of the file and will contain a 540 # list of all bogus lines 541 if not e: 542 e = ParsingError(fpname) 543 e.append(lineno, repr(line)) 544 # if any parsing errors occurred, raise an exception 545 if e: 546 raise e 547 548 # join the multi-line values collected while reading 549 all_sections = [self._defaults] 550 all_sections.extend(self._sections.values()) 551 for options in all_sections: 552 for name, val in options.items(): 553 if isinstance(val, list): 554 options[name] = '\n'.join(val) 555 556 import UserDict as _UserDict 557 558 class _Chainmap(_UserDict.DictMixin): 559 """Combine multiple mappings for successive lookups. 560 561 For example, to emulate Python's normal lookup sequence: 562 563 import __builtin__ 564 pylookup = _Chainmap(locals(), globals(), vars(__builtin__)) 565 """ 566 567 def __init__(self, *maps): 568 self._maps = maps 569 570 def __getitem__(self, key): 571 for mapping in self._maps: 572 try: 573 return mapping[key] 574 except KeyError: 575 pass 576 raise KeyError(key) 577 578 def keys(self): 579 result = [] 580 seen = set() 581 for mapping in self._maps: 582 for key in mapping: 583 if key not in seen: 584 result.append(key) 585 seen.add(key) 586 return result 587 588 class ConfigParser(RawConfigParser): 589 590 def get(self, section, option, raw=False, vars=None): 591 """Get an option value for a given section. 592 593 If `vars' is provided, it must be a dictionary. The option is looked up 594 in `vars' (if provided), `section', and in `defaults' in that order. 595 596 All % interpolations are expanded in the return values, unless the 597 optional argument `raw' is true. Values for interpolation keys are 598 looked up in the same manner as the option. 599 600 The section DEFAULT is special. 601 """ 602 sectiondict = {} 603 try: 604 sectiondict = self._sections[section] 605 except KeyError: 606 if section != DEFAULTSECT: 607 raise NoSectionError(section) 608 # Update with the entry specific variables 609 vardict = {} 610 if vars: 611 for key, value in vars.items(): 612 vardict[self.optionxform(key)] = value 613 d = _Chainmap(vardict, sectiondict, self._defaults) 614 option = self.optionxform(option) 615 try: 616 value = d[option] 617 except KeyError: 618 raise NoOptionError(option, section) 619 620 if raw or value is None: 621 return value 622 else: 623 return self._interpolate(section, option, value, d) 624 625 def items(self, section, raw=False, vars=None): 626 """Return a list of tuples with (name, value) for each option 627 in the section. 628 629 All % interpolations are expanded in the return values, based on the 630 defaults passed into the constructor, unless the optional argument 631 `raw' is true. Additional substitutions may be provided using the 632 `vars' argument, which must be a dictionary whose contents overrides 633 any pre-existing defaults. 634 635 The section DEFAULT is special. 636 """ 637 d = self._defaults.copy() 638 try: 639 d.update(self._sections[section]) 640 except KeyError: 641 if section != DEFAULTSECT: 642 raise NoSectionError(section) 643 # Update with the entry specific variables 644 if vars: 645 for key, value in vars.items(): 646 d[self.optionxform(key)] = value 647 options = d.keys() 648 if "__name__" in options: 649 options.remove("__name__") 650 if raw: 651 return [(option, d[option]) 652 for option in options] 653 else: 654 return [(option, self._interpolate(section, option, d[option], d)) 655 for option in options] 656 657 def _interpolate(self, section, option, rawval, vars): 658 # do the string interpolation 659 value = rawval 660 depth = MAX_INTERPOLATION_DEPTH 661 while depth: # Loop through this until it's done 662 depth -= 1 663 if value and "%(" in value: 664 value = self._KEYCRE.sub(self._interpolation_replace, value) 665 try: 666 value = value % vars 667 except KeyError, e: 668 raise InterpolationMissingOptionError( 669 option, section, rawval, e.args[0]) 670 else: 671 break 672 if value and "%(" in value: 673 raise InterpolationDepthError(option, section, rawval) 674 return value 675 676 _KEYCRE = re.compile(r"%\(([^)]*)\)s|.") 677 678 def _interpolation_replace(self, match): 679 s = match.group(1) 680 if s is None: 681 return match.group() 682 else: 683 return "%%(%s)s" % self.optionxform(s) 684 685 686 class SafeConfigParser(ConfigParser): 687 688 def _interpolate(self, section, option, rawval, vars): 689 # do the string interpolation 690 L = [] 691 self._interpolate_some(option, L, rawval, section, vars, 1) 692 return ''.join(L) 693 694 _interpvar_re = re.compile(r"%\(([^)]+)\)s") 695 696 def _interpolate_some(self, option, accum, rest, section, map, depth): 697 if depth > MAX_INTERPOLATION_DEPTH: 698 raise InterpolationDepthError(option, section, rest) 699 while rest: 700 p = rest.find("%") 701 if p < 0: 702 accum.append(rest) 703 return 704 if p > 0: 705 accum.append(rest[:p]) 706 rest = rest[p:] 707 # p is no longer used 708 c = rest[1:2] 709 if c == "%": 710 accum.append("%") 711 rest = rest[2:] 712 elif c == "(": 713 m = self._interpvar_re.match(rest) 714 if m is None: 715 raise InterpolationSyntaxError(option, section, 716 "bad interpolation variable reference %r" % rest) 717 var = self.optionxform(m.group(1)) 718 rest = rest[m.end():] 719 try: 720 v = map[var] 721 except KeyError: 722 raise InterpolationMissingOptionError( 723 option, section, rest, var) 724 if "%" in v: 725 self._interpolate_some(option, accum, v, 726 section, map, depth + 1) 727 else: 728 accum.append(v) 729 else: 730 raise InterpolationSyntaxError( 731 option, section, 732 "'%%' must be followed by '%%' or '(', found: %r" % (rest,)) 733 734 def set(self, section, option, value=None): 735 """Set an option. Extend ConfigParser.set: check for string values.""" 736 # The only legal non-string value if we allow valueless 737 # options is None, so we need to check if the value is a 738 # string if: 739 # - we do not allow valueless options, or 740 # - we allow valueless options but the value is not None 741 if self._optcre is self.OPTCRE or value: 742 if not isinstance(value, basestring): 743 raise TypeError("option values must be strings") 744 if value is not None: 745 # check for bad percent signs: 746 # first, replace all "good" interpolations 747 tmp_value = value.replace('%%', '') 748 tmp_value = self._interpvar_re.sub('', tmp_value) 749 # then, check if there's a lone percent sign left 750 if '%' in tmp_value: 751 raise ValueError("invalid interpolation syntax in %r at " 752 "position %d" % (value, tmp_value.find('%'))) 753 ConfigParser.set(self, section, option, value) 754