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