lmgsanm

每天学习一点,每天进步一点点…… Tomorrow is another beatifull day

导航

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)

 

posted on 2018-01-30 19:03  lmgsanm  阅读(1364)  评论(0编辑  收藏  举报