1"""Configuration file parser. 2 3A configuration file consists of sections, lead by a "[section]" header, 4and followed by "name: value" entries, with continuations and such in 5the style of RFC 822. 6 7Intrinsic defaults can be specified by passing them into the 8ConfigParser constructor as a dictionary. 9 10class: 11 12ConfigParser -- responsible for parsing a list of 13 configuration files, and managing the parsed database. 14 15 methods: 16 17 __init__(defaults=None, dict_type=_default_dict, allow_no_value=False, 18 delimiters=('=', ':'), comment_prefixes=('#', ';'), 19 inline_comment_prefixes=None, strict=True, 20 empty_lines_in_values=True, default_section='DEFAULT', 21 interpolation=<unset>, converters=<unset>): 22 Create the parser. When `defaults' is given, it is initialized into the 23 dictionary or intrinsic defaults. The keys must be strings, the values 24 must be appropriate for %()s string interpolation. 25 26 When `dict_type' is given, it will be used to create the dictionary 27 objects for the list of sections, for the options within a section, and 28 for the default values. 29 30 When `delimiters' is given, it will be used as the set of substrings 31 that divide keys from values. 32 33 When `comment_prefixes' is given, it will be used as the set of 34 substrings that prefix comments in empty lines. Comments can be 35 indented. 36 37 When `inline_comment_prefixes' is given, it will be used as the set of 38 substrings that prefix comments in non-empty lines. 39 40 When `strict` is True, the parser won't allow for any section or option 41 duplicates while reading from a single source (file, string or 42 dictionary). Default is True. 43 44 When `empty_lines_in_values' is False (default: True), each empty line 45 marks the end of an option. Otherwise, internal empty lines of 46 a multiline option are kept as part of the value. 47 48 When `allow_no_value' is True (default: False), options without 49 values are accepted; the value presented for these is None. 50 51 When `default_section' is given, the name of the special section is 52 named accordingly. By default it is called ``"DEFAULT"`` but this can 53 be customized to point to any other valid section name. Its current 54 value can be retrieved using the ``parser_instance.default_section`` 55 attribute and may be modified at runtime. 56 57 When `interpolation` is given, it should be an Interpolation subclass 58 instance. It will be used as the handler for option value 59 pre-processing when using getters. RawConfigParser objects don't do 60 any sort of interpolation, whereas ConfigParser uses an instance of 61 BasicInterpolation. The library also provides a ``zc.buildbot`` 62 inspired ExtendedInterpolation implementation. 63 64 When `converters` is given, it should be a dictionary where each key 65 represents the name of a type converter and each value is a callable 66 implementing the conversion from string to the desired datatype. Every 67 converter gets its corresponding get*() method on the parser object and 68 section proxies. 69 70 sections() 71 Return all the configuration section names, sans DEFAULT. 72 73 has_section(section) 74 Return whether the given section exists. 75 76 has_option(section, option) 77 Return whether the given option exists in the given section. 78 79 options(section) 80 Return list of configuration options for the named section. 81 82 read(filenames, encoding=None) 83 Read and parse the iterable of named configuration files, given by 84 name. A single filename is also allowed. Non-existing files 85 are ignored. Return list of successfully read files. 86 87 read_file(f, filename=None) 88 Read and parse one configuration file, given as a file object. 89 The filename defaults to f.name; it is only used in error 90 messages (if f has no `name' attribute, the string `<???>' is used). 91 92 read_string(string) 93 Read configuration from a given string. 94 95 read_dict(dictionary) 96 Read configuration from a dictionary. Keys are section names, 97 values are dictionaries with keys and values that should be present 98 in the section. If the used dictionary type preserves order, sections 99 and their keys will be added in order. Values are automatically 100 converted to strings. 101 102 get(section, option, raw=False, vars=None, fallback=_UNSET) 103 Return a string value for the named option. All % interpolations are 104 expanded in the return values, based on the defaults passed into the 105 constructor and the DEFAULT section. Additional substitutions may be 106 provided using the `vars' argument, which must be a dictionary whose 107 contents override any pre-existing defaults. If `option' is a key in 108 `vars', the value from `vars' is used. 109 110 getint(section, options, raw=False, vars=None, fallback=_UNSET) 111 Like get(), but convert value to an integer. 112 113 getfloat(section, options, raw=False, vars=None, fallback=_UNSET) 114 Like get(), but convert value to a float. 115 116 getboolean(section, options, raw=False, vars=None, fallback=_UNSET) 117 Like get(), but convert value to a boolean (currently case 118 insensitively defined as 0, false, no, off for False, and 1, true, 119 yes, on for True). Returns False or True. 120 121 items(section=_UNSET, raw=False, vars=None) 122 If section is given, return a list of tuples with (name, value) for 123 each option in the section. Otherwise, return a list of tuples with 124 (section_name, section_proxy) for each section, including DEFAULTSECT. 125 126 remove_section(section) 127 Remove the given file section and all its options. 128 129 remove_option(section, option) 130 Remove the given option from the given section. 131 132 set(section, option, value) 133 Set the given option. 134 135 write(fp, space_around_delimiters=True) 136 Write the configuration state in .ini format. If 137 `space_around_delimiters' is True (the default), delimiters 138 between keys and values are surrounded by spaces. 139""" 140 141from collections.abc import MutableMapping 142from collections import ChainMap as _ChainMap 143import functools 144import io 145import itertools 146import os 147import re 148import sys 149import warnings 150 151__all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError", 152 "NoOptionError", "InterpolationError", "InterpolationDepthError", 153 "InterpolationMissingOptionError", "InterpolationSyntaxError", 154 "ParsingError", "MissingSectionHeaderError", 155 "ConfigParser", "SafeConfigParser", "RawConfigParser", 156 "Interpolation", "BasicInterpolation", "ExtendedInterpolation", 157 "LegacyInterpolation", "SectionProxy", "ConverterMapping", 158 "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"] 159 160_default_dict = dict 161DEFAULTSECT = "DEFAULT" 162 163MAX_INTERPOLATION_DEPTH = 10 164 165 166 167# exception classes 168class Error(Exception): 169 """Base class for ConfigParser exceptions.""" 170 171 def __init__(self, msg=''): 172 self.message = msg 173 Exception.__init__(self, msg) 174 175 def __repr__(self): 176 return self.message 177 178 __str__ = __repr__ 179 180 181class NoSectionError(Error): 182 """Raised when no section matches a requested option.""" 183 184 def __init__(self, section): 185 Error.__init__(self, 'No section: %r' % (section,)) 186 self.section = section 187 self.args = (section, ) 188 189 190class DuplicateSectionError(Error): 191 """Raised when a section is repeated in an input source. 192 193 Possible repetitions that raise this exception are: multiple creation 194 using the API or in strict parsers when a section is found more than once 195 in a single input file, string or dictionary. 196 """ 197 198 def __init__(self, section, source=None, lineno=None): 199 msg = [repr(section), " already exists"] 200 if source is not None: 201 message = ["While reading from ", repr(source)] 202 if lineno is not None: 203 message.append(" [line {0:2d}]".format(lineno)) 204 message.append(": section ") 205 message.extend(msg) 206 msg = message 207 else: 208 msg.insert(0, "Section ") 209 Error.__init__(self, "".join(msg)) 210 self.section = section 211 self.source = source 212 self.lineno = lineno 213 self.args = (section, source, lineno) 214 215 216class DuplicateOptionError(Error): 217 """Raised by strict parsers when an option is repeated in an input source. 218 219 Current implementation raises this exception only when an option is found 220 more than once in a single file, string or dictionary. 221 """ 222 223 def __init__(self, section, option, source=None, lineno=None): 224 msg = [repr(option), " in section ", repr(section), 225 " already exists"] 226 if source is not None: 227 message = ["While reading from ", repr(source)] 228 if lineno is not None: 229 message.append(" [line {0:2d}]".format(lineno)) 230 message.append(": option ") 231 message.extend(msg) 232 msg = message 233 else: 234 msg.insert(0, "Option ") 235 Error.__init__(self, "".join(msg)) 236 self.section = section 237 self.option = option 238 self.source = source 239 self.lineno = lineno 240 self.args = (section, option, source, lineno) 241 242 243class NoOptionError(Error): 244 """A requested option was not found.""" 245 246 def __init__(self, option, section): 247 Error.__init__(self, "No option %r in section: %r" % 248 (option, section)) 249 self.option = option 250 self.section = section 251 self.args = (option, section) 252 253 254class InterpolationError(Error): 255 """Base class for interpolation-related exceptions.""" 256 257 def __init__(self, option, section, msg): 258 Error.__init__(self, msg) 259 self.option = option 260 self.section = section 261 self.args = (option, section, msg) 262 263 264class InterpolationMissingOptionError(InterpolationError): 265 """A string substitution required a setting which was not available.""" 266 267 def __init__(self, option, section, rawval, reference): 268 msg = ("Bad value substitution: option {!r} in section {!r} contains " 269 "an interpolation key {!r} which is not a valid option name. " 270 "Raw value: {!r}".format(option, section, reference, rawval)) 271 InterpolationError.__init__(self, option, section, msg) 272 self.reference = reference 273 self.args = (option, section, rawval, reference) 274 275 276class InterpolationSyntaxError(InterpolationError): 277 """Raised when the source text contains invalid syntax. 278 279 Current implementation raises this exception when the source text into 280 which substitutions are made does not conform to the required syntax. 281 """ 282 283 284class InterpolationDepthError(InterpolationError): 285 """Raised when substitutions are nested too deeply.""" 286 287 def __init__(self, option, section, rawval): 288 msg = ("Recursion limit exceeded in value substitution: option {!r} " 289 "in section {!r} contains an interpolation key which " 290 "cannot be substituted in {} steps. Raw value: {!r}" 291 "".format(option, section, MAX_INTERPOLATION_DEPTH, 292 rawval)) 293 InterpolationError.__init__(self, option, section, msg) 294 self.args = (option, section, rawval) 295 296 297class ParsingError(Error): 298 """Raised when a configuration file does not follow legal syntax.""" 299 300 def __init__(self, source=None, filename=None): 301 # Exactly one of `source'/`filename' arguments has to be given. 302 # `filename' kept for compatibility. 303 if filename and source: 304 raise ValueError("Cannot specify both `filename' and `source'. " 305 "Use `source'.") 306 elif not filename and not source: 307 raise ValueError("Required argument `source' not given.") 308 elif filename: 309 source = filename 310 Error.__init__(self, 'Source contains parsing errors: %r' % source) 311 self.source = source 312 self.errors = [] 313 self.args = (source, ) 314 315 @property 316 def filename(self): 317 """Deprecated, use `source'.""" 318 warnings.warn( 319 "The 'filename' attribute will be removed in future versions. " 320 "Use 'source' instead.", 321 DeprecationWarning, stacklevel=2 322 ) 323 return self.source 324 325 @filename.setter 326 def filename(self, value): 327 """Deprecated, user `source'.""" 328 warnings.warn( 329 "The 'filename' attribute will be removed in future versions. " 330 "Use 'source' instead.", 331 DeprecationWarning, stacklevel=2 332 ) 333 self.source = value 334 335 def append(self, lineno, line): 336 self.errors.append((lineno, line)) 337 self.message += '\n\t[line %2d]: %s' % (lineno, line) 338 339 340class MissingSectionHeaderError(ParsingError): 341 """Raised when a key-value pair is found before any section header.""" 342 343 def __init__(self, filename, lineno, line): 344 Error.__init__( 345 self, 346 'File contains no section headers.\nfile: %r, line: %d\n%r' % 347 (filename, lineno, line)) 348 self.source = filename 349 self.lineno = lineno 350 self.line = line 351 self.args = (filename, lineno, line) 352 353 354# Used in parser getters to indicate the default behaviour when a specific 355# option is not found it to raise an exception. Created to enable `None' as 356# a valid fallback value. 357_UNSET = object() 358 359 360class Interpolation: 361 """Dummy interpolation that passes the value through with no changes.""" 362 363 def before_get(self, parser, section, option, value, defaults): 364 return value 365 366 def before_set(self, parser, section, option, value): 367 return value 368 369 def before_read(self, parser, section, option, value): 370 return value 371 372 def before_write(self, parser, section, option, value): 373 return value 374 375 376class BasicInterpolation(Interpolation): 377 """Interpolation as implemented in the classic ConfigParser. 378 379 The option values can contain format strings which refer to other values in 380 the same section, or values in the special default section. 381 382 For example: 383 384 something: %(dir)s/whatever 385 386 would resolve the "%(dir)s" to the value of dir. All reference 387 expansions are done late, on demand. If a user needs to use a bare % in 388 a configuration file, she can escape it by writing %%. Other % usage 389 is considered a user error and raises `InterpolationSyntaxError'.""" 390 391 _KEYCRE = re.compile(r"%\(([^)]+)\)s") 392 393 def before_get(self, parser, section, option, value, defaults): 394 L = [] 395 self._interpolate_some(parser, option, L, value, section, defaults, 1) 396 return ''.join(L) 397 398 def before_set(self, parser, section, option, value): 399 tmp_value = value.replace('%%', '') # escaped percent signs 400 tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax 401 if '%' in tmp_value: 402 raise ValueError("invalid interpolation syntax in %r at " 403 "position %d" % (value, tmp_value.find('%'))) 404 return value 405 406 def _interpolate_some(self, parser, option, accum, rest, section, map, 407 depth): 408 rawval = parser.get(section, option, raw=True, fallback=rest) 409 if depth > MAX_INTERPOLATION_DEPTH: 410 raise InterpolationDepthError(option, section, rawval) 411 while rest: 412 p = rest.find("%") 413 if p < 0: 414 accum.append(rest) 415 return 416 if p > 0: 417 accum.append(rest[:p]) 418 rest = rest[p:] 419 # p is no longer used 420 c = rest[1:2] 421 if c == "%": 422 accum.append("%") 423 rest = rest[2:] 424 elif c == "(": 425 m = self._KEYCRE.match(rest) 426 if m is None: 427 raise InterpolationSyntaxError(option, section, 428 "bad interpolation variable reference %r" % rest) 429 var = parser.optionxform(m.group(1)) 430 rest = rest[m.end():] 431 try: 432 v = map[var] 433 except KeyError: 434 raise InterpolationMissingOptionError( 435 option, section, rawval, var) from None 436 if "%" in v: 437 self._interpolate_some(parser, option, accum, v, 438 section, map, depth + 1) 439 else: 440 accum.append(v) 441 else: 442 raise InterpolationSyntaxError( 443 option, section, 444 "'%%' must be followed by '%%' or '(', " 445 "found: %r" % (rest,)) 446 447 448class ExtendedInterpolation(Interpolation): 449 """Advanced variant of interpolation, supports the syntax used by 450 `zc.buildout'. Enables interpolation between sections.""" 451 452 _KEYCRE = re.compile(r"\$\{([^}]+)\}") 453 454 def before_get(self, parser, section, option, value, defaults): 455 L = [] 456 self._interpolate_some(parser, option, L, value, section, defaults, 1) 457 return ''.join(L) 458 459 def before_set(self, parser, section, option, value): 460 tmp_value = value.replace('$$', '') # escaped dollar signs 461 tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax 462 if '$' in tmp_value: 463 raise ValueError("invalid interpolation syntax in %r at " 464 "position %d" % (value, tmp_value.find('$'))) 465 return value 466 467 def _interpolate_some(self, parser, option, accum, rest, section, map, 468 depth): 469 rawval = parser.get(section, option, raw=True, fallback=rest) 470 if depth > MAX_INTERPOLATION_DEPTH: 471 raise InterpolationDepthError(option, section, rawval) 472 while rest: 473 p = rest.find("$") 474 if p < 0: 475 accum.append(rest) 476 return 477 if p > 0: 478 accum.append(rest[:p]) 479 rest = rest[p:] 480 # p is no longer used 481 c = rest[1:2] 482 if c == "$": 483 accum.append("$") 484 rest = rest[2:] 485 elif c == "{": 486 m = self._KEYCRE.match(rest) 487 if m is None: 488 raise InterpolationSyntaxError(option, section, 489 "bad interpolation variable reference %r" % rest) 490 path = m.group(1).split(':') 491 rest = rest[m.end():] 492 sect = section 493 opt = option 494 try: 495 if len(path) == 1: 496 opt = parser.optionxform(path[0]) 497 v = map[opt] 498 elif len(path) == 2: 499 sect = path[0] 500 opt = parser.optionxform(path[1]) 501 v = parser.get(sect, opt, raw=True) 502 else: 503 raise InterpolationSyntaxError( 504 option, section, 505 "More than one ':' found: %r" % (rest,)) 506 except (KeyError, NoSectionError, NoOptionError): 507 raise InterpolationMissingOptionError( 508 option, section, rawval, ":".join(path)) from None 509 if "$" in v: 510 self._interpolate_some(parser, opt, accum, v, sect, 511 dict(parser.items(sect, raw=True)), 512 depth + 1) 513 else: 514 accum.append(v) 515 else: 516 raise InterpolationSyntaxError( 517 option, section, 518 "'$' must be followed by '$' or '{', " 519 "found: %r" % (rest,)) 520 521 522class LegacyInterpolation(Interpolation): 523 """Deprecated interpolation used in old versions of ConfigParser. 524 Use BasicInterpolation or ExtendedInterpolation instead.""" 525 526 _KEYCRE = re.compile(r"%\(([^)]*)\)s|.") 527 528 def before_get(self, parser, section, option, value, vars): 529 rawval = value 530 depth = MAX_INTERPOLATION_DEPTH 531 while depth: # Loop through this until it's done 532 depth -= 1 533 if value and "%(" in value: 534 replace = functools.partial(self._interpolation_replace, 535 parser=parser) 536 value = self._KEYCRE.sub(replace, value) 537 try: 538 value = value % vars 539 except KeyError as e: 540 raise InterpolationMissingOptionError( 541 option, section, rawval, e.args[0]) from None 542 else: 543 break 544 if value and "%(" in value: 545 raise InterpolationDepthError(option, section, rawval) 546 return value 547 548 def before_set(self, parser, section, option, value): 549 return value 550 551 @staticmethod 552 def _interpolation_replace(match, parser): 553 s = match.group(1) 554 if s is None: 555 return match.group() 556 else: 557 return "%%(%s)s" % parser.optionxform(s) 558 559 560class RawConfigParser(MutableMapping): 561 """ConfigParser that does not do interpolation.""" 562 563 # Regular expressions for parsing section headers and options 564 _SECT_TMPL = r""" 565 \[ # [ 566 (?P<header>.+) # very permissive! 567 \] # ] 568 """ 569 _OPT_TMPL = r""" 570 (?P<option>.*?) # very permissive! 571 \s*(?P<vi>{delim})\s* # any number of space/tab, 572 # followed by any of the 573 # allowed delimiters, 574 # followed by any space/tab 575 (?P<value>.*)$ # everything up to eol 576 """ 577 _OPT_NV_TMPL = r""" 578 (?P<option>.*?) # very permissive! 579 \s*(?: # any number of space/tab, 580 (?P<vi>{delim})\s* # optionally followed by 581 # any of the allowed 582 # delimiters, followed by any 583 # space/tab 584 (?P<value>.*))?$ # everything up to eol 585 """ 586 # Interpolation algorithm to be used if the user does not specify another 587 _DEFAULT_INTERPOLATION = Interpolation() 588 # Compiled regular expression for matching sections 589 SECTCRE = re.compile(_SECT_TMPL, re.VERBOSE) 590 # Compiled regular expression for matching options with typical separators 591 OPTCRE = re.compile(_OPT_TMPL.format(delim="=|:"), re.VERBOSE) 592 # Compiled regular expression for matching options with optional values 593 # delimited using typical separators 594 OPTCRE_NV = re.compile(_OPT_NV_TMPL.format(delim="=|:"), re.VERBOSE) 595 # Compiled regular expression for matching leading whitespace in a line 596 NONSPACECRE = re.compile(r"\S") 597 # Possible boolean values in the configuration. 598 BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True, 599 '0': False, 'no': False, 'false': False, 'off': False} 600 601 def __init__(self, defaults=None, dict_type=_default_dict, 602 allow_no_value=False, *, delimiters=('=', ':'), 603 comment_prefixes=('#', ';'), inline_comment_prefixes=None, 604 strict=True, empty_lines_in_values=True, 605 default_section=DEFAULTSECT, 606 interpolation=_UNSET, converters=_UNSET): 607 608 self._dict = dict_type 609 self._sections = self._dict() 610 self._defaults = self._dict() 611 self._converters = ConverterMapping(self) 612 self._proxies = self._dict() 613 self._proxies[default_section] = SectionProxy(self, default_section) 614 self._delimiters = tuple(delimiters) 615 if delimiters == ('=', ':'): 616 self._optcre = self.OPTCRE_NV if allow_no_value else self.OPTCRE 617 else: 618 d = "|".join(re.escape(d) for d in delimiters) 619 if allow_no_value: 620 self._optcre = re.compile(self._OPT_NV_TMPL.format(delim=d), 621 re.VERBOSE) 622 else: 623 self._optcre = re.compile(self._OPT_TMPL.format(delim=d), 624 re.VERBOSE) 625 self._comment_prefixes = tuple(comment_prefixes or ()) 626 self._inline_comment_prefixes = tuple(inline_comment_prefixes or ()) 627 self._strict = strict 628 self._allow_no_value = allow_no_value 629 self._empty_lines_in_values = empty_lines_in_values 630 self.default_section=default_section 631 self._interpolation = interpolation 632 if self._interpolation is _UNSET: 633 self._interpolation = self._DEFAULT_INTERPOLATION 634 if self._interpolation is None: 635 self._interpolation = Interpolation() 636 if converters is not _UNSET: 637 self._converters.update(converters) 638 if defaults: 639 self._read_defaults(defaults) 640 641 def defaults(self): 642 return self._defaults 643 644 def sections(self): 645 """Return a list of section names, excluding [DEFAULT]""" 646 # self._sections will never have [DEFAULT] in it 647 return list(self._sections.keys()) 648 649 def add_section(self, section): 650 """Create a new section in the configuration. 651 652 Raise DuplicateSectionError if a section by the specified name 653 already exists. Raise ValueError if name is DEFAULT. 654 """ 655 if section == self.default_section: 656 raise ValueError('Invalid section name: %r' % section) 657 658 if section in self._sections: 659 raise DuplicateSectionError(section) 660 self._sections[section] = self._dict() 661 self._proxies[section] = SectionProxy(self, section) 662 663 def has_section(self, section): 664 """Indicate whether the named section is present in the configuration. 665 666 The DEFAULT section is not acknowledged. 667 """ 668 return section in self._sections 669 670 def options(self, section): 671 """Return a list of option names for the given section name.""" 672 try: 673 opts = self._sections[section].copy() 674 except KeyError: 675 raise NoSectionError(section) from None 676 opts.update(self._defaults) 677 return list(opts.keys()) 678 679 def read(self, filenames, encoding=None): 680 """Read and parse a filename or an iterable of filenames. 681 682 Files that cannot be opened are silently ignored; this is 683 designed so that you can specify an iterable of potential 684 configuration file locations (e.g. current directory, user's 685 home directory, systemwide directory), and all existing 686 configuration files in the iterable will be read. A single 687 filename may also be given. 688 689 Return list of successfully read files. 690 """ 691 if isinstance(filenames, (str, bytes, os.PathLike)): 692 filenames = [filenames] 693 encoding = io.text_encoding(encoding) 694 read_ok = [] 695 for filename in filenames: 696 try: 697 with open(filename, encoding=encoding) as fp: 698 self._read(fp, filename) 699 except OSError: 700 continue 701 if isinstance(filename, os.PathLike): 702 filename = os.fspath(filename) 703 read_ok.append(filename) 704 return read_ok 705 706 def read_file(self, f, source=None): 707 """Like read() but the argument must be a file-like object. 708 709 The `f' argument must be iterable, returning one line at a time. 710 Optional second argument is the `source' specifying the name of the 711 file being read. If not given, it is taken from f.name. If `f' has no 712 `name' attribute, `<???>' is used. 713 """ 714 if source is None: 715 try: 716 source = f.name 717 except AttributeError: 718 source = '<???>' 719 self._read(f, source) 720 721 def read_string(self, string, source='<string>'): 722 """Read configuration from a given string.""" 723 sfile = io.StringIO(string) 724 self.read_file(sfile, source) 725 726 def read_dict(self, dictionary, source='<dict>'): 727 """Read configuration from a dictionary. 728 729 Keys are section names, values are dictionaries with keys and values 730 that should be present in the section. If the used dictionary type 731 preserves order, sections and their keys will be added in order. 732 733 All types held in the dictionary are converted to strings during 734 reading, including section names, option names and keys. 735 736 Optional second argument is the `source' specifying the name of the 737 dictionary being read. 738 """ 739 elements_added = set() 740 for section, keys in dictionary.items(): 741 section = str(section) 742 try: 743 self.add_section(section) 744 except (DuplicateSectionError, ValueError): 745 if self._strict and section in elements_added: 746 raise 747 elements_added.add(section) 748 for key, value in keys.items(): 749 key = self.optionxform(str(key)) 750 if value is not None: 751 value = str(value) 752 if self._strict and (section, key) in elements_added: 753 raise DuplicateOptionError(section, key, source) 754 elements_added.add((section, key)) 755 self.set(section, key, value) 756 757 def readfp(self, fp, filename=None): 758 """Deprecated, use read_file instead.""" 759 warnings.warn( 760 "This method will be removed in future versions. " 761 "Use 'parser.read_file()' instead.", 762 DeprecationWarning, stacklevel=2 763 ) 764 self.read_file(fp, source=filename) 765 766 def get(self, section, option, *, raw=False, vars=None, fallback=_UNSET): 767 """Get an option value for a given section. 768 769 If `vars' is provided, it must be a dictionary. The option is looked up 770 in `vars' (if provided), `section', and in `DEFAULTSECT' in that order. 771 If the key is not found and `fallback' is provided, it is used as 772 a fallback value. `None' can be provided as a `fallback' value. 773 774 If interpolation is enabled and the optional argument `raw' is False, 775 all interpolations are expanded in the return values. 776 777 Arguments `raw', `vars', and `fallback' are keyword only. 778 779 The section DEFAULT is special. 780 """ 781 try: 782 d = self._unify_values(section, vars) 783 except NoSectionError: 784 if fallback is _UNSET: 785 raise 786 else: 787 return fallback 788 option = self.optionxform(option) 789 try: 790 value = d[option] 791 except KeyError: 792 if fallback is _UNSET: 793 raise NoOptionError(option, section) 794 else: 795 return fallback 796 797 if raw or value is None: 798 return value 799 else: 800 return self._interpolation.before_get(self, section, option, value, 801 d) 802 803 def _get(self, section, conv, option, **kwargs): 804 return conv(self.get(section, option, **kwargs)) 805 806 def _get_conv(self, section, option, conv, *, raw=False, vars=None, 807 fallback=_UNSET, **kwargs): 808 try: 809 return self._get(section, conv, option, raw=raw, vars=vars, 810 **kwargs) 811 except (NoSectionError, NoOptionError): 812 if fallback is _UNSET: 813 raise 814 return fallback 815 816 # getint, getfloat and getboolean provided directly for backwards compat 817 def getint(self, section, option, *, raw=False, vars=None, 818 fallback=_UNSET, **kwargs): 819 return self._get_conv(section, option, int, raw=raw, vars=vars, 820 fallback=fallback, **kwargs) 821 822 def getfloat(self, section, option, *, raw=False, vars=None, 823 fallback=_UNSET, **kwargs): 824 return self._get_conv(section, option, float, raw=raw, vars=vars, 825 fallback=fallback, **kwargs) 826 827 def getboolean(self, section, option, *, raw=False, vars=None, 828 fallback=_UNSET, **kwargs): 829 return self._get_conv(section, option, self._convert_to_boolean, 830 raw=raw, vars=vars, fallback=fallback, **kwargs) 831 832 def items(self, section=_UNSET, raw=False, vars=None): 833 """Return a list of (name, value) tuples for each option in a section. 834 835 All % interpolations are expanded in the return values, based on the 836 defaults passed into the constructor, unless the optional argument 837 `raw' is true. Additional substitutions may be provided using the 838 `vars' argument, which must be a dictionary whose contents overrides 839 any pre-existing defaults. 840 841 The section DEFAULT is special. 842 """ 843 if section is _UNSET: 844 return super().items() 845 d = self._defaults.copy() 846 try: 847 d.update(self._sections[section]) 848 except KeyError: 849 if section != self.default_section: 850 raise NoSectionError(section) 851 orig_keys = list(d.keys()) 852 # Update with the entry specific variables 853 if vars: 854 for key, value in vars.items(): 855 d[self.optionxform(key)] = value 856 value_getter = lambda option: self._interpolation.before_get(self, 857 section, option, d[option], d) 858 if raw: 859 value_getter = lambda option: d[option] 860 return [(option, value_getter(option)) for option in orig_keys] 861 862 def popitem(self): 863 """Remove a section from the parser and return it as 864 a (section_name, section_proxy) tuple. If no section is present, raise 865 KeyError. 866 867 The section DEFAULT is never returned because it cannot be removed. 868 """ 869 for key in self.sections(): 870 value = self[key] 871 del self[key] 872 return key, value 873 raise KeyError 874 875 def optionxform(self, optionstr): 876 return optionstr.lower() 877 878 def has_option(self, section, option): 879 """Check for the existence of a given option in a given section. 880 If the specified `section' is None or an empty string, DEFAULT is 881 assumed. If the specified `section' does not exist, returns False.""" 882 if not section or section == self.default_section: 883 option = self.optionxform(option) 884 return option in self._defaults 885 elif section not in self._sections: 886 return False 887 else: 888 option = self.optionxform(option) 889 return (option in self._sections[section] 890 or option in self._defaults) 891 892 def set(self, section, option, value=None): 893 """Set an option.""" 894 if value: 895 value = self._interpolation.before_set(self, section, option, 896 value) 897 if not section or section == self.default_section: 898 sectdict = self._defaults 899 else: 900 try: 901 sectdict = self._sections[section] 902 except KeyError: 903 raise NoSectionError(section) from None 904 sectdict[self.optionxform(option)] = value 905 906 def write(self, fp, space_around_delimiters=True): 907 """Write an .ini-format representation of the configuration state. 908 909 If `space_around_delimiters' is True (the default), delimiters 910 between keys and values are surrounded by spaces. 911 912 Please note that comments in the original configuration file are not 913 preserved when writing the configuration back. 914 """ 915 if space_around_delimiters: 916 d = " {} ".format(self._delimiters[0]) 917 else: 918 d = self._delimiters[0] 919 if self._defaults: 920 self._write_section(fp, self.default_section, 921 self._defaults.items(), d) 922 for section in self._sections: 923 self._write_section(fp, section, 924 self._sections[section].items(), d) 925 926 def _write_section(self, fp, section_name, section_items, delimiter): 927 """Write a single section to the specified `fp'.""" 928 fp.write("[{}]\n".format(section_name)) 929 for key, value in section_items: 930 value = self._interpolation.before_write(self, section_name, key, 931 value) 932 if value is not None or not self._allow_no_value: 933 value = delimiter + str(value).replace('\n', '\n\t') 934 else: 935 value = "" 936 fp.write("{}{}\n".format(key, value)) 937 fp.write("\n") 938 939 def remove_option(self, section, option): 940 """Remove an option.""" 941 if not section or section == self.default_section: 942 sectdict = self._defaults 943 else: 944 try: 945 sectdict = self._sections[section] 946 except KeyError: 947 raise NoSectionError(section) from None 948 option = self.optionxform(option) 949 existed = option in sectdict 950 if existed: 951 del sectdict[option] 952 return existed 953 954 def remove_section(self, section): 955 """Remove a file section.""" 956 existed = section in self._sections 957 if existed: 958 del self._sections[section] 959 del self._proxies[section] 960 return existed 961 962 def __getitem__(self, key): 963 if key != self.default_section and not self.has_section(key): 964 raise KeyError(key) 965 return self._proxies[key] 966 967 def __setitem__(self, key, value): 968 # To conform with the mapping protocol, overwrites existing values in 969 # the section. 970 if key in self and self[key] is value: 971 return 972 # XXX this is not atomic if read_dict fails at any point. Then again, 973 # no update method in configparser is atomic in this implementation. 974 if key == self.default_section: 975 self._defaults.clear() 976 elif key in self._sections: 977 self._sections[key].clear() 978 self.read_dict({key: value}) 979 980 def __delitem__(self, key): 981 if key == self.default_section: 982 raise ValueError("Cannot remove the default section.") 983 if not self.has_section(key): 984 raise KeyError(key) 985 self.remove_section(key) 986 987 def __contains__(self, key): 988 return key == self.default_section or self.has_section(key) 989 990 def __len__(self): 991 return len(self._sections) + 1 # the default section 992 993 def __iter__(self): 994 # XXX does it break when underlying container state changed? 995 return itertools.chain((self.default_section,), self._sections.keys()) 996 997 def _read(self, fp, fpname): 998 """Parse a sectioned configuration file. 999 1000 Each section in a configuration file contains a header, indicated by 1001 a name in square brackets (`[]'), plus key/value options, indicated by 1002 `name' and `value' delimited with a specific substring (`=' or `:' by 1003 default). 1004 1005 Values can span multiple lines, as long as they are indented deeper 1006 than the first line of the value. Depending on the parser's mode, blank 1007 lines may be treated as parts of multiline values or ignored. 1008 1009 Configuration files may include comments, prefixed by specific 1010 characters (`#' and `;' by default). Comments may appear on their own 1011 in an otherwise empty line or may be entered in lines holding values or 1012 section names. Please note that comments get stripped off when reading configuration files. 1013 """ 1014 elements_added = set() 1015 cursect = None # None, or a dictionary 1016 sectname = None 1017 optname = None 1018 lineno = 0 1019 indent_level = 0 1020 e = None # None, or an exception 1021 for lineno, line in enumerate(fp, start=1): 1022 comment_start = sys.maxsize 1023 # strip inline comments 1024 inline_prefixes = {p: -1 for p in self._inline_comment_prefixes} 1025 while comment_start == sys.maxsize and inline_prefixes: 1026 next_prefixes = {} 1027 for prefix, index in inline_prefixes.items(): 1028 index = line.find(prefix, index+1) 1029 if index == -1: 1030 continue 1031 next_prefixes[prefix] = index 1032 if index == 0 or (index > 0 and line[index-1].isspace()): 1033 comment_start = min(comment_start, index) 1034 inline_prefixes = next_prefixes 1035 # strip full line comments 1036 for prefix in self._comment_prefixes: 1037 if line.strip().startswith(prefix): 1038 comment_start = 0 1039 break 1040 if comment_start == sys.maxsize: 1041 comment_start = None 1042 value = line[:comment_start].strip() 1043 if not value: 1044 if self._empty_lines_in_values: 1045 # add empty line to the value, but only if there was no 1046 # comment on the line 1047 if (comment_start is None and 1048 cursect is not None and 1049 optname and 1050 cursect[optname] is not None): 1051 cursect[optname].append('') # newlines added at join 1052 else: 1053 # empty line marks end of value 1054 indent_level = sys.maxsize 1055 continue 1056 # continuation line? 1057 first_nonspace = self.NONSPACECRE.search(line) 1058 cur_indent_level = first_nonspace.start() if first_nonspace else 0 1059 if (cursect is not None and optname and 1060 cur_indent_level > indent_level): 1061 cursect[optname].append(value) 1062 # a section header or option header? 1063 else: 1064 indent_level = cur_indent_level 1065 # is it a section header? 1066 mo = self.SECTCRE.match(value) 1067 if mo: 1068 sectname = mo.group('header') 1069 if sectname in self._sections: 1070 if self._strict and sectname in elements_added: 1071 raise DuplicateSectionError(sectname, fpname, 1072 lineno) 1073 cursect = self._sections[sectname] 1074 elements_added.add(sectname) 1075 elif sectname == self.default_section: 1076 cursect = self._defaults 1077 else: 1078 cursect = self._dict() 1079 self._sections[sectname] = cursect 1080 self._proxies[sectname] = SectionProxy(self, sectname) 1081 elements_added.add(sectname) 1082 # So sections can't start with a continuation line 1083 optname = None 1084 # no section header in the file? 1085 elif cursect is None: 1086 raise MissingSectionHeaderError(fpname, lineno, line) 1087 # an option line? 1088 else: 1089 mo = self._optcre.match(value) 1090 if mo: 1091 optname, vi, optval = mo.group('option', 'vi', 'value') 1092 if not optname: 1093 e = self._handle_error(e, fpname, lineno, line) 1094 optname = self.optionxform(optname.rstrip()) 1095 if (self._strict and 1096 (sectname, optname) in elements_added): 1097 raise DuplicateOptionError(sectname, optname, 1098 fpname, lineno) 1099 elements_added.add((sectname, optname)) 1100 # This check is fine because the OPTCRE cannot 1101 # match if it would set optval to None 1102 if optval is not None: 1103 optval = optval.strip() 1104 cursect[optname] = [optval] 1105 else: 1106 # valueless option handling 1107 cursect[optname] = None 1108 else: 1109 # a non-fatal parsing error occurred. set up the 1110 # exception but keep going. the exception will be 1111 # raised at the end of the file and will contain a 1112 # list of all bogus lines 1113 e = self._handle_error(e, fpname, lineno, line) 1114 self._join_multiline_values() 1115 # if any parsing errors occurred, raise an exception 1116 if e: 1117 raise e 1118 1119 def _join_multiline_values(self): 1120 defaults = self.default_section, self._defaults 1121 all_sections = itertools.chain((defaults,), 1122 self._sections.items()) 1123 for section, options in all_sections: 1124 for name, val in options.items(): 1125 if isinstance(val, list): 1126 val = '\n'.join(val).rstrip() 1127 options[name] = self._interpolation.before_read(self, 1128 section, 1129 name, val) 1130 1131 def _read_defaults(self, defaults): 1132 """Read the defaults passed in the initializer. 1133 Note: values can be non-string.""" 1134 for key, value in defaults.items(): 1135 self._defaults[self.optionxform(key)] = value 1136 1137 def _handle_error(self, exc, fpname, lineno, line): 1138 if not exc: 1139 exc = ParsingError(fpname) 1140 exc.append(lineno, repr(line)) 1141 return exc 1142 1143 def _unify_values(self, section, vars): 1144 """Create a sequence of lookups with 'vars' taking priority over 1145 the 'section' which takes priority over the DEFAULTSECT. 1146 1147 """ 1148 sectiondict = {} 1149 try: 1150 sectiondict = self._sections[section] 1151 except KeyError: 1152 if section != self.default_section: 1153 raise NoSectionError(section) from None 1154 # Update with the entry specific variables 1155 vardict = {} 1156 if vars: 1157 for key, value in vars.items(): 1158 if value is not None: 1159 value = str(value) 1160 vardict[self.optionxform(key)] = value 1161 return _ChainMap(vardict, sectiondict, self._defaults) 1162 1163 def _convert_to_boolean(self, value): 1164 """Return a boolean value translating from other types if necessary. 1165 """ 1166 if value.lower() not in self.BOOLEAN_STATES: 1167 raise ValueError('Not a boolean: %s' % value) 1168 return self.BOOLEAN_STATES[value.lower()] 1169 1170 def _validate_value_types(self, *, section="", option="", value=""): 1171 """Raises a TypeError for non-string values. 1172 1173 The only legal non-string value if we allow valueless 1174 options is None, so we need to check if the value is a 1175 string if: 1176 - we do not allow valueless options, or 1177 - we allow valueless options but the value is not None 1178 1179 For compatibility reasons this method is not used in classic set() 1180 for RawConfigParsers. It is invoked in every case for mapping protocol 1181 access and in ConfigParser.set(). 1182 """ 1183 if not isinstance(section, str): 1184 raise TypeError("section names must be strings") 1185 if not isinstance(option, str): 1186 raise TypeError("option keys must be strings") 1187 if not self._allow_no_value or value: 1188 if not isinstance(value, str): 1189 raise TypeError("option values must be strings") 1190 1191 @property 1192 def converters(self): 1193 return self._converters 1194 1195 1196class ConfigParser(RawConfigParser): 1197 """ConfigParser implementing interpolation.""" 1198 1199 _DEFAULT_INTERPOLATION = BasicInterpolation() 1200 1201 def set(self, section, option, value=None): 1202 """Set an option. Extends RawConfigParser.set by validating type and 1203 interpolation syntax on the value.""" 1204 self._validate_value_types(option=option, value=value) 1205 super().set(section, option, value) 1206 1207 def add_section(self, section): 1208 """Create a new section in the configuration. Extends 1209 RawConfigParser.add_section by validating if the section name is 1210 a string.""" 1211 self._validate_value_types(section=section) 1212 super().add_section(section) 1213 1214 def _read_defaults(self, defaults): 1215 """Reads the defaults passed in the initializer, implicitly converting 1216 values to strings like the rest of the API. 1217 1218 Does not perform interpolation for backwards compatibility. 1219 """ 1220 try: 1221 hold_interpolation = self._interpolation 1222 self._interpolation = Interpolation() 1223 self.read_dict({self.default_section: defaults}) 1224 finally: 1225 self._interpolation = hold_interpolation 1226 1227 1228class SafeConfigParser(ConfigParser): 1229 """ConfigParser alias for backwards compatibility purposes.""" 1230 1231 def __init__(self, *args, **kwargs): 1232 super().__init__(*args, **kwargs) 1233 warnings.warn( 1234 "The SafeConfigParser class has been renamed to ConfigParser " 1235 "in Python 3.2. This alias will be removed in future versions." 1236 " Use ConfigParser directly instead.", 1237 DeprecationWarning, stacklevel=2 1238 ) 1239 1240 1241class SectionProxy(MutableMapping): 1242 """A proxy for a single section from a parser.""" 1243 1244 def __init__(self, parser, name): 1245 """Creates a view on a section of the specified `name` in `parser`.""" 1246 self._parser = parser 1247 self._name = name 1248 for conv in parser.converters: 1249 key = 'get' + conv 1250 getter = functools.partial(self.get, _impl=getattr(parser, key)) 1251 setattr(self, key, getter) 1252 1253 def __repr__(self): 1254 return '<Section: {}>'.format(self._name) 1255 1256 def __getitem__(self, key): 1257 if not self._parser.has_option(self._name, key): 1258 raise KeyError(key) 1259 return self._parser.get(self._name, key) 1260 1261 def __setitem__(self, key, value): 1262 self._parser._validate_value_types(option=key, value=value) 1263 return self._parser.set(self._name, key, value) 1264 1265 def __delitem__(self, key): 1266 if not (self._parser.has_option(self._name, key) and 1267 self._parser.remove_option(self._name, key)): 1268 raise KeyError(key) 1269 1270 def __contains__(self, key): 1271 return self._parser.has_option(self._name, key) 1272 1273 def __len__(self): 1274 return len(self._options()) 1275 1276 def __iter__(self): 1277 return self._options().__iter__() 1278 1279 def _options(self): 1280 if self._name != self._parser.default_section: 1281 return self._parser.options(self._name) 1282 else: 1283 return self._parser.defaults() 1284 1285 @property 1286 def parser(self): 1287 # The parser object of the proxy is read-only. 1288 return self._parser 1289 1290 @property 1291 def name(self): 1292 # The name of the section on a proxy is read-only. 1293 return self._name 1294 1295 def get(self, option, fallback=None, *, raw=False, vars=None, 1296 _impl=None, **kwargs): 1297 """Get an option value. 1298 1299 Unless `fallback` is provided, `None` will be returned if the option 1300 is not found. 1301 1302 """ 1303 # If `_impl` is provided, it should be a getter method on the parser 1304 # object that provides the desired type conversion. 1305 if not _impl: 1306 _impl = self._parser.get 1307 return _impl(self._name, option, raw=raw, vars=vars, 1308 fallback=fallback, **kwargs) 1309 1310 1311class ConverterMapping(MutableMapping): 1312 """Enables reuse of get*() methods between the parser and section proxies. 1313 1314 If a parser class implements a getter directly, the value for the given 1315 key will be ``None``. The presence of the converter name here enables 1316 section proxies to find and use the implementation on the parser class. 1317 """ 1318 1319 GETTERCRE = re.compile(r"^get(?P<name>.+)$") 1320 1321 def __init__(self, parser): 1322 self._parser = parser 1323 self._data = {} 1324 for getter in dir(self._parser): 1325 m = self.GETTERCRE.match(getter) 1326 if not m or not callable(getattr(self._parser, getter)): 1327 continue 1328 self._data[m.group('name')] = None # See class docstring. 1329 1330 def __getitem__(self, key): 1331 return self._data[key] 1332 1333 def __setitem__(self, key, value): 1334 try: 1335 k = 'get' + key 1336 except TypeError: 1337 raise ValueError('Incompatible key: {} (type: {})' 1338 ''.format(key, type(key))) 1339 if k == 'get': 1340 raise ValueError('Incompatible key: cannot use "" as a name') 1341 self._data[key] = value 1342 func = functools.partial(self._parser._get_conv, conv=value) 1343 func.converter = value 1344 setattr(self._parser, k, func) 1345 for proxy in self._parser.values(): 1346 getter = functools.partial(proxy.get, _impl=func) 1347 setattr(proxy, k, getter) 1348 1349 def __delitem__(self, key): 1350 try: 1351 k = 'get' + (key or None) 1352 except TypeError: 1353 raise KeyError(key) 1354 del self._data[key] 1355 for inst in itertools.chain((self._parser,), self._parser.values()): 1356 try: 1357 delattr(inst, k) 1358 except AttributeError: 1359 # don't raise since the entry was present in _data, silently 1360 # clean up 1361 continue 1362 1363 def __iter__(self): 1364 return iter(self._data) 1365 1366 def __len__(self): 1367 return len(self._data) 1368