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