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