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