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