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