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