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