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