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 read_ok = [] 694 for filename in filenames: 695 try: 696 with open(filename, encoding=encoding) as fp: 697 self._read(fp, filename) 698 except OSError: 699 continue 700 if isinstance(filename, os.PathLike): 701 filename = os.fspath(filename) 702 read_ok.append(filename) 703 return read_ok 704 705 def read_file(self, f, source=None): 706 """Like read() but the argument must be a file-like object. 707 708 The `f' argument must be iterable, returning one line at a time. 709 Optional second argument is the `source' specifying the name of the 710 file being read. If not given, it is taken from f.name. If `f' has no 711 `name' attribute, `<???>' is used. 712 """ 713 if source is None: 714 try: 715 source = f.name 716 except AttributeError: 717 source = '<???>' 718 self._read(f, source) 719 720 def read_string(self, string, source='<string>'): 721 """Read configuration from a given string.""" 722 sfile = io.StringIO(string) 723 self.read_file(sfile, source) 724 725 def read_dict(self, dictionary, source='<dict>'): 726 """Read configuration from a dictionary. 727 728 Keys are section names, values are dictionaries with keys and values 729 that should be present in the section. If the used dictionary type 730 preserves order, sections and their keys will be added in order. 731 732 All types held in the dictionary are converted to strings during 733 reading, including section names, option names and keys. 734 735 Optional second argument is the `source' specifying the name of the 736 dictionary being read. 737 """ 738 elements_added = set() 739 for section, keys in dictionary.items(): 740 section = str(section) 741 try: 742 self.add_section(section) 743 except (DuplicateSectionError, ValueError): 744 if self._strict and section in elements_added: 745 raise 746 elements_added.add(section) 747 for key, value in keys.items(): 748 key = self.optionxform(str(key)) 749 if value is not None: 750 value = str(value) 751 if self._strict and (section, key) in elements_added: 752 raise DuplicateOptionError(section, key, source) 753 elements_added.add((section, key)) 754 self.set(section, key, value) 755 756 def readfp(self, fp, filename=None): 757 """Deprecated, use read_file instead.""" 758 warnings.warn( 759 "This method will be removed in future versions. " 760 "Use 'parser.read_file()' instead.", 761 DeprecationWarning, stacklevel=2 762 ) 763 self.read_file(fp, source=filename) 764 765 def get(self, section, option, *, raw=False, vars=None, fallback=_UNSET): 766 """Get an option value for a given section. 767 768 If `vars' is provided, it must be a dictionary. The option is looked up 769 in `vars' (if provided), `section', and in `DEFAULTSECT' in that order. 770 If the key is not found and `fallback' is provided, it is used as 771 a fallback value. `None' can be provided as a `fallback' value. 772 773 If interpolation is enabled and the optional argument `raw' is False, 774 all interpolations are expanded in the return values. 775 776 Arguments `raw', `vars', and `fallback' are keyword only. 777 778 The section DEFAULT is special. 779 """ 780 try: 781 d = self._unify_values(section, vars) 782 except NoSectionError: 783 if fallback is _UNSET: 784 raise 785 else: 786 return fallback 787 option = self.optionxform(option) 788 try: 789 value = d[option] 790 except KeyError: 791 if fallback is _UNSET: 792 raise NoOptionError(option, section) 793 else: 794 return fallback 795 796 if raw or value is None: 797 return value 798 else: 799 return self._interpolation.before_get(self, section, option, value, 800 d) 801 802 def _get(self, section, conv, option, **kwargs): 803 return conv(self.get(section, option, **kwargs)) 804 805 def _get_conv(self, section, option, conv, *, raw=False, vars=None, 806 fallback=_UNSET, **kwargs): 807 try: 808 return self._get(section, conv, option, raw=raw, vars=vars, 809 **kwargs) 810 except (NoSectionError, NoOptionError): 811 if fallback is _UNSET: 812 raise 813 return fallback 814 815 # getint, getfloat and getboolean provided directly for backwards compat 816 def getint(self, section, option, *, raw=False, vars=None, 817 fallback=_UNSET, **kwargs): 818 return self._get_conv(section, option, int, raw=raw, vars=vars, 819 fallback=fallback, **kwargs) 820 821 def getfloat(self, section, option, *, raw=False, vars=None, 822 fallback=_UNSET, **kwargs): 823 return self._get_conv(section, option, float, raw=raw, vars=vars, 824 fallback=fallback, **kwargs) 825 826 def getboolean(self, section, option, *, raw=False, vars=None, 827 fallback=_UNSET, **kwargs): 828 return self._get_conv(section, option, self._convert_to_boolean, 829 raw=raw, vars=vars, fallback=fallback, **kwargs) 830 831 def items(self, section=_UNSET, raw=False, vars=None): 832 """Return a list of (name, value) tuples for each option in a section. 833 834 All % interpolations are expanded in the return values, based on the 835 defaults passed into the constructor, unless the optional argument 836 `raw' is true. Additional substitutions may be provided using the 837 `vars' argument, which must be a dictionary whose contents overrides 838 any pre-existing defaults. 839 840 The section DEFAULT is special. 841 """ 842 if section is _UNSET: 843 return super().items() 844 d = self._defaults.copy() 845 try: 846 d.update(self._sections[section]) 847 except KeyError: 848 if section != self.default_section: 849 raise NoSectionError(section) 850 orig_keys = list(d.keys()) 851 # Update with the entry specific variables 852 if vars: 853 for key, value in vars.items(): 854 d[self.optionxform(key)] = value 855 value_getter = lambda option: self._interpolation.before_get(self, 856 section, option, d[option], d) 857 if raw: 858 value_getter = lambda option: d[option] 859 return [(option, value_getter(option)) for option in orig_keys] 860 861 def popitem(self): 862 """Remove a section from the parser and return it as 863 a (section_name, section_proxy) tuple. If no section is present, raise 864 KeyError. 865 866 The section DEFAULT is never returned because it cannot be removed. 867 """ 868 for key in self.sections(): 869 value = self[key] 870 del self[key] 871 return key, value 872 raise KeyError 873 874 def optionxform(self, optionstr): 875 return optionstr.lower() 876 877 def has_option(self, section, option): 878 """Check for the existence of a given option in a given section. 879 If the specified `section' is None or an empty string, DEFAULT is 880 assumed. If the specified `section' does not exist, returns False.""" 881 if not section or section == self.default_section: 882 option = self.optionxform(option) 883 return option in self._defaults 884 elif section not in self._sections: 885 return False 886 else: 887 option = self.optionxform(option) 888 return (option in self._sections[section] 889 or option in self._defaults) 890 891 def set(self, section, option, value=None): 892 """Set an option.""" 893 if value: 894 value = self._interpolation.before_set(self, section, option, 895 value) 896 if not section or section == self.default_section: 897 sectdict = self._defaults 898 else: 899 try: 900 sectdict = self._sections[section] 901 except KeyError: 902 raise NoSectionError(section) from None 903 sectdict[self.optionxform(option)] = value 904 905 def write(self, fp, space_around_delimiters=True): 906 """Write an .ini-format representation of the configuration state. 907 908 If `space_around_delimiters' is True (the default), delimiters 909 between keys and values are surrounded by spaces. 910 """ 911 if space_around_delimiters: 912 d = " {} ".format(self._delimiters[0]) 913 else: 914 d = self._delimiters[0] 915 if self._defaults: 916 self._write_section(fp, self.default_section, 917 self._defaults.items(), d) 918 for section in self._sections: 919 self._write_section(fp, section, 920 self._sections[section].items(), d) 921 922 def _write_section(self, fp, section_name, section_items, delimiter): 923 """Write a single section to the specified `fp'.""" 924 fp.write("[{}]\n".format(section_name)) 925 for key, value in section_items: 926 value = self._interpolation.before_write(self, section_name, key, 927 value) 928 if value is not None or not self._allow_no_value: 929 value = delimiter + str(value).replace('\n', '\n\t') 930 else: 931 value = "" 932 fp.write("{}{}\n".format(key, value)) 933 fp.write("\n") 934 935 def remove_option(self, section, option): 936 """Remove an option.""" 937 if not section or section == self.default_section: 938 sectdict = self._defaults 939 else: 940 try: 941 sectdict = self._sections[section] 942 except KeyError: 943 raise NoSectionError(section) from None 944 option = self.optionxform(option) 945 existed = option in sectdict 946 if existed: 947 del sectdict[option] 948 return existed 949 950 def remove_section(self, section): 951 """Remove a file section.""" 952 existed = section in self._sections 953 if existed: 954 del self._sections[section] 955 del self._proxies[section] 956 return existed 957 958 def __getitem__(self, key): 959 if key != self.default_section and not self.has_section(key): 960 raise KeyError(key) 961 return self._proxies[key] 962 963 def __setitem__(self, key, value): 964 # To conform with the mapping protocol, overwrites existing values in 965 # the section. 966 if key in self and self[key] is value: 967 return 968 # XXX this is not atomic if read_dict fails at any point. Then again, 969 # no update method in configparser is atomic in this implementation. 970 if key == self.default_section: 971 self._defaults.clear() 972 elif key in self._sections: 973 self._sections[key].clear() 974 self.read_dict({key: value}) 975 976 def __delitem__(self, key): 977 if key == self.default_section: 978 raise ValueError("Cannot remove the default section.") 979 if not self.has_section(key): 980 raise KeyError(key) 981 self.remove_section(key) 982 983 def __contains__(self, key): 984 return key == self.default_section or self.has_section(key) 985 986 def __len__(self): 987 return len(self._sections) + 1 # the default section 988 989 def __iter__(self): 990 # XXX does it break when underlying container state changed? 991 return itertools.chain((self.default_section,), self._sections.keys()) 992 993 def _read(self, fp, fpname): 994 """Parse a sectioned configuration file. 995 996 Each section in a configuration file contains a header, indicated by 997 a name in square brackets (`[]'), plus key/value options, indicated by 998 `name' and `value' delimited with a specific substring (`=' or `:' by 999 default). 1000 1001 Values can span multiple lines, as long as they are indented deeper 1002 than the first line of the value. Depending on the parser's mode, blank 1003 lines may be treated as parts of multiline values or ignored. 1004 1005 Configuration files may include comments, prefixed by specific 1006 characters (`#' and `;' by default). Comments may appear on their own 1007 in an otherwise empty line or may be entered in lines holding values or 1008 section names. 1009 """ 1010 elements_added = set() 1011 cursect = None # None, or a dictionary 1012 sectname = None 1013 optname = None 1014 lineno = 0 1015 indent_level = 0 1016 e = None # None, or an exception 1017 for lineno, line in enumerate(fp, start=1): 1018 comment_start = sys.maxsize 1019 # strip inline comments 1020 inline_prefixes = {p: -1 for p in self._inline_comment_prefixes} 1021 while comment_start == sys.maxsize and inline_prefixes: 1022 next_prefixes = {} 1023 for prefix, index in inline_prefixes.items(): 1024 index = line.find(prefix, index+1) 1025 if index == -1: 1026 continue 1027 next_prefixes[prefix] = index 1028 if index == 0 or (index > 0 and line[index-1].isspace()): 1029 comment_start = min(comment_start, index) 1030 inline_prefixes = next_prefixes 1031 # strip full line comments 1032 for prefix in self._comment_prefixes: 1033 if line.strip().startswith(prefix): 1034 comment_start = 0 1035 break 1036 if comment_start == sys.maxsize: 1037 comment_start = None 1038 value = line[:comment_start].strip() 1039 if not value: 1040 if self._empty_lines_in_values: 1041 # add empty line to the value, but only if there was no 1042 # comment on the line 1043 if (comment_start is None and 1044 cursect is not None and 1045 optname and 1046 cursect[optname] is not None): 1047 cursect[optname].append('') # newlines added at join 1048 else: 1049 # empty line marks end of value 1050 indent_level = sys.maxsize 1051 continue 1052 # continuation line? 1053 first_nonspace = self.NONSPACECRE.search(line) 1054 cur_indent_level = first_nonspace.start() if first_nonspace else 0 1055 if (cursect is not None and optname and 1056 cur_indent_level > indent_level): 1057 cursect[optname].append(value) 1058 # a section header or option header? 1059 else: 1060 indent_level = cur_indent_level 1061 # is it a section header? 1062 mo = self.SECTCRE.match(value) 1063 if mo: 1064 sectname = mo.group('header') 1065 if sectname in self._sections: 1066 if self._strict and sectname in elements_added: 1067 raise DuplicateSectionError(sectname, fpname, 1068 lineno) 1069 cursect = self._sections[sectname] 1070 elements_added.add(sectname) 1071 elif sectname == self.default_section: 1072 cursect = self._defaults 1073 else: 1074 cursect = self._dict() 1075 self._sections[sectname] = cursect 1076 self._proxies[sectname] = SectionProxy(self, sectname) 1077 elements_added.add(sectname) 1078 # So sections can't start with a continuation line 1079 optname = None 1080 # no section header in the file? 1081 elif cursect is None: 1082 raise MissingSectionHeaderError(fpname, lineno, line) 1083 # an option line? 1084 else: 1085 mo = self._optcre.match(value) 1086 if mo: 1087 optname, vi, optval = mo.group('option', 'vi', 'value') 1088 if not optname: 1089 e = self._handle_error(e, fpname, lineno, line) 1090 optname = self.optionxform(optname.rstrip()) 1091 if (self._strict and 1092 (sectname, optname) in elements_added): 1093 raise DuplicateOptionError(sectname, optname, 1094 fpname, lineno) 1095 elements_added.add((sectname, optname)) 1096 # This check is fine because the OPTCRE cannot 1097 # match if it would set optval to None 1098 if optval is not None: 1099 optval = optval.strip() 1100 cursect[optname] = [optval] 1101 else: 1102 # valueless option handling 1103 cursect[optname] = None 1104 else: 1105 # a non-fatal parsing error occurred. set up the 1106 # exception but keep going. the exception will be 1107 # raised at the end of the file and will contain a 1108 # list of all bogus lines 1109 e = self._handle_error(e, fpname, lineno, line) 1110 self._join_multiline_values() 1111 # if any parsing errors occurred, raise an exception 1112 if e: 1113 raise e 1114 1115 def _join_multiline_values(self): 1116 defaults = self.default_section, self._defaults 1117 all_sections = itertools.chain((defaults,), 1118 self._sections.items()) 1119 for section, options in all_sections: 1120 for name, val in options.items(): 1121 if isinstance(val, list): 1122 val = '\n'.join(val).rstrip() 1123 options[name] = self._interpolation.before_read(self, 1124 section, 1125 name, val) 1126 1127 def _read_defaults(self, defaults): 1128 """Read the defaults passed in the initializer. 1129 Note: values can be non-string.""" 1130 for key, value in defaults.items(): 1131 self._defaults[self.optionxform(key)] = value 1132 1133 def _handle_error(self, exc, fpname, lineno, line): 1134 if not exc: 1135 exc = ParsingError(fpname) 1136 exc.append(lineno, repr(line)) 1137 return exc 1138 1139 def _unify_values(self, section, vars): 1140 """Create a sequence of lookups with 'vars' taking priority over 1141 the 'section' which takes priority over the DEFAULTSECT. 1142 1143 """ 1144 sectiondict = {} 1145 try: 1146 sectiondict = self._sections[section] 1147 except KeyError: 1148 if section != self.default_section: 1149 raise NoSectionError(section) from None 1150 # Update with the entry specific variables 1151 vardict = {} 1152 if vars: 1153 for key, value in vars.items(): 1154 if value is not None: 1155 value = str(value) 1156 vardict[self.optionxform(key)] = value 1157 return _ChainMap(vardict, sectiondict, self._defaults) 1158 1159 def _convert_to_boolean(self, value): 1160 """Return a boolean value translating from other types if necessary. 1161 """ 1162 if value.lower() not in self.BOOLEAN_STATES: 1163 raise ValueError('Not a boolean: %s' % value) 1164 return self.BOOLEAN_STATES[value.lower()] 1165 1166 def _validate_value_types(self, *, section="", option="", value=""): 1167 """Raises a TypeError for non-string values. 1168 1169 The only legal non-string value if we allow valueless 1170 options is None, so we need to check if the value is a 1171 string if: 1172 - we do not allow valueless options, or 1173 - we allow valueless options but the value is not None 1174 1175 For compatibility reasons this method is not used in classic set() 1176 for RawConfigParsers. It is invoked in every case for mapping protocol 1177 access and in ConfigParser.set(). 1178 """ 1179 if not isinstance(section, str): 1180 raise TypeError("section names must be strings") 1181 if not isinstance(option, str): 1182 raise TypeError("option keys must be strings") 1183 if not self._allow_no_value or value: 1184 if not isinstance(value, str): 1185 raise TypeError("option values must be strings") 1186 1187 @property 1188 def converters(self): 1189 return self._converters 1190 1191 1192class ConfigParser(RawConfigParser): 1193 """ConfigParser implementing interpolation.""" 1194 1195 _DEFAULT_INTERPOLATION = BasicInterpolation() 1196 1197 def set(self, section, option, value=None): 1198 """Set an option. Extends RawConfigParser.set by validating type and 1199 interpolation syntax on the value.""" 1200 self._validate_value_types(option=option, value=value) 1201 super().set(section, option, value) 1202 1203 def add_section(self, section): 1204 """Create a new section in the configuration. Extends 1205 RawConfigParser.add_section by validating if the section name is 1206 a string.""" 1207 self._validate_value_types(section=section) 1208 super().add_section(section) 1209 1210 def _read_defaults(self, defaults): 1211 """Reads the defaults passed in the initializer, implicitly converting 1212 values to strings like the rest of the API. 1213 1214 Does not perform interpolation for backwards compatibility. 1215 """ 1216 try: 1217 hold_interpolation = self._interpolation 1218 self._interpolation = Interpolation() 1219 self.read_dict({self.default_section: defaults}) 1220 finally: 1221 self._interpolation = hold_interpolation 1222 1223 1224class SafeConfigParser(ConfigParser): 1225 """ConfigParser alias for backwards compatibility purposes.""" 1226 1227 def __init__(self, *args, **kwargs): 1228 super().__init__(*args, **kwargs) 1229 warnings.warn( 1230 "The SafeConfigParser class has been renamed to ConfigParser " 1231 "in Python 3.2. This alias will be removed in future versions." 1232 " Use ConfigParser directly instead.", 1233 DeprecationWarning, stacklevel=2 1234 ) 1235 1236 1237class SectionProxy(MutableMapping): 1238 """A proxy for a single section from a parser.""" 1239 1240 def __init__(self, parser, name): 1241 """Creates a view on a section of the specified `name` in `parser`.""" 1242 self._parser = parser 1243 self._name = name 1244 for conv in parser.converters: 1245 key = 'get' + conv 1246 getter = functools.partial(self.get, _impl=getattr(parser, key)) 1247 setattr(self, key, getter) 1248 1249 def __repr__(self): 1250 return '<Section: {}>'.format(self._name) 1251 1252 def __getitem__(self, key): 1253 if not self._parser.has_option(self._name, key): 1254 raise KeyError(key) 1255 return self._parser.get(self._name, key) 1256 1257 def __setitem__(self, key, value): 1258 self._parser._validate_value_types(option=key, value=value) 1259 return self._parser.set(self._name, key, value) 1260 1261 def __delitem__(self, key): 1262 if not (self._parser.has_option(self._name, key) and 1263 self._parser.remove_option(self._name, key)): 1264 raise KeyError(key) 1265 1266 def __contains__(self, key): 1267 return self._parser.has_option(self._name, key) 1268 1269 def __len__(self): 1270 return len(self._options()) 1271 1272 def __iter__(self): 1273 return self._options().__iter__() 1274 1275 def _options(self): 1276 if self._name != self._parser.default_section: 1277 return self._parser.options(self._name) 1278 else: 1279 return self._parser.defaults() 1280 1281 @property 1282 def parser(self): 1283 # The parser object of the proxy is read-only. 1284 return self._parser 1285 1286 @property 1287 def name(self): 1288 # The name of the section on a proxy is read-only. 1289 return self._name 1290 1291 def get(self, option, fallback=None, *, raw=False, vars=None, 1292 _impl=None, **kwargs): 1293 """Get an option value. 1294 1295 Unless `fallback` is provided, `None` will be returned if the option 1296 is not found. 1297 1298 """ 1299 # If `_impl` is provided, it should be a getter method on the parser 1300 # object that provides the desired type conversion. 1301 if not _impl: 1302 _impl = self._parser.get 1303 return _impl(self._name, option, raw=raw, vars=vars, 1304 fallback=fallback, **kwargs) 1305 1306 1307class ConverterMapping(MutableMapping): 1308 """Enables reuse of get*() methods between the parser and section proxies. 1309 1310 If a parser class implements a getter directly, the value for the given 1311 key will be ``None``. The presence of the converter name here enables 1312 section proxies to find and use the implementation on the parser class. 1313 """ 1314 1315 GETTERCRE = re.compile(r"^get(?P<name>.+)$") 1316 1317 def __init__(self, parser): 1318 self._parser = parser 1319 self._data = {} 1320 for getter in dir(self._parser): 1321 m = self.GETTERCRE.match(getter) 1322 if not m or not callable(getattr(self._parser, getter)): 1323 continue 1324 self._data[m.group('name')] = None # See class docstring. 1325 1326 def __getitem__(self, key): 1327 return self._data[key] 1328 1329 def __setitem__(self, key, value): 1330 try: 1331 k = 'get' + key 1332 except TypeError: 1333 raise ValueError('Incompatible key: {} (type: {})' 1334 ''.format(key, type(key))) 1335 if k == 'get': 1336 raise ValueError('Incompatible key: cannot use "" as a name') 1337 self._data[key] = value 1338 func = functools.partial(self._parser._get_conv, conv=value) 1339 func.converter = value 1340 setattr(self._parser, k, func) 1341 for proxy in self._parser.values(): 1342 getter = functools.partial(proxy.get, _impl=func) 1343 setattr(proxy, k, getter) 1344 1345 def __delitem__(self, key): 1346 try: 1347 k = 'get' + (key or None) 1348 except TypeError: 1349 raise KeyError(key) 1350 del self._data[key] 1351 for inst in itertools.chain((self._parser,), self._parser.values()): 1352 try: 1353 delattr(inst, k) 1354 except AttributeError: 1355 # don't raise since the entry was present in _data, silently 1356 # clean up 1357 continue 1358 1359 def __iter__(self): 1360 return iter(self._data) 1361 1362 def __len__(self): 1363 return len(self._data) 1364