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