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