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