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