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