~bzr-pqm/bzr/bzr.dev

1185.12.49 by Aaron Bentley
Switched to ConfigObj
1
# configobj.py
2
# A config file reader/writer that supports nested sections in config files.
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
3
# Copyright (C) 2005-2008 Michael Foord, Nicola Larosa
1185.12.49 by Aaron Bentley
Switched to ConfigObj
4
# E-mail: fuzzyman AT voidspace DOT org DOT uk
5
#         nico AT tekNico DOT net
6
7
# ConfigObj 4
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
8
# http://www.voidspace.org.uk/python/configobj.html
1185.12.49 by Aaron Bentley
Switched to ConfigObj
9
10
# Released subject to the BSD License
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
11
# Please see http://www.voidspace.org.uk/python/license.shtml
1185.12.49 by Aaron Bentley
Switched to ConfigObj
12
13
# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml
14
# For information about bugfixes, updates and support, please join the
15
# ConfigObj mailing list:
16
# http://lists.sourceforge.net/lists/listinfo/configobj-develop
17
# Comments, suggestions and bug reports welcome.
18
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
19
from __future__ import generators
20
1185.12.49 by Aaron Bentley
Switched to ConfigObj
21
import sys
22
INTP_VER = sys.version_info[:2]
23
if INTP_VER < (2, 2):
24
    raise RuntimeError("Python v.2.2 or later needed")
25
26
import os, re
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
27
compiler = None
3224.5.35 by Andrew Bennetts
More improvements suggested by John's review.
28
# Bzr modification: Disabled import of 'compiler' module
29
# bzr doesn't use the 'unrepr' feature of configobj, so importing compiler just
30
# wastes several milliseconds on every single bzr invocation.
31
#   -- Andrew Bennetts, 2008-10-14
32
#try:
33
#    import compiler
34
#except ImportError:
35
#    # for IronPython
36
#    pass
1185.12.49 by Aaron Bentley
Switched to ConfigObj
37
from types import StringTypes
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
38
from warnings import warn
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
39
try:
40
    from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE
41
except ImportError:
42
    # Python 2.2 does not have these
43
    # UTF-8
44
    BOM_UTF8 = '\xef\xbb\xbf'
45
    # UTF-16, little endian
46
    BOM_UTF16_LE = '\xff\xfe'
47
    # UTF-16, big endian
48
    BOM_UTF16_BE = '\xfe\xff'
49
    if sys.byteorder == 'little':
50
        # UTF-16, native endianness
51
        BOM_UTF16 = BOM_UTF16_LE
52
    else:
53
        # UTF-16, native endianness
54
        BOM_UTF16 = BOM_UTF16_BE
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
55
56
# A dictionary mapping BOM to
57
# the encoding to decode with, and what to set the
58
# encoding attribute to.
59
BOMS = {
60
    BOM_UTF8: ('utf_8', None),
61
    BOM_UTF16_BE: ('utf16_be', 'utf_16'),
62
    BOM_UTF16_LE: ('utf16_le', 'utf_16'),
63
    BOM_UTF16: ('utf_16', 'utf_16'),
64
    }
65
# All legal variants of the BOM codecs.
66
# TODO: the list of aliases is not meant to be exhaustive, is there a
67
#   better way ?
68
BOM_LIST = {
69
    'utf_16': 'utf_16',
70
    'u16': 'utf_16',
71
    'utf16': 'utf_16',
72
    'utf-16': 'utf_16',
73
    'utf16_be': 'utf16_be',
74
    'utf_16_be': 'utf16_be',
75
    'utf-16be': 'utf16_be',
76
    'utf16_le': 'utf16_le',
77
    'utf_16_le': 'utf16_le',
78
    'utf-16le': 'utf16_le',
79
    'utf_8': 'utf_8',
80
    'u8': 'utf_8',
81
    'utf': 'utf_8',
82
    'utf8': 'utf_8',
83
    'utf-8': 'utf_8',
84
    }
85
86
# Map of encodings to the BOM to write.
87
BOM_SET = {
88
    'utf_8': BOM_UTF8,
89
    'utf_16': BOM_UTF16,
90
    'utf16_be': BOM_UTF16_BE,
91
    'utf16_le': BOM_UTF16_LE,
92
    None: BOM_UTF8
93
    }
94
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
95
96
def match_utf8(encoding):
97
    return BOM_LIST.get(encoding.lower()) == 'utf_8'
98
99
100
# Quote strings used for writing values
101
squot = "'%s'"
102
dquot = '"%s"'
103
noquot = "%s"
104
wspace_plus = ' \r\t\n\v\t\'"'
105
tsquot = '"""%s"""'
106
tdquot = "'''%s'''"
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
107
108
try:
109
    enumerate
110
except NameError:
111
    def enumerate(obj):
112
        """enumerate for Python 2.2."""
113
        i = -1
114
        for item in obj:
115
            i += 1
116
            yield i, item
117
118
try:
119
    True, False
120
except NameError:
121
    True, False = 1, 0
122
123
3239.1.1 by Matt Nordhoff
Upgrade ConfigObj to 4.5.2.
124
__version__ = '4.5.2'
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
125
126
__revision__ = '$Id: configobj.py 156 2006-01-31 14:57:08Z fuzzyman $'
1185.12.49 by Aaron Bentley
Switched to ConfigObj
127
128
__docformat__ = "restructuredtext en"
129
130
__all__ = (
131
    '__version__',
132
    'DEFAULT_INDENT_TYPE',
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
133
    'DEFAULT_INTERPOLATION',
1185.12.49 by Aaron Bentley
Switched to ConfigObj
134
    'ConfigObjError',
135
    'NestingError',
136
    'ParseError',
137
    'DuplicateError',
138
    'ConfigspecError',
139
    'ConfigObj',
140
    'SimpleVal',
141
    'InterpolationError',
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
142
    'InterpolationLoopError',
1185.12.49 by Aaron Bentley
Switched to ConfigObj
143
    'MissingInterpolationOption',
144
    'RepeatSectionError',
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
145
    'ReloadError',
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
146
    'UnreprError',
147
    'UnknownType',
1185.12.49 by Aaron Bentley
Switched to ConfigObj
148
    '__docformat__',
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
149
    'flatten_errors',
1185.12.49 by Aaron Bentley
Switched to ConfigObj
150
)
151
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
152
DEFAULT_INTERPOLATION = 'configparser'
153
DEFAULT_INDENT_TYPE = '    '
1185.12.49 by Aaron Bentley
Switched to ConfigObj
154
MAX_INTERPOL_DEPTH = 10
155
156
OPTION_DEFAULTS = {
157
    'interpolation': True,
158
    'raise_errors': False,
159
    'list_values': True,
160
    'create_empty': False,
161
    'file_error': False,
162
    'configspec': None,
163
    'stringify': True,
164
    # option may be set to one of ('', ' ', '\t')
165
    'indent_type': None,
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
166
    'encoding': None,
167
    'default_encoding': None,
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
168
    'unrepr': False,
169
    'write_empty_values': False,
1185.12.49 by Aaron Bentley
Switched to ConfigObj
170
}
171
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
172
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
173
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
174
def getObj(s):
175
    s = "a=" + s
176
    if compiler is None:
177
        raise ImportError('compiler module not available')
178
    p = compiler.parse(s)
179
    return p.getChildren()[1].getChildren()[0].getChildren()[1]
180
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
181
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
182
class UnknownType(Exception):
183
    pass
184
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
185
186
class Builder(object):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
187
    
188
    def build(self, o):
189
        m = getattr(self, 'build_' + o.__class__.__name__, None)
190
        if m is None:
191
            raise UnknownType(o.__class__.__name__)
192
        return m(o)
193
    
194
    def build_List(self, o):
195
        return map(self.build, o.getChildren())
196
    
197
    def build_Const(self, o):
198
        return o.value
199
    
200
    def build_Dict(self, o):
201
        d = {}
202
        i = iter(map(self.build, o.getChildren()))
203
        for el in i:
204
            d[el] = i.next()
205
        return d
206
    
207
    def build_Tuple(self, o):
208
        return tuple(self.build_List(o))
209
    
210
    def build_Name(self, o):
211
        if o.name == 'None':
212
            return None
213
        if o.name == 'True':
214
            return True
215
        if o.name == 'False':
216
            return False
217
        
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
218
        # An undefined Name
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
219
        raise UnknownType('Undefined Name')
220
    
221
    def build_Add(self, o):
222
        real, imag = map(self.build_Const, o.getChildren())
223
        try:
224
            real = float(real)
225
        except TypeError:
226
            raise UnknownType('Add')
227
        if not isinstance(imag, complex) or imag.real != 0.0:
228
            raise UnknownType('Add')
229
        return real+imag
230
    
231
    def build_Getattr(self, o):
232
        parent = self.build(o.expr)
233
        return getattr(parent, o.attrname)
234
    
235
    def build_UnarySub(self, o):
236
        return -self.build_Const(o.getChildren()[0])
237
    
238
    def build_UnaryAdd(self, o):
239
        return self.build_Const(o.getChildren()[0])
240
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
241
242
_builder = Builder()
243
244
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
245
def unrepr(s):
246
    if not s:
247
        return s
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
248
    return _builder.build(getObj(s))
249
250
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
251
1185.12.49 by Aaron Bentley
Switched to ConfigObj
252
class ConfigObjError(SyntaxError):
253
    """
254
    This is the base class for all errors that ConfigObj raises.
255
    It is a subclass of SyntaxError.
256
    """
3734.2.7 by Vincent Ladeuil
Fix python-2.6 BaseException 'message' attribute deprecation.
257
    def __init__(self, msg='', line_number=None, line=''):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
258
        self.line = line
259
        self.line_number = line_number
3734.2.7 by Vincent Ladeuil
Fix python-2.6 BaseException 'message' attribute deprecation.
260
        self.msg = msg
261
        SyntaxError.__init__(self, msg)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
262
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
263
1185.12.49 by Aaron Bentley
Switched to ConfigObj
264
class NestingError(ConfigObjError):
265
    """
266
    This error indicates a level of nesting that doesn't match.
267
    """
268
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
269
1185.12.49 by Aaron Bentley
Switched to ConfigObj
270
class ParseError(ConfigObjError):
271
    """
272
    This error indicates that a line is badly written.
273
    It is neither a valid ``key = value`` line,
274
    nor a valid section marker line.
275
    """
276
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
277
278
class ReloadError(IOError):
279
    """
280
    A 'reload' operation failed.
281
    This exception is a subclass of ``IOError``.
282
    """
283
    def __init__(self):
284
        IOError.__init__(self, 'reload failed, filename is not set.')
285
286
1185.12.49 by Aaron Bentley
Switched to ConfigObj
287
class DuplicateError(ConfigObjError):
288
    """
289
    The keyword or section specified already exists.
290
    """
291
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
292
1185.12.49 by Aaron Bentley
Switched to ConfigObj
293
class ConfigspecError(ConfigObjError):
294
    """
295
    An error occured whilst parsing a configspec.
296
    """
297
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
298
1185.12.49 by Aaron Bentley
Switched to ConfigObj
299
class InterpolationError(ConfigObjError):
300
    """Base class for the two interpolation errors."""
301
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
302
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
303
class InterpolationLoopError(InterpolationError):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
304
    """Maximum interpolation depth exceeded in string interpolation."""
305
306
    def __init__(self, option):
307
        InterpolationError.__init__(
308
            self,
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
309
            'interpolation loop detected in value "%s".' % option)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
310
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
311
1185.12.49 by Aaron Bentley
Switched to ConfigObj
312
class RepeatSectionError(ConfigObjError):
313
    """
314
    This error indicates additional sections in a section with a
315
    ``__many__`` (repeated) section.
316
    """
317
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
318
1185.12.49 by Aaron Bentley
Switched to ConfigObj
319
class MissingInterpolationOption(InterpolationError):
320
    """A value specified for interpolation was missing."""
321
322
    def __init__(self, option):
323
        InterpolationError.__init__(
324
            self,
325
            'missing option "%s" in interpolation.' % option)
326
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
327
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
328
class UnreprError(ConfigObjError):
329
    """An error parsing in unrepr mode."""
330
331
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
332
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
333
class InterpolationEngine(object):
334
    """
335
    A helper class to help perform string interpolation.
336
337
    This class is an abstract base class; its descendants perform
338
    the actual work.
339
    """
340
341
    # compiled regexp to use in self.interpolate()
342
    _KEYCRE = re.compile(r"%\(([^)]*)\)s")
343
344
    def __init__(self, section):
345
        # the Section instance that "owns" this engine
346
        self.section = section
347
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
348
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
349
    def interpolate(self, key, value):
350
        def recursive_interpolate(key, value, section, backtrail):
351
            """The function that does the actual work.
352
353
            ``value``: the string we're trying to interpolate.
354
            ``section``: the section in which that string was found
355
            ``backtrail``: a dict to keep track of where we've been,
356
            to detect and prevent infinite recursion loops
357
358
            This is similar to a depth-first-search algorithm.
359
            """
360
            # Have we been here already?
361
            if backtrail.has_key((key, section.name)):
362
                # Yes - infinite loop detected
363
                raise InterpolationLoopError(key)
364
            # Place a marker on our backtrail so we won't come back here again
365
            backtrail[(key, section.name)] = 1
366
367
            # Now start the actual work
368
            match = self._KEYCRE.search(value)
369
            while match:
370
                # The actual parsing of the match is implementation-dependent,
371
                # so delegate to our helper function
372
                k, v, s = self._parse_match(match)
373
                if k is None:
374
                    # That's the signal that no further interpolation is needed
375
                    replacement = v
376
                else:
377
                    # Further interpolation may be needed to obtain final value
378
                    replacement = recursive_interpolate(k, v, s, backtrail)
379
                # Replace the matched string with its final value
380
                start, end = match.span()
381
                value = ''.join((value[:start], replacement, value[end:]))
382
                new_search_start = start + len(replacement)
383
                # Pick up the next interpolation key, if any, for next time
384
                # through the while loop
385
                match = self._KEYCRE.search(value, new_search_start)
386
387
            # Now safe to come back here again; remove marker from backtrail
388
            del backtrail[(key, section.name)]
389
390
            return value
391
392
        # Back in interpolate(), all we have to do is kick off the recursive
393
        # function with appropriate starting values
394
        value = recursive_interpolate(key, value, self.section, {})
395
        return value
396
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
397
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
398
    def _fetch(self, key):
399
        """Helper function to fetch values from owning section.
400
401
        Returns a 2-tuple: the value, and the section where it was found.
402
        """
403
        # switch off interpolation before we try and fetch anything !
404
        save_interp = self.section.main.interpolation
405
        self.section.main.interpolation = False
406
407
        # Start at section that "owns" this InterpolationEngine
408
        current_section = self.section
409
        while True:
410
            # try the current section first
411
            val = current_section.get(key)
412
            if val is not None:
413
                break
414
            # try "DEFAULT" next
415
            val = current_section.get('DEFAULT', {}).get(key)
416
            if val is not None:
417
                break
418
            # move up to parent and try again
419
            # top-level's parent is itself
420
            if current_section.parent is current_section:
421
                # reached top level, time to give up
422
                break
423
            current_section = current_section.parent
424
425
        # restore interpolation to previous value before returning
426
        self.section.main.interpolation = save_interp
427
        if val is None:
428
            raise MissingInterpolationOption(key)
429
        return val, current_section
430
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
431
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
432
    def _parse_match(self, match):
433
        """Implementation-dependent helper function.
434
435
        Will be passed a match object corresponding to the interpolation
436
        key we just found (e.g., "%(foo)s" or "$foo"). Should look up that
437
        key in the appropriate config file section (using the ``_fetch()``
438
        helper function) and return a 3-tuple: (key, value, section)
439
440
        ``key`` is the name of the key we're looking for
441
        ``value`` is the value found for that key
442
        ``section`` is a reference to the section where it was found
443
444
        ``key`` and ``section`` should be None if no further
445
        interpolation should be performed on the resulting value
446
        (e.g., if we interpolated "$$" and returned "$").
447
        """
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
448
        raise NotImplementedError()
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
449
    
450
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
451
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
452
class ConfigParserInterpolation(InterpolationEngine):
453
    """Behaves like ConfigParser."""
454
    _KEYCRE = re.compile(r"%\(([^)]*)\)s")
455
456
    def _parse_match(self, match):
457
        key = match.group(1)
458
        value, section = self._fetch(key)
459
        return key, value, section
460
461
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
462
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
463
class TemplateInterpolation(InterpolationEngine):
464
    """Behaves like string.Template."""
465
    _delimiter = '$'
466
    _KEYCRE = re.compile(r"""
467
        \$(?:
468
          (?P<escaped>\$)              |   # Two $ signs
469
          (?P<named>[_a-z][_a-z0-9]*)  |   # $name format
470
          {(?P<braced>[^}]*)}              # ${name} format
471
        )
472
        """, re.IGNORECASE | re.VERBOSE)
473
474
    def _parse_match(self, match):
475
        # Valid name (in or out of braces): fetch value from section
476
        key = match.group('named') or match.group('braced')
477
        if key is not None:
478
            value, section = self._fetch(key)
479
            return key, value, section
480
        # Escaped delimiter (e.g., $$): return single delimiter
481
        if match.group('escaped') is not None:
482
            # Return None for key and section to indicate it's time to stop
483
            return None, self._delimiter, None
484
        # Anything else: ignore completely, just return it unchanged
485
        return None, match.group(), None
486
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
487
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
488
interpolation_engines = {
489
    'configparser': ConfigParserInterpolation,
490
    'template': TemplateInterpolation,
491
}
492
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
493
494
1185.12.49 by Aaron Bentley
Switched to ConfigObj
495
class Section(dict):
496
    """
497
    A dictionary-like object that represents a section in a config file.
498
    
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
499
    It does string interpolation if the 'interpolation' attribute
1185.12.49 by Aaron Bentley
Switched to ConfigObj
500
    of the 'main' object is set to True.
501
    
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
502
    Interpolation is tried first from this object, then from the 'DEFAULT'
503
    section of this object, next from the parent and its 'DEFAULT' section,
504
    and so on until the main object is reached.
1185.12.49 by Aaron Bentley
Switched to ConfigObj
505
    
506
    A Section will behave like an ordered dictionary - following the
507
    order of the ``scalars`` and ``sections`` attributes.
508
    You can use this to change the order of members.
509
    
510
    Iteration follows the order: scalars, then sections.
511
    """
512
513
    def __init__(self, parent, depth, main, indict=None, name=None):
514
        """
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
515
        * parent is the section above
516
        * depth is the depth level of this section
517
        * main is the main ConfigObj
518
        * indict is a dictionary to initialise the section with
1185.12.49 by Aaron Bentley
Switched to ConfigObj
519
        """
520
        if indict is None:
521
            indict = {}
522
        dict.__init__(self)
523
        # used for nesting level *and* interpolation
524
        self.parent = parent
525
        # used for the interpolation attribute
526
        self.main = main
527
        # level of nesting depth of this Section
528
        self.depth = depth
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
529
        # purely for information
530
        self.name = name
531
        #
532
        self._initialise()
533
        # we do this explicitly so that __setitem__ is used properly
534
        # (rather than just passing to ``dict.__init__``)
535
        for entry, value in indict.iteritems():
536
            self[entry] = value
537
            
538
            
539
    def _initialise(self):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
540
        # the sequence of scalar values in this Section
541
        self.scalars = []
542
        # the sequence of sections in this Section
543
        self.sections = []
544
        # for comments :-)
545
        self.comments = {}
546
        self.inline_comments = {}
547
        # for the configspec
548
        self.configspec = {}
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
549
        self._order = []
550
        self._configspec_comments = {}
551
        self._configspec_inline_comments = {}
552
        self._cs_section_comments = {}
553
        self._cs_section_inline_comments = {}
1185.12.49 by Aaron Bentley
Switched to ConfigObj
554
        # for defaults
555
        self.defaults = []
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
556
        self.default_values = {}
557
1185.12.49 by Aaron Bentley
Switched to ConfigObj
558
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
559
    def _interpolate(self, key, value):
560
        try:
561
            # do we already have an interpolation engine?
562
            engine = self._interpolation_engine
563
        except AttributeError:
564
            # not yet: first time running _interpolate(), so pick the engine
565
            name = self.main.interpolation
566
            if name == True:  # note that "if name:" would be incorrect here
567
                # backwards-compatibility: interpolation=True means use default
568
                name = DEFAULT_INTERPOLATION
569
            name = name.lower()  # so that "Template", "template", etc. all work
570
            class_ = interpolation_engines.get(name, None)
571
            if class_ is None:
572
                # invalid value for self.main.interpolation
573
                self.main.interpolation = False
574
                return value
1185.12.49 by Aaron Bentley
Switched to ConfigObj
575
            else:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
576
                # save reference to engine so we don't have to do this again
577
                engine = self._interpolation_engine = class_(self)
578
        # let the engine do the actual work
579
        return engine.interpolate(key, value)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
580
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
581
1185.12.49 by Aaron Bentley
Switched to ConfigObj
582
    def __getitem__(self, key):
583
        """Fetch the item and do string interpolation."""
584
        val = dict.__getitem__(self, key)
585
        if self.main.interpolation and isinstance(val, StringTypes):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
586
            return self._interpolate(key, val)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
587
        return val
588
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
589
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
590
    def __setitem__(self, key, value, unrepr=False):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
591
        """
592
        Correctly set a value.
593
        
594
        Making dictionary values Section instances.
595
        (We have to special case 'Section' instances - which are also dicts)
596
        
597
        Keys must be strings.
598
        Values need only be strings (or lists of strings) if
599
        ``main.stringify`` is set.
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
600
        
601
        `unrepr`` must be set when setting a value to a dictionary, without
602
        creating a new sub-section.
1185.12.49 by Aaron Bentley
Switched to ConfigObj
603
        """
604
        if not isinstance(key, StringTypes):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
605
            raise ValueError('The key "%s" is not a string.' % key)
606
        
1185.12.49 by Aaron Bentley
Switched to ConfigObj
607
        # add the comment
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
608
        if not self.comments.has_key(key):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
609
            self.comments[key] = []
610
            self.inline_comments[key] = ''
611
        # remove the entry from defaults
612
        if key in self.defaults:
613
            self.defaults.remove(key)
614
        #
615
        if isinstance(value, Section):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
616
            if not self.has_key(key):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
617
                self.sections.append(key)
618
            dict.__setitem__(self, key, value)
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
619
        elif isinstance(value, dict) and not unrepr:
1185.12.49 by Aaron Bentley
Switched to ConfigObj
620
            # First create the new depth level,
621
            # then create the section
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
622
            if not self.has_key(key):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
623
                self.sections.append(key)
624
            new_depth = self.depth + 1
625
            dict.__setitem__(
626
                self,
627
                key,
628
                Section(
629
                    self,
630
                    new_depth,
631
                    self.main,
632
                    indict=value,
633
                    name=key))
634
        else:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
635
            if not self.has_key(key):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
636
                self.scalars.append(key)
637
            if not self.main.stringify:
638
                if isinstance(value, StringTypes):
639
                    pass
640
                elif isinstance(value, (list, tuple)):
641
                    for entry in value:
642
                        if not isinstance(entry, StringTypes):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
643
                            raise TypeError('Value is not a string "%s".' % entry)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
644
                else:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
645
                    raise TypeError('Value is not a string "%s".' % value)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
646
            dict.__setitem__(self, key, value)
647
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
648
1185.12.49 by Aaron Bentley
Switched to ConfigObj
649
    def __delitem__(self, key):
650
        """Remove items from the sequence when deleting."""
651
        dict. __delitem__(self, key)
652
        if key in self.scalars:
653
            self.scalars.remove(key)
654
        else:
655
            self.sections.remove(key)
656
        del self.comments[key]
657
        del self.inline_comments[key]
658
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
659
1185.12.49 by Aaron Bentley
Switched to ConfigObj
660
    def get(self, key, default=None):
661
        """A version of ``get`` that doesn't bypass string interpolation."""
662
        try:
663
            return self[key]
664
        except KeyError:
665
            return default
666
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
667
1185.12.49 by Aaron Bentley
Switched to ConfigObj
668
    def update(self, indict):
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
669
        """
670
        A version of update that uses our ``__setitem__``.
671
        """
1185.12.49 by Aaron Bentley
Switched to ConfigObj
672
        for entry in indict:
673
            self[entry] = indict[entry]
674
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
675
1185.12.49 by Aaron Bentley
Switched to ConfigObj
676
    def pop(self, key, *args):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
677
        """
678
        'D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
679
        If key is not found, d is returned if given, otherwise KeyError is raised'
680
        """
1185.12.49 by Aaron Bentley
Switched to ConfigObj
681
        val = dict.pop(self, key, *args)
682
        if key in self.scalars:
683
            del self.comments[key]
684
            del self.inline_comments[key]
685
            self.scalars.remove(key)
686
        elif key in self.sections:
687
            del self.comments[key]
688
            del self.inline_comments[key]
689
            self.sections.remove(key)
690
        if self.main.interpolation and isinstance(val, StringTypes):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
691
            return self._interpolate(key, val)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
692
        return val
693
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
694
1185.12.49 by Aaron Bentley
Switched to ConfigObj
695
    def popitem(self):
696
        """Pops the first (key,val)"""
697
        sequence = (self.scalars + self.sections)
698
        if not sequence:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
699
            raise KeyError(": 'popitem(): dictionary is empty'")
1185.12.49 by Aaron Bentley
Switched to ConfigObj
700
        key = sequence[0]
701
        val =  self[key]
702
        del self[key]
703
        return key, val
704
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
705
1185.12.49 by Aaron Bentley
Switched to ConfigObj
706
    def clear(self):
707
        """
708
        A version of clear that also affects scalars/sections
709
        Also clears comments and configspec.
710
        
711
        Leaves other attributes alone :
712
            depth/main/parent are not affected
713
        """
714
        dict.clear(self)
715
        self.scalars = []
716
        self.sections = []
717
        self.comments = {}
718
        self.inline_comments = {}
719
        self.configspec = {}
720
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
721
1185.12.49 by Aaron Bentley
Switched to ConfigObj
722
    def setdefault(self, key, default=None):
723
        """A version of setdefault that sets sequence if appropriate."""
724
        try:
725
            return self[key]
726
        except KeyError:
727
            self[key] = default
728
            return self[key]
729
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
730
1185.12.49 by Aaron Bentley
Switched to ConfigObj
731
    def items(self):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
732
        """D.items() -> list of D's (key, value) pairs, as 2-tuples"""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
733
        return zip((self.scalars + self.sections), self.values())
734
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
735
1185.12.49 by Aaron Bentley
Switched to ConfigObj
736
    def keys(self):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
737
        """D.keys() -> list of D's keys"""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
738
        return (self.scalars + self.sections)
739
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
740
1185.12.49 by Aaron Bentley
Switched to ConfigObj
741
    def values(self):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
742
        """D.values() -> list of D's values"""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
743
        return [self[key] for key in (self.scalars + self.sections)]
744
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
745
1185.12.49 by Aaron Bentley
Switched to ConfigObj
746
    def iteritems(self):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
747
        """D.iteritems() -> an iterator over the (key, value) items of D"""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
748
        return iter(self.items())
749
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
750
1185.12.49 by Aaron Bentley
Switched to ConfigObj
751
    def iterkeys(self):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
752
        """D.iterkeys() -> an iterator over the keys of D"""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
753
        return iter((self.scalars + self.sections))
754
755
    __iter__ = iterkeys
756
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
757
1185.12.49 by Aaron Bentley
Switched to ConfigObj
758
    def itervalues(self):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
759
        """D.itervalues() -> an iterator over the values of D"""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
760
        return iter(self.values())
761
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
762
1185.12.49 by Aaron Bentley
Switched to ConfigObj
763
    def __repr__(self):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
764
        """x.__repr__() <==> repr(x)"""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
765
        return '{%s}' % ', '.join([('%s: %s' % (repr(key), repr(self[key])))
766
            for key in (self.scalars + self.sections)])
767
768
    __str__ = __repr__
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
769
    __str__.__doc__ = "x.__str__() <==> str(x)"
770
1185.12.49 by Aaron Bentley
Switched to ConfigObj
771
772
    # Extra methods - not in a normal dictionary
773
774
    def dict(self):
775
        """
776
        Return a deepcopy of self as a dictionary.
777
        
778
        All members that are ``Section`` instances are recursively turned to
779
        ordinary dictionaries - by calling their ``dict`` method.
780
        
781
        >>> n = a.dict()
782
        >>> n == a
783
        1
784
        >>> n is a
785
        0
786
        """
787
        newdict = {}
788
        for entry in self:
789
            this_entry = self[entry]
790
            if isinstance(this_entry, Section):
791
                this_entry = this_entry.dict()
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
792
            elif isinstance(this_entry, list):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
793
                # create a copy rather than a reference
794
                this_entry = list(this_entry)
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
795
            elif isinstance(this_entry, tuple):
796
                # create a copy rather than a reference
797
                this_entry = tuple(this_entry)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
798
            newdict[entry] = this_entry
799
        return newdict
800
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
801
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
802
    def merge(self, indict):
803
        """
804
        A recursive update - useful for merging config files.
805
        
806
        >>> a = '''[section1]
807
        ...     option1 = True
808
        ...     [[subsection]]
809
        ...     more_options = False
810
        ...     # end of file'''.splitlines()
811
        >>> b = '''# File is user.ini
812
        ...     [section1]
813
        ...     option1 = False
814
        ...     # end of file'''.splitlines()
815
        >>> c1 = ConfigObj(b)
816
        >>> c2 = ConfigObj(a)
817
        >>> c2.merge(c1)
818
        >>> c2
819
        {'section1': {'option1': 'False', 'subsection': {'more_options': 'False'}}}
820
        """
821
        for key, val in indict.items():
822
            if (key in self and isinstance(self[key], dict) and
823
                                isinstance(val, dict)):
824
                self[key].merge(val)
825
            else:   
826
                self[key] = val
827
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
828
1185.12.49 by Aaron Bentley
Switched to ConfigObj
829
    def rename(self, oldkey, newkey):
830
        """
831
        Change a keyname to another, without changing position in sequence.
832
        
833
        Implemented so that transformations can be made on keys,
834
        as well as on values. (used by encode and decode)
835
        
836
        Also renames comments.
837
        """
838
        if oldkey in self.scalars:
839
            the_list = self.scalars
840
        elif oldkey in self.sections:
841
            the_list = self.sections
842
        else:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
843
            raise KeyError('Key "%s" not found.' % oldkey)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
844
        pos = the_list.index(oldkey)
845
        #
846
        val = self[oldkey]
847
        dict.__delitem__(self, oldkey)
848
        dict.__setitem__(self, newkey, val)
849
        the_list.remove(oldkey)
850
        the_list.insert(pos, newkey)
851
        comm = self.comments[oldkey]
852
        inline_comment = self.inline_comments[oldkey]
853
        del self.comments[oldkey]
854
        del self.inline_comments[oldkey]
855
        self.comments[newkey] = comm
856
        self.inline_comments[newkey] = inline_comment
857
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
858
1185.12.49 by Aaron Bentley
Switched to ConfigObj
859
    def walk(self, function, raise_errors=True,
860
            call_on_sections=False, **keywargs):
861
        """
862
        Walk every member and call a function on the keyword and value.
863
        
864
        Return a dictionary of the return values
865
        
866
        If the function raises an exception, raise the errror
867
        unless ``raise_errors=False``, in which case set the return value to
868
        ``False``.
869
        
870
        Any unrecognised keyword arguments you pass to walk, will be pased on
871
        to the function you pass in.
872
        
873
        Note: if ``call_on_sections`` is ``True`` then - on encountering a
874
        subsection, *first* the function is called for the *whole* subsection,
875
        and then recurses into it's members. This means your function must be
876
        able to handle strings, dictionaries and lists. This allows you
877
        to change the key of subsections as well as for ordinary members. The
878
        return value when called on the whole subsection has to be discarded.
879
        
880
        See  the encode and decode methods for examples, including functions.
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
881
        
882
        .. caution::
883
        
884
            You can use ``walk`` to transform the names of members of a section
885
            but you mustn't add or delete members.
886
        
887
        >>> config = '''[XXXXsection]
888
        ... XXXXkey = XXXXvalue'''.splitlines()
889
        >>> cfg = ConfigObj(config)
890
        >>> cfg
891
        {'XXXXsection': {'XXXXkey': 'XXXXvalue'}}
892
        >>> def transform(section, key):
893
        ...     val = section[key]
894
        ...     newkey = key.replace('XXXX', 'CLIENT1')
895
        ...     section.rename(key, newkey)
896
        ...     if isinstance(val, (tuple, list, dict)):
897
        ...         pass
898
        ...     else:
899
        ...         val = val.replace('XXXX', 'CLIENT1')
900
        ...         section[newkey] = val
901
        >>> cfg.walk(transform, call_on_sections=True)
902
        {'CLIENT1section': {'CLIENT1key': None}}
903
        >>> cfg
904
        {'CLIENT1section': {'CLIENT1key': 'CLIENT1value'}}
1185.12.49 by Aaron Bentley
Switched to ConfigObj
905
        """
906
        out = {}
907
        # scalars first
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
908
        for i in range(len(self.scalars)):
909
            entry = self.scalars[i]
1185.12.49 by Aaron Bentley
Switched to ConfigObj
910
            try:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
911
                val = function(self, entry, **keywargs)
912
                # bound again in case name has changed
913
                entry = self.scalars[i]
914
                out[entry] = val
1185.12.49 by Aaron Bentley
Switched to ConfigObj
915
            except Exception:
916
                if raise_errors:
917
                    raise
918
                else:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
919
                    entry = self.scalars[i]
1185.12.49 by Aaron Bentley
Switched to ConfigObj
920
                    out[entry] = False
921
        # then sections
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
922
        for i in range(len(self.sections)):
923
            entry = self.sections[i]
1185.12.49 by Aaron Bentley
Switched to ConfigObj
924
            if call_on_sections:
925
                try:
926
                    function(self, entry, **keywargs)
927
                except Exception:
928
                    if raise_errors:
929
                        raise
930
                    else:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
931
                        entry = self.sections[i]
1185.12.49 by Aaron Bentley
Switched to ConfigObj
932
                        out[entry] = False
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
933
                # bound again in case name has changed
934
                entry = self.sections[i]
1185.12.49 by Aaron Bentley
Switched to ConfigObj
935
            # previous result is discarded
936
            out[entry] = self[entry].walk(
937
                function,
938
                raise_errors=raise_errors,
939
                call_on_sections=call_on_sections,
940
                **keywargs)
941
        return out
942
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
943
1185.12.49 by Aaron Bentley
Switched to ConfigObj
944
    def decode(self, encoding):
945
        """
946
        Decode all strings and values to unicode, using the specified encoding.
947
        
948
        Works with subsections and list values.
949
        
950
        Uses the ``walk`` method.
951
        
952
        Testing ``encode`` and ``decode``.
953
        >>> m = ConfigObj(a)
954
        >>> m.decode('ascii')
955
        >>> def testuni(val):
956
        ...     for entry in val:
957
        ...         if not isinstance(entry, unicode):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
958
        ...             print >> sys.stderr, type(entry)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
959
        ...             raise AssertionError, 'decode failed.'
960
        ...         if isinstance(val[entry], dict):
961
        ...             testuni(val[entry])
962
        ...         elif not isinstance(val[entry], unicode):
963
        ...             raise AssertionError, 'decode failed.'
964
        >>> testuni(m)
965
        >>> m.encode('ascii')
966
        >>> a == m
967
        1
968
        """
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
969
        warn('use of ``decode`` is deprecated.', DeprecationWarning)
970
        def decode(section, key, encoding=encoding, warn=True):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
971
            """ """
972
            val = section[key]
973
            if isinstance(val, (list, tuple)):
974
                newval = []
975
                for entry in val:
976
                    newval.append(entry.decode(encoding))
977
            elif isinstance(val, dict):
978
                newval = val
979
            else:
980
                newval = val.decode(encoding)
981
            newkey = key.decode(encoding)
982
            section.rename(key, newkey)
983
            section[newkey] = newval
984
        # using ``call_on_sections`` allows us to modify section names
985
        self.walk(decode, call_on_sections=True)
986
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
987
1185.12.49 by Aaron Bentley
Switched to ConfigObj
988
    def encode(self, encoding):
989
        """
990
        Encode all strings and values from unicode,
991
        using the specified encoding.
992
        
993
        Works with subsections and list values.
994
        Uses the ``walk`` method.
995
        """
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
996
        warn('use of ``encode`` is deprecated.', DeprecationWarning)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
997
        def encode(section, key, encoding=encoding):
998
            """ """
999
            val = section[key]
1000
            if isinstance(val, (list, tuple)):
1001
                newval = []
1002
                for entry in val:
1003
                    newval.append(entry.encode(encoding))
1004
            elif isinstance(val, dict):
1005
                newval = val
1006
            else:
1007
                newval = val.encode(encoding)
1008
            newkey = key.encode(encoding)
1009
            section.rename(key, newkey)
1010
            section[newkey] = newval
1011
        self.walk(encode, call_on_sections=True)
1012
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1013
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1014
    def istrue(self, key):
1015
        """A deprecated version of ``as_bool``."""
1016
        warn('use of ``istrue`` is deprecated. Use ``as_bool`` method '
1017
                'instead.', DeprecationWarning)
1018
        return self.as_bool(key)
1019
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1020
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1021
    def as_bool(self, key):
1022
        """
1023
        Accepts a key as input. The corresponding value must be a string or
1024
        the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to
1025
        retain compatibility with Python 2.2.
1026
        
1027
        If the string is one of  ``True``, ``On``, ``Yes``, or ``1`` it returns 
1028
        ``True``.
1029
        
1030
        If the string is one of  ``False``, ``Off``, ``No``, or ``0`` it returns 
1031
        ``False``.
1032
        
1033
        ``as_bool`` is not case sensitive.
1034
        
1035
        Any other input will raise a ``ValueError``.
1036
        
1037
        >>> a = ConfigObj()
1038
        >>> a['a'] = 'fish'
1039
        >>> a.as_bool('a')
1040
        Traceback (most recent call last):
1041
        ValueError: Value "fish" is neither True nor False
1042
        >>> a['b'] = 'True'
1043
        >>> a.as_bool('b')
1044
        1
1045
        >>> a['b'] = 'off'
1046
        >>> a.as_bool('b')
1047
        0
1048
        """
1049
        val = self[key]
1050
        if val == True:
1051
            return True
1052
        elif val == False:
1053
            return False
1054
        else:
1055
            try:
1056
                if not isinstance(val, StringTypes):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1057
                    # TODO: Why do we raise a KeyError here?
1058
                    raise KeyError()
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1059
                else:
1060
                    return self.main._bools[val.lower()]
1061
            except KeyError:
1062
                raise ValueError('Value "%s" is neither True nor False' % val)
1063
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1064
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1065
    def as_int(self, key):
1066
        """
1067
        A convenience method which coerces the specified value to an integer.
1068
        
1069
        If the value is an invalid literal for ``int``, a ``ValueError`` will
1070
        be raised.
1071
        
1072
        >>> a = ConfigObj()
1073
        >>> a['a'] = 'fish'
1074
        >>> a.as_int('a')
1075
        Traceback (most recent call last):
1076
        ValueError: invalid literal for int(): fish
1077
        >>> a['b'] = '1'
1078
        >>> a.as_int('b')
1079
        1
1080
        >>> a['b'] = '3.2'
1081
        >>> a.as_int('b')
1082
        Traceback (most recent call last):
1083
        ValueError: invalid literal for int(): 3.2
1084
        """
1085
        return int(self[key])
1086
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1087
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1088
    def as_float(self, key):
1089
        """
1090
        A convenience method which coerces the specified value to a float.
1091
        
1092
        If the value is an invalid literal for ``float``, a ``ValueError`` will
1093
        be raised.
1094
        
1095
        >>> a = ConfigObj()
1096
        >>> a['a'] = 'fish'
1097
        >>> a.as_float('a')
1098
        Traceback (most recent call last):
1099
        ValueError: invalid literal for float(): fish
1100
        >>> a['b'] = '1'
1101
        >>> a.as_float('b')
1102
        1.0
1103
        >>> a['b'] = '3.2'
1104
        >>> a.as_float('b')
1105
        3.2000000000000002
1106
        """
1107
        return float(self[key])
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1108
1109
1110
    def restore_default(self, key):
1111
        """
1112
        Restore (and return) default value for the specified key.
1113
        
1114
        This method will only work for a ConfigObj that was created
1115
        with a configspec and has been validated.
1116
        
1117
        If there is no default value for this key, ``KeyError`` is raised.
1118
        """
1119
        default = self.default_values[key]
1120
        dict.__setitem__(self, key, default)
1121
        if key not in self.defaults:
1122
            self.defaults.append(key)
1123
        return default
1124
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1125
    
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1126
    def restore_defaults(self):
1127
        """
1128
        Recursively restore default values to all members
1129
        that have them.
1130
        
1131
        This method will only work for a ConfigObj that was created
1132
        with a configspec and has been validated.
1133
        
1134
        It doesn't delete or modify entries without default values.
1135
        """
1136
        for key in self.default_values:
1137
            self.restore_default(key)
1138
            
1139
        for section in self.sections:
1140
            self[section].restore_defaults()
1141
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1142
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1143
class ConfigObj(Section):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1144
    """An object to read, create, and write config files."""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1145
1146
    _keyword = re.compile(r'''^ # line start
1147
        (\s*)                   # indentation
1148
        (                       # keyword
1149
            (?:".*?")|          # double quotes
1150
            (?:'.*?')|          # single quotes
1151
            (?:[^'"=].*?)       # no quotes
1152
        )
1153
        \s*=\s*                 # divider
1154
        (.*)                    # value (including list values and comments)
1155
        $   # line end
1156
        ''',
1157
        re.VERBOSE)
1158
1159
    _sectionmarker = re.compile(r'''^
1160
        (\s*)                     # 1: indentation
1161
        ((?:\[\s*)+)              # 2: section marker open
1162
        (                         # 3: section name open
1163
            (?:"\s*\S.*?\s*")|    # at least one non-space with double quotes
1164
            (?:'\s*\S.*?\s*')|    # at least one non-space with single quotes
1165
            (?:[^'"\s].*?)        # at least one non-space unquoted
1166
        )                         # section name close
1167
        ((?:\s*\])+)              # 4: section marker close
1168
        \s*(\#.*)?                # 5: optional comment
1169
        $''',
1170
        re.VERBOSE)
1171
1172
    # this regexp pulls list values out as a single string
1173
    # or single values and comments
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1174
    # FIXME: this regex adds a '' to the end of comma terminated lists
1175
    #   workaround in ``_handle_value``
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1176
    _valueexp = re.compile(r'''^
1177
        (?:
1178
            (?:
1179
                (
1180
                    (?:
1181
                        (?:
1182
                            (?:".*?")|              # double quotes
1183
                            (?:'.*?')|              # single quotes
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1184
                            (?:[^'",\#][^,\#]*?)    # unquoted
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1185
                        )
1186
                        \s*,\s*                     # comma
1187
                    )*      # match all list items ending in a comma (if any)
1188
                )
1189
                (
1190
                    (?:".*?")|                      # double quotes
1191
                    (?:'.*?')|                      # single quotes
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1192
                    (?:[^'",\#\s][^,]*?)|           # unquoted
1193
                    (?:(?<!,))                      # Empty value
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1194
                )?          # last item in a list - or string value
1195
            )|
1196
            (,)             # alternatively a single comma - empty list
1197
        )
1198
        \s*(\#.*)?          # optional comment
1199
        $''',
1200
        re.VERBOSE)
1201
1202
    # use findall to get the members of a list value
1203
    _listvalueexp = re.compile(r'''
1204
        (
1205
            (?:".*?")|          # double quotes
1206
            (?:'.*?')|          # single quotes
1207
            (?:[^'",\#].*?)       # unquoted
1208
        )
1209
        \s*,\s*                 # comma
1210
        ''',
1211
        re.VERBOSE)
1212
1213
    # this regexp is used for the value
1214
    # when lists are switched off
1215
    _nolistvalue = re.compile(r'''^
1216
        (
1217
            (?:".*?")|          # double quotes
1218
            (?:'.*?')|          # single quotes
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1219
            (?:[^'"\#].*?)|     # unquoted
1220
            (?:)                # Empty value
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1221
        )
1222
        \s*(\#.*)?              # optional comment
1223
        $''',
1224
        re.VERBOSE)
1225
1226
    # regexes for finding triple quoted values on one line
1227
    _single_line_single = re.compile(r"^'''(.*?)'''\s*(#.*)?$")
1228
    _single_line_double = re.compile(r'^"""(.*?)"""\s*(#.*)?$')
1229
    _multi_line_single = re.compile(r"^(.*?)'''\s*(#.*)?$")
1230
    _multi_line_double = re.compile(r'^(.*?)"""\s*(#.*)?$')
1231
1232
    _triple_quote = {
1233
        "'''": (_single_line_single, _multi_line_single),
1234
        '"""': (_single_line_double, _multi_line_double),
1235
    }
1236
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1237
    # Used by the ``istrue`` Section method
1238
    _bools = {
1239
        'yes': True, 'no': False,
1240
        'on': True, 'off': False,
1241
        '1': True, '0': False,
1242
        'true': True, 'false': False,
1243
        }
1244
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1245
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1246
    def __init__(self, infile=None, options=None, **kwargs):
1247
        """
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1248
        Parse a config file or create a config file object.
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1249
        
1250
        ``ConfigObj(infile=None, options=None, **kwargs)``
1251
        """
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1252
        # init the superclass
1253
        Section.__init__(self, self, 0, self)
1254
        
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1255
        if infile is None:
1256
            infile = []
1257
        if options is None:
1258
            options = {}
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1259
        else:
1260
            options = dict(options)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1261
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1262
        # keyword arguments take precedence over an options dictionary
1263
        options.update(kwargs)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1264
        
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1265
        defaults = OPTION_DEFAULTS.copy()
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1266
        # TODO: check the values too.
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1267
        for entry in options:
1268
            if entry not in defaults:
1269
                raise TypeError('Unrecognised option "%s".' % entry)
1270
        
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1271
        # Add any explicit options to the defaults
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1272
        defaults.update(options)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1273
        self._initialise(defaults)
1274
        configspec = defaults['configspec']
1275
        self._original_configspec = configspec
1276
        self._load(infile, configspec)
1277
        
1278
        
1279
    def _load(self, infile, configspec):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1280
        if isinstance(infile, StringTypes):
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1281
            self.filename = infile
1282
            if os.path.isfile(infile):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1283
                h = open(infile, 'rb')
1284
                infile = h.read() or []
1285
                h.close()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1286
            elif self.file_error:
1287
                # raise an error if the file doesn't exist
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1288
                raise IOError('Config file not found: "%s".' % self.filename)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1289
            else:
1290
                # file doesn't already exist
1291
                if self.create_empty:
1292
                    # this is a good test that the filename specified
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1293
                    # isn't impossible - like on a non-existent device
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1294
                    h = open(infile, 'w')
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1295
                    h.write('')
1296
                    h.close()
1297
                infile = []
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1298
                
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1299
        elif isinstance(infile, (list, tuple)):
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1300
            infile = list(infile)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1301
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1302
        elif isinstance(infile, dict):
1303
            # initialise self
1304
            # the Section class handles creating subsections
1305
            if isinstance(infile, ConfigObj):
1306
                # get a copy of our ConfigObj
1307
                infile = infile.dict()
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1308
                
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1309
            for entry in infile:
1310
                self[entry] = infile[entry]
1311
            del self._errors
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1312
            
1313
            if configspec is not None:
1314
                self._handle_configspec(configspec)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1315
            else:
1316
                self.configspec = None
1317
            return
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1318
        
3239.1.2 by Matt Nordhoff
Restore hasattr -> getattr
1319
        elif getattr(infile, 'read', None) is not None:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1320
            # This supports file like objects
1321
            infile = infile.read() or []
1322
            # needs splitting into lines - but needs doing *after* decoding
1323
            # in case it's not an 8 bit encoding
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1324
        else:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1325
            raise TypeError('infile must be a filename, file like object, or list of lines.')
1326
        
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1327
        if infile:
1328
            # don't do it for the empty ConfigObj
1329
            infile = self._handle_bom(infile)
1330
            # infile is now *always* a list
1331
            #
1332
            # Set the newlines attribute (first line ending it finds)
1333
            # and strip trailing '\n' or '\r' from lines
1334
            for line in infile:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1335
                if (not line) or (line[-1] not in ('\r', '\n', '\r\n')):
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1336
                    continue
1337
                for end in ('\r\n', '\n', '\r'):
1338
                    if line.endswith(end):
1339
                        self.newlines = end
1340
                        break
1341
                break
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1342
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1343
            infile = [line.rstrip('\r\n') for line in infile]
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1344
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1345
        self._parse(infile)
1346
        # if we had any errors, now is the time to raise them
1347
        if self._errors:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1348
            info = "at line %s." % self._errors[0].line_number
1349
            if len(self._errors) > 1:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1350
                msg = "Parsing failed with several errors.\nFirst error %s" % info
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1351
                error = ConfigObjError(msg)
1352
            else:
1353
                error = self._errors[0]
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1354
            # set the errors attribute; it's a list of tuples:
1355
            # (error_type, message, line_number)
1356
            error.errors = self._errors
1357
            # set the config attribute
1358
            error.config = self
1359
            raise error
1360
        # delete private attributes
1361
        del self._errors
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1362
        
1363
        if configspec is None:
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1364
            self.configspec = None
1365
        else:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1366
            self._handle_configspec(configspec)
1367
    
1368
    
1369
    def _initialise(self, options=None):
1370
        if options is None:
1371
            options = OPTION_DEFAULTS
1372
            
1373
        # initialise a few variables
1374
        self.filename = None
1375
        self._errors = []
1376
        self.raise_errors = options['raise_errors']
1377
        self.interpolation = options['interpolation']
1378
        self.list_values = options['list_values']
1379
        self.create_empty = options['create_empty']
1380
        self.file_error = options['file_error']
1381
        self.stringify = options['stringify']
1382
        self.indent_type = options['indent_type']
1383
        self.encoding = options['encoding']
1384
        self.default_encoding = options['default_encoding']
1385
        self.BOM = False
1386
        self.newlines = None
1387
        self.write_empty_values = options['write_empty_values']
1388
        self.unrepr = options['unrepr']
1389
        
1390
        self.initial_comment = []
1391
        self.final_comment = []
1392
        self.configspec = {}
1393
        
1394
        # Clear section attributes as well
1395
        Section._initialise(self)
1396
        
1397
        
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1398
    def __repr__(self):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1399
        return ('ConfigObj({%s})' % 
1400
                ', '.join([('%s: %s' % (repr(key), repr(self[key]))) 
1401
                for key in (self.scalars + self.sections)]))
1402
    
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1403
    
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1404
    def _handle_bom(self, infile):
1405
        """
1406
        Handle any BOM, and decode if necessary.
1407
        
1408
        If an encoding is specified, that *must* be used - but the BOM should
1409
        still be removed (and the BOM attribute set).
1410
        
1411
        (If the encoding is wrongly specified, then a BOM for an alternative
1412
        encoding won't be discovered or removed.)
1413
        
1414
        If an encoding is not specified, UTF8 or UTF16 BOM will be detected and
1415
        removed. The BOM attribute will be set. UTF16 will be decoded to
1416
        unicode.
1417
        
1418
        NOTE: This method must not be called with an empty ``infile``.
1419
        
1420
        Specifying the *wrong* encoding is likely to cause a
1421
        ``UnicodeDecodeError``.
1422
        
1423
        ``infile`` must always be returned as a list of lines, but may be
1424
        passed in as a single string.
1425
        """
1426
        if ((self.encoding is not None) and
1427
            (self.encoding.lower() not in BOM_LIST)):
1428
            # No need to check for a BOM
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1429
            # the encoding specified doesn't have one
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1430
            # just decode
1431
            return self._decode(infile, self.encoding)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1432
        
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1433
        if isinstance(infile, (list, tuple)):
1434
            line = infile[0]
1435
        else:
1436
            line = infile
1437
        if self.encoding is not None:
1438
            # encoding explicitly supplied
1439
            # And it could have an associated BOM
1440
            # TODO: if encoding is just UTF16 - we ought to check for both
1441
            # TODO: big endian and little endian versions.
1442
            enc = BOM_LIST[self.encoding.lower()]
1443
            if enc == 'utf_16':
1444
                # For UTF16 we try big endian and little endian
1445
                for BOM, (encoding, final_encoding) in BOMS.items():
1446
                    if not final_encoding:
1447
                        # skip UTF8
1448
                        continue
1449
                    if infile.startswith(BOM):
1450
                        ### BOM discovered
1451
                        ##self.BOM = True
1452
                        # Don't need to remove BOM
1453
                        return self._decode(infile, encoding)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1454
                    
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1455
                # If we get this far, will *probably* raise a DecodeError
1456
                # As it doesn't appear to start with a BOM
1457
                return self._decode(infile, self.encoding)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1458
            
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1459
            # Must be UTF8
1460
            BOM = BOM_SET[enc]
1461
            if not line.startswith(BOM):
1462
                return self._decode(infile, self.encoding)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1463
            
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1464
            newline = line[len(BOM):]
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1465
            
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1466
            # BOM removed
1467
            if isinstance(infile, (list, tuple)):
1468
                infile[0] = newline
1469
            else:
1470
                infile = newline
1471
            self.BOM = True
1472
            return self._decode(infile, self.encoding)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1473
        
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1474
        # No encoding specified - so we need to check for UTF8/UTF16
1475
        for BOM, (encoding, final_encoding) in BOMS.items():
1476
            if not line.startswith(BOM):
1477
                continue
1478
            else:
1479
                # BOM discovered
1480
                self.encoding = final_encoding
1481
                if not final_encoding:
1482
                    self.BOM = True
1483
                    # UTF8
1484
                    # remove BOM
1485
                    newline = line[len(BOM):]
1486
                    if isinstance(infile, (list, tuple)):
1487
                        infile[0] = newline
1488
                    else:
1489
                        infile = newline
1490
                    # UTF8 - don't decode
1491
                    if isinstance(infile, StringTypes):
1492
                        return infile.splitlines(True)
1493
                    else:
1494
                        return infile
1495
                # UTF16 - have to decode
1496
                return self._decode(infile, encoding)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1497
            
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1498
        # No BOM discovered and no encoding specified, just return
1499
        if isinstance(infile, StringTypes):
1500
            # infile read from a file will be a single string
1501
            return infile.splitlines(True)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1502
        return infile
1503
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1504
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1505
    def _a_to_u(self, aString):
1506
        """Decode ASCII strings to unicode if a self.encoding is specified."""
1507
        if self.encoding:
1508
            return aString.decode('ascii')
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1509
        else:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1510
            return aString
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1511
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1512
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1513
    def _decode(self, infile, encoding):
1514
        """
1515
        Decode infile to unicode. Using the specified encoding.
1516
        
1517
        if is a string, it also needs converting to a list.
1518
        """
1519
        if isinstance(infile, StringTypes):
1520
            # can't be unicode
1521
            # NOTE: Could raise a ``UnicodeDecodeError``
1522
            return infile.decode(encoding).splitlines(True)
1523
        for i, line in enumerate(infile):
1524
            if not isinstance(line, unicode):
1525
                # NOTE: The isinstance test here handles mixed lists of unicode/string
1526
                # NOTE: But the decode will break on any non-string values
1527
                # NOTE: Or could raise a ``UnicodeDecodeError``
1528
                infile[i] = line.decode(encoding)
1529
        return infile
1530
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1531
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1532
    def _decode_element(self, line):
1533
        """Decode element to unicode if necessary."""
1534
        if not self.encoding:
1535
            return line
1536
        if isinstance(line, str) and self.default_encoding:
1537
            return line.decode(self.default_encoding)
1538
        return line
1539
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1540
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1541
    def _str(self, value):
1542
        """
1543
        Used by ``stringify`` within validate, to turn non-string values
1544
        into strings.
1545
        """
1546
        if not isinstance(value, StringTypes):
1547
            return str(value)
1548
        else:
1549
            return value
1550
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1551
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1552
    def _parse(self, infile):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1553
        """Actually parse the config file."""
1554
        temp_list_values = self.list_values
1555
        if self.unrepr:
1556
            self.list_values = False
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1557
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1558
        comment_list = []
1559
        done_start = False
1560
        this_section = self
1561
        maxline = len(infile) - 1
1562
        cur_index = -1
1563
        reset_comment = False
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1564
        
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1565
        while cur_index < maxline:
1566
            if reset_comment:
1567
                comment_list = []
1568
            cur_index += 1
1569
            line = infile[cur_index]
1570
            sline = line.strip()
1571
            # do we have anything on the line ?
1572
            if not sline or sline.startswith('#'):
1573
                reset_comment = False
1574
                comment_list.append(line)
1575
                continue
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1576
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1577
            if not done_start:
1578
                # preserve initial comment
1579
                self.initial_comment = comment_list
1580
                comment_list = []
1581
                done_start = True
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1582
                
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1583
            reset_comment = True
1584
            # first we check if it's a section marker
1585
            mat = self._sectionmarker.match(line)
1586
            if mat is not None:
1587
                # is a section line
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1588
                (indent, sect_open, sect_name, sect_close, comment) = mat.groups()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1589
                if indent and (self.indent_type is None):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1590
                    self.indent_type = indent
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1591
                cur_depth = sect_open.count('[')
1592
                if cur_depth != sect_close.count(']'):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1593
                    self._handle_error("Cannot compute the section depth at line %s.",
1594
                                       NestingError, infile, cur_index)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1595
                    continue
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1596
                
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1597
                if cur_depth < this_section.depth:
1598
                    # the new section is dropping back to a previous level
1599
                    try:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1600
                        parent = self._match_depth(this_section,
1601
                                                   cur_depth).parent
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1602
                    except SyntaxError:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1603
                        self._handle_error("Cannot compute nesting level at line %s.",
1604
                                           NestingError, infile, cur_index)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1605
                        continue
1606
                elif cur_depth == this_section.depth:
1607
                    # the new section is a sibling of the current section
1608
                    parent = this_section.parent
1609
                elif cur_depth == this_section.depth + 1:
1610
                    # the new section is a child the current section
1611
                    parent = this_section
1612
                else:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1613
                    self._handle_error("Section too nested at line %s.",
1614
                                       NestingError, infile, cur_index)
1615
                    
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1616
                sect_name = self._unquote(sect_name)
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1617
                if parent.has_key(sect_name):
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1618
                    self._handle_error('Duplicate section name at line %s.',
1619
                                       DuplicateError, infile, cur_index)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1620
                    continue
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1621
                
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1622
                # create the new section
1623
                this_section = Section(
1624
                    parent,
1625
                    cur_depth,
1626
                    self,
1627
                    name=sect_name)
1628
                parent[sect_name] = this_section
1629
                parent.inline_comments[sect_name] = comment
1630
                parent.comments[sect_name] = comment_list
1631
                continue
1632
            #
1633
            # it's not a section marker,
1634
            # so it should be a valid ``key = value`` line
1635
            mat = self._keyword.match(line)
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1636
            if mat is None:
1637
                # it neither matched as a keyword
1638
                # or a section marker
1639
                self._handle_error(
1640
                    'Invalid line at line "%s".',
1641
                    ParseError, infile, cur_index)
1642
            else:
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1643
                # is a keyword value
1644
                # value will include any inline comment
1645
                (indent, key, value) = mat.groups()
1646
                if indent and (self.indent_type is None):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1647
                    self.indent_type = indent
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1648
                # check for a multiline value
1649
                if value[:3] in ['"""', "'''"]:
1650
                    try:
1651
                        (value, comment, cur_index) = self._multiline(
1652
                            value, infile, cur_index, maxline)
1653
                    except SyntaxError:
1654
                        self._handle_error(
1655
                            'Parse error in value at line %s.',
1656
                            ParseError, infile, cur_index)
1657
                        continue
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1658
                    else:
1659
                        if self.unrepr:
1660
                            comment = ''
1661
                            try:
1662
                                value = unrepr(value)
1663
                            except Exception, e:
1664
                                if type(e) == UnknownType:
1665
                                    msg = 'Unknown name or type in value at line %s.'
1666
                                else:
1667
                                    msg = 'Parse error in value at line %s.'
1668
                                self._handle_error(msg, UnreprError, infile,
1669
                                    cur_index)
1670
                                continue
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1671
                else:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1672
                    if self.unrepr:
1673
                        comment = ''
1674
                        try:
1675
                            value = unrepr(value)
1676
                        except Exception, e:
1677
                            if isinstance(e, UnknownType):
1678
                                msg = 'Unknown name or type in value at line %s.'
1679
                            else:
1680
                                msg = 'Parse error in value at line %s.'
1681
                            self._handle_error(msg, UnreprError, infile,
1682
                                cur_index)
1683
                            continue
1684
                    else:
1685
                        # extract comment and lists
1686
                        try:
1687
                            (value, comment) = self._handle_value(value)
1688
                        except SyntaxError:
1689
                            self._handle_error(
1690
                                'Parse error in value at line %s.',
1691
                                ParseError, infile, cur_index)
1692
                            continue
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1693
                #
1694
                key = self._unquote(key)
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1695
                if this_section.has_key(key):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1696
                    self._handle_error(
1697
                        'Duplicate keyword name at line %s.',
1698
                        DuplicateError, infile, cur_index)
1699
                    continue
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1700
                # add the key.
1701
                # we set unrepr because if we have got this far we will never
1702
                # be creating a new section
1703
                this_section.__setitem__(key, value, unrepr=True)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1704
                this_section.inline_comments[key] = comment
1705
                this_section.comments[key] = comment_list
1706
                continue
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1707
        #
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1708
        if self.indent_type is None:
1709
            # no indentation used, set the type accordingly
1710
            self.indent_type = ''
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1711
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1712
        # preserve the final comment
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1713
        if not self and not self.initial_comment:
1714
            self.initial_comment = comment_list
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1715
        elif not reset_comment:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1716
            self.final_comment = comment_list
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1717
        self.list_values = temp_list_values
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1718
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1719
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1720
    def _match_depth(self, sect, depth):
1721
        """
1722
        Given a section and a depth level, walk back through the sections
1723
        parents to see if the depth level matches a previous section.
1724
        
1725
        Return a reference to the right section,
1726
        or raise a SyntaxError.
1727
        """
1728
        while depth < sect.depth:
1729
            if sect is sect.parent:
1730
                # we've reached the top level already
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1731
                raise SyntaxError()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1732
            sect = sect.parent
1733
        if sect.depth == depth:
1734
            return sect
1735
        # shouldn't get here
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1736
        raise SyntaxError()
1737
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1738
1739
    def _handle_error(self, text, ErrorClass, infile, cur_index):
1740
        """
1741
        Handle an error according to the error settings.
1742
        
1743
        Either raise the error or store it.
1744
        The error will have occured at ``cur_index``
1745
        """
1746
        line = infile[cur_index]
2900.1.2 by Vincent Ladeuil
Fix 149019 by using a proper line number when reporting errors.
1747
        cur_index += 1
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1748
        message = text % cur_index
1749
        error = ErrorClass(message, cur_index, line)
1750
        if self.raise_errors:
1751
            # raise the error - parsing stops here
1752
            raise error
1753
        # store the error
1754
        # reraise when parsing has finished
1755
        self._errors.append(error)
1756
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1757
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1758
    def _unquote(self, value):
1759
        """Return an unquoted version of a value"""
1760
        if (value[0] == value[-1]) and (value[0] in ('"', "'")):
1761
            value = value[1:-1]
1762
        return value
1763
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1764
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1765
    def _quote(self, value, multiline=True):
1766
        """
1767
        Return a safely quoted version of a value.
1768
        
1769
        Raise a ConfigObjError if the value cannot be safely quoted.
1770
        If multiline is ``True`` (default) then use triple quotes
1771
        if necessary.
1772
        
1773
        Don't quote values that don't need it.
1774
        Recursively quote members of a list and return a comma joined list.
1775
        Multiline is ``False`` for lists.
1776
        Obey list syntax for empty and single member lists.
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1777
        
1778
        If ``list_values=False`` then the value is only quoted if it contains
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1779
        a ``\n`` (is multiline) or '#'.
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1780
        
1781
        If ``write_empty_values`` is set, and the value is an empty string, it
1782
        won't be quoted.
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1783
        """
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1784
        if multiline and self.write_empty_values and value == '':
1785
            # Only if multiline is set, so that it is used for values not
1786
            # keys, and not values that are part of a list
1787
            return ''
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1788
        
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1789
        if multiline and isinstance(value, (list, tuple)):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1790
            if not value:
1791
                return ','
1792
            elif len(value) == 1:
1793
                return self._quote(value[0], multiline=False) + ','
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1794
            return ', '.join([self._quote(val, multiline=False)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1795
                for val in value])
1796
        if not isinstance(value, StringTypes):
1797
            if self.stringify:
1798
                value = str(value)
1799
            else:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1800
                raise TypeError('Value "%s" is not a string.' % value)
1801
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1802
        if not value:
1803
            return '""'
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1804
        
1805
        no_lists_no_quotes = not self.list_values and '\n' not in value and '#' not in value
1806
        need_triple = multiline and ((("'" in value) and ('"' in value)) or ('\n' in value ))
1807
        hash_triple_quote = multiline and not need_triple and ("'" in value) and ('"' in value) and ('#' in value)
1808
        check_for_single = (no_lists_no_quotes or not need_triple) and not hash_triple_quote
1809
        
1810
        if check_for_single:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1811
            if not self.list_values:
1812
                # we don't quote if ``list_values=False``
1813
                quot = noquot
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1814
            # for normal values either single or double quotes will do
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1815
            elif '\n' in value:
1816
                # will only happen if multiline is off - e.g. '\n' in key
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1817
                raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1818
            elif ((value[0] not in wspace_plus) and
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1819
                    (value[-1] not in wspace_plus) and
1820
                    (',' not in value)):
1821
                quot = noquot
1822
            else:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1823
                quot = self._get_single_quote(value)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1824
        else:
1825
            # if value has '\n' or "'" *and* '"', it will need triple quotes
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1826
            quot = self._get_triple_quote(value)
1827
        
1828
        if quot == noquot and '#' in value and self.list_values:
1829
            quot = self._get_single_quote(value)
1830
                
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1831
        return quot % value
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1832
    
1833
    
1834
    def _get_single_quote(self, value):
1835
        if ("'" in value) and ('"' in value):
1836
            raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
1837
        elif '"' in value:
1838
            quot = squot
1839
        else:
1840
            quot = dquot
1841
        return quot
1842
    
1843
    
1844
    def _get_triple_quote(self, value):
1845
        if (value.find('"""') != -1) and (value.find("'''") != -1):
1846
            raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
1847
        if value.find('"""') == -1:
1848
            quot = tdquot
1849
        else:
1850
            quot = tsquot 
1851
        return quot
1852
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1853
1854
    def _handle_value(self, value):
1855
        """
1856
        Given a value string, unquote, remove comment,
1857
        handle lists. (including empty and single member lists)
1858
        """
1859
        # do we look for lists in values ?
1860
        if not self.list_values:
1861
            mat = self._nolistvalue.match(value)
1862
            if mat is None:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1863
                raise SyntaxError()
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
1864
            # NOTE: we don't unquote here
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1865
            return mat.groups()
1866
        #
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1867
        mat = self._valueexp.match(value)
1868
        if mat is None:
1869
            # the value is badly constructed, probably badly quoted,
1870
            # or an invalid list
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1871
            raise SyntaxError()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1872
        (list_values, single, empty_list, comment) = mat.groups()
1873
        if (list_values == '') and (single is None):
1874
            # change this if you want to accept empty values
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1875
            raise SyntaxError()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1876
        # NOTE: note there is no error handling from here if the regex
1877
        # is wrong: then incorrect values will slip through
1878
        if empty_list is not None:
1879
            # the single comma - meaning an empty list
1880
            return ([], comment)
1881
        if single is not None:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1882
            # handle empty values
1883
            if list_values and not single:
1884
                # FIXME: the '' is a workaround because our regex now matches
1885
                #   '' at the end of a list if it has a trailing comma
1886
                single = None
1887
            else:
1888
                single = single or '""'
1889
                single = self._unquote(single)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1890
        if list_values == '':
1891
            # not a list value
1892
            return (single, comment)
1893
        the_list = self._listvalueexp.findall(list_values)
1894
        the_list = [self._unquote(val) for val in the_list]
1895
        if single is not None:
1896
            the_list += [single]
1897
        return (the_list, comment)
1898
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1899
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1900
    def _multiline(self, value, infile, cur_index, maxline):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1901
        """Extract the value, where we are in a multiline situation."""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1902
        quot = value[:3]
1903
        newvalue = value[3:]
1904
        single_line = self._triple_quote[quot][0]
1905
        multi_line = self._triple_quote[quot][1]
1906
        mat = single_line.match(value)
1907
        if mat is not None:
1908
            retval = list(mat.groups())
1909
            retval.append(cur_index)
1910
            return retval
1911
        elif newvalue.find(quot) != -1:
1912
            # somehow the triple quote is missing
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1913
            raise SyntaxError()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1914
        #
1915
        while cur_index < maxline:
1916
            cur_index += 1
1917
            newvalue += '\n'
1918
            line = infile[cur_index]
1919
            if line.find(quot) == -1:
1920
                newvalue += line
1921
            else:
1922
                # end of multiline, process it
1923
                break
1924
        else:
1925
            # we've got to the end of the config, oops...
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1926
            raise SyntaxError()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1927
        mat = multi_line.match(line)
1928
        if mat is None:
1929
            # a badly formed line
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1930
            raise SyntaxError()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1931
        (value, comment) = mat.groups()
1932
        return (newvalue + value, comment, cur_index)
1933
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1934
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1935
    def _handle_configspec(self, configspec):
1936
        """Parse the configspec."""
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1937
        # FIXME: Should we check that the configspec was created with the 
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1938
        #        correct settings ? (i.e. ``list_values=False``)
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1939
        if not isinstance(configspec, ConfigObj):
1940
            try:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1941
                configspec = ConfigObj(configspec,
1942
                                       raise_errors=True,
1943
                                       file_error=True,
1944
                                       list_values=False)
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1945
            except ConfigObjError, e:
1946
                # FIXME: Should these errors have a reference
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1947
                #        to the already parsed ConfigObj ?
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1948
                raise ConfigspecError('Parsing configspec failed: %s' % e)
1949
            except IOError, e:
1950
                raise IOError('Reading configspec failed: %s' % e)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1951
        
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1952
        self._set_configspec_value(configspec, self)
1953
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1954
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1955
    def _set_configspec_value(self, configspec, section):
1956
        """Used to recursively set configspec values."""
1957
        if '__many__' in configspec.sections:
1958
            section.configspec['__many__'] = configspec['__many__']
1959
            if len(configspec.sections) > 1:
1960
                # FIXME: can we supply any useful information here ?
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1961
                raise RepeatSectionError()
1962
            
3239.1.2 by Matt Nordhoff
Restore hasattr -> getattr
1963
        if getattr(configspec, 'initial_comment', None) is not None:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1964
            section._configspec_initial_comment = configspec.initial_comment
1965
            section._configspec_final_comment = configspec.final_comment
1966
            section._configspec_encoding = configspec.encoding
1967
            section._configspec_BOM = configspec.BOM
1968
            section._configspec_newlines = configspec.newlines
1969
            section._configspec_indent_type = configspec.indent_type
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1970
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1971
        for entry in configspec.scalars:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1972
            section._configspec_comments[entry] = configspec.comments[entry]
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1973
            section._configspec_inline_comments[entry] = configspec.inline_comments[entry]
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1974
            section.configspec[entry] = configspec[entry]
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1975
            section._order.append(entry)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1976
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1977
        for entry in configspec.sections:
1978
            if entry == '__many__':
1979
                continue
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1980
            
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1981
            section._cs_section_comments[entry] = configspec.comments[entry]
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1982
            section._cs_section_inline_comments[entry] = configspec.inline_comments[entry]
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
1983
            if not section.has_key(entry):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1984
                section[entry] = {}
1985
            self._set_configspec_value(configspec[entry], section[entry])
1986
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1987
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1988
    def _handle_repeat(self, section, configspec):
1989
        """Dynamically assign configspec for repeated section."""
1990
        try:
1991
            section_keys = configspec.sections
1992
            scalar_keys = configspec.scalars
1993
        except AttributeError:
1994
            section_keys = [entry for entry in configspec 
1995
                                if isinstance(configspec[entry], dict)]
1996
            scalar_keys = [entry for entry in configspec 
1997
                                if not isinstance(configspec[entry], dict)]
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1998
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
1999
        if '__many__' in section_keys and len(section_keys) > 1:
2000
            # FIXME: can we supply any useful information here ?
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2001
            raise RepeatSectionError()
2002
        
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2003
        scalars = {}
2004
        sections = {}
2005
        for entry in scalar_keys:
2006
            val = configspec[entry]
2007
            scalars[entry] = val
2008
        for entry in section_keys:
2009
            val = configspec[entry]
2010
            if entry == '__many__':
2011
                scalars[entry] = val
2012
                continue
2013
            sections[entry] = val
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2014
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2015
        section.configspec = scalars
2016
        for entry in sections:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2017
            if not section.has_key(entry):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2018
                section[entry] = {}
2019
            self._handle_repeat(section[entry], sections[entry])
2020
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2021
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2022
    def _write_line(self, indent_string, entry, this_entry, comment):
2023
        """Write an individual line, for the write method"""
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2024
        # NOTE: the calls to self._quote here handles non-StringType values.
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2025
        if not self.unrepr:
2026
            val = self._decode_element(self._quote(this_entry))
2027
        else:
2028
            val = repr(this_entry)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2029
        return '%s%s%s%s%s' % (indent_string,
2030
                               self._decode_element(self._quote(entry, multiline=False)),
2031
                               self._a_to_u(' = '),
2032
                               val,
2033
                               self._decode_element(comment))
2034
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2035
2036
    def _write_marker(self, indent_string, depth, entry, comment):
2037
        """Write a section marker line"""
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2038
        return '%s%s%s%s%s' % (indent_string,
2039
                               self._a_to_u('[' * depth),
2040
                               self._quote(self._decode_element(entry), multiline=False),
2041
                               self._a_to_u(']' * depth),
2042
                               self._decode_element(comment))
2043
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2044
2045
    def _handle_comment(self, comment):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2046
        """Deal with a comment."""
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2047
        if not comment:
2048
            return ''
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2049
        start = self.indent_type
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2050
        if not comment.startswith('#'):
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2051
            start += self._a_to_u(' # ')
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2052
        return (start + comment)
2053
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2054
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2055
    # Public methods
2056
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2057
    def write(self, outfile=None, section=None):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2058
        """
2059
        Write the current ConfigObj as a file
2060
        
2061
        tekNico: FIXME: use StringIO instead of real files
2062
        
2063
        >>> filename = a.filename
2064
        >>> a.filename = 'test.ini'
2065
        >>> a.write()
2066
        >>> a.filename = filename
2067
        >>> a == ConfigObj('test.ini', raise_errors=True)
2068
        1
2069
        """
2070
        if self.indent_type is None:
2071
            # this can be true if initialised from a dictionary
2072
            self.indent_type = DEFAULT_INDENT_TYPE
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2073
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2074
        out = []
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2075
        cs = self._a_to_u('#')
2076
        csp = self._a_to_u('# ')
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2077
        if section is None:
2078
            int_val = self.interpolation
2079
            self.interpolation = False
2080
            section = self
2081
            for line in self.initial_comment:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2082
                line = self._decode_element(line)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2083
                stripped_line = line.strip()
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2084
                if stripped_line and not stripped_line.startswith(cs):
2085
                    line = csp + line
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2086
                out.append(line)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2087
                
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2088
        indent_string = self.indent_type * section.depth
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2089
        for entry in (section.scalars + section.sections):
2090
            if entry in section.defaults:
2091
                # don't write out default values
2092
                continue
2093
            for comment_line in section.comments[entry]:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2094
                comment_line = self._decode_element(comment_line.lstrip())
2095
                if comment_line and not comment_line.startswith(cs):
2096
                    comment_line = csp + comment_line
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2097
                out.append(indent_string + comment_line)
2098
            this_entry = section[entry]
2099
            comment = self._handle_comment(section.inline_comments[entry])
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2100
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2101
            if isinstance(this_entry, dict):
2102
                # a section
2103
                out.append(self._write_marker(
2104
                    indent_string,
2105
                    this_entry.depth,
2106
                    entry,
2107
                    comment))
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2108
                out.extend(self.write(section=this_entry))
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2109
            else:
2110
                out.append(self._write_line(
2111
                    indent_string,
2112
                    entry,
2113
                    this_entry,
2114
                    comment))
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2115
                
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2116
        if section is self:
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2117
            for line in self.final_comment:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2118
                line = self._decode_element(line)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2119
                stripped_line = line.strip()
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2120
                if stripped_line and not stripped_line.startswith(cs):
2121
                    line = csp + line
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2122
                out.append(line)
2123
            self.interpolation = int_val
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2124
            
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2125
        if section is not self:
2126
            return out
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2127
        
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2128
        if (self.filename is None) and (outfile is None):
2129
            # output a list of lines
2130
            # might need to encode
2131
            # NOTE: This will *screw* UTF16, each line will start with the BOM
2132
            if self.encoding:
2133
                out = [l.encode(self.encoding) for l in out]
2134
            if (self.BOM and ((self.encoding is None) or
2135
                (BOM_LIST.get(self.encoding.lower()) == 'utf_8'))):
2136
                # Add the UTF8 BOM
2137
                if not out:
2138
                    out.append('')
2139
                out[0] = BOM_UTF8 + out[0]
2140
            return out
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2141
        
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2142
        # Turn the list to a string, joined with correct newlines
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2143
        newline = self.newlines or os.linesep
2144
        output = self._a_to_u(newline).join(out)
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2145
        if self.encoding:
2146
            output = output.encode(self.encoding)
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2147
        if self.BOM and ((self.encoding is None) or match_utf8(self.encoding)):
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2148
            # Add the UTF8 BOM
2149
            output = BOM_UTF8 + output
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2150
            
2151
        if not output.endswith(newline):
2152
            output += newline
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2153
        if outfile is not None:
2154
            outfile.write(output)
2155
        else:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2156
            h = open(self.filename, 'wb')
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2157
            h.write(output)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2158
            h.close()
2159
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2160
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2161
    def validate(self, validator, preserve_errors=False, copy=False,
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2162
                 section=None):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2163
        """
2164
        Test the ConfigObj against a configspec.
2165
        
2166
        It uses the ``validator`` object from *validate.py*.
2167
        
2168
        To run ``validate`` on the current ConfigObj, call: ::
2169
        
2170
            test = config.validate(validator)
2171
        
2172
        (Normally having previously passed in the configspec when the ConfigObj
2173
        was created - you can dynamically assign a dictionary of checks to the
2174
        ``configspec`` attribute of a section though).
2175
        
2176
        It returns ``True`` if everything passes, or a dictionary of
2177
        pass/fails (True/False). If every member of a subsection passes, it
2178
        will just have the value ``True``. (It also returns ``False`` if all
2179
        members fail).
2180
        
2181
        In addition, it converts the values from strings to their native
2182
        types if their checks pass (and ``stringify`` is set).
2183
        
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2184
        If ``preserve_errors`` is ``True`` (``False`` is default) then instead
2185
        of a marking a fail with a ``False``, it will preserve the actual
2186
        exception object. This can contain info about the reason for failure.
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2187
        For example the ``VdtValueTooSmallError`` indicates that the value
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2188
        supplied was too small. If a value (or section) is missing it will
2189
        still be marked as ``False``.
2190
        
2191
        You must have the validate module to use ``preserve_errors=True``.
2192
        
2193
        You can then use the ``flatten_errors`` function to turn your nested
2194
        results dictionary into a flattened list of failures - useful for
2195
        displaying meaningful error messages.
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2196
        """
2197
        if section is None:
2198
            if self.configspec is None:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2199
                raise ValueError('No configspec supplied.')
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2200
            if preserve_errors:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2201
                # We do this once to remove a top level dependency on the validate module
2202
                # Which makes importing configobj faster
2203
                from validate import VdtMissingValue
2204
                self._vdtMissingValue = VdtMissingValue
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2205
            section = self
2206
        #
2207
        spec_section = section.configspec
3239.1.2 by Matt Nordhoff
Restore hasattr -> getattr
2208
        if copy and getattr(section, '_configspec_initial_comment', None) is not None:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2209
            section.initial_comment = section._configspec_initial_comment
2210
            section.final_comment = section._configspec_final_comment
2211
            section.encoding = section._configspec_encoding
2212
            section.BOM = section._configspec_BOM
2213
            section.newlines = section._configspec_newlines
2214
            section.indent_type = section._configspec_indent_type
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2215
            
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2216
        if '__many__' in section.configspec:
2217
            many = spec_section['__many__']
2218
            # dynamically assign the configspecs
2219
            # for the sections below
2220
            for entry in section.sections:
2221
                self._handle_repeat(section[entry], many)
2222
        #
2223
        out = {}
2224
        ret_true = True
2225
        ret_false = True
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2226
        order = [k for k in section._order if k in spec_section]
2227
        order += [k for k in spec_section if k not in order]
2228
        for entry in order:
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2229
            if entry == '__many__':
2230
                continue
2231
            if (not entry in section.scalars) or (entry in section.defaults):
2232
                # missing entries
2233
                # or entries from defaults
2234
                missing = True
2235
                val = None
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2236
                if copy and not entry in section.scalars:
2237
                    # copy comments
2238
                    section.comments[entry] = (
2239
                        section._configspec_comments.get(entry, []))
2240
                    section.inline_comments[entry] = (
2241
                        section._configspec_inline_comments.get(entry, ''))
2242
                #
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2243
            else:
2244
                missing = False
2245
                val = section[entry]
2246
            try:
2247
                check = validator.check(spec_section[entry],
2248
                                        val,
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2249
                                        missing=missing
2250
                                        )
2251
            except validator.baseErrorClass, e:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2252
                if not preserve_errors or isinstance(e, self._vdtMissingValue):
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2253
                    out[entry] = False
2254
                else:
2255
                    # preserve the error
2256
                    out[entry] = e
2257
                    ret_false = False
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2258
                ret_true = False
2259
            else:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2260
                try: 
2261
                    section.default_values.pop(entry, None)
2262
                except AttributeError: 
2263
                    # For Python 2.2 compatibility
2264
                    try:
2265
                        del section.default_values[entry]
2266
                    except KeyError:
2267
                        pass
2268
                    
3239.1.2 by Matt Nordhoff
Restore hasattr -> getattr
2269
                if getattr(validator, 'get_default_value', None) is not None:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2270
                    try: 
2271
                        section.default_values[entry] = validator.get_default_value(spec_section[entry])
2272
                    except KeyError:
2273
                        # No default
2274
                        pass
2275
                    
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2276
                ret_false = False
2277
                out[entry] = True
2278
                if self.stringify or missing:
2279
                    # if we are doing type conversion
2280
                    # or the value is a supplied default
2281
                    if not self.stringify:
2282
                        if isinstance(check, (list, tuple)):
2283
                            # preserve lists
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2284
                            check = [self._str(item) for item in check]
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2285
                        elif missing and check is None:
2286
                            # convert the None from a default to a ''
2287
                            check = ''
2288
                        else:
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2289
                            check = self._str(check)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2290
                    if (check != val) or missing:
2291
                        section[entry] = check
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2292
                if not copy and missing and entry not in section.defaults:
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2293
                    section.defaults.append(entry)
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2294
        # Missing sections will have been created as empty ones when the
2295
        # configspec was read.
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2296
        for entry in section.sections:
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2297
            # FIXME: this means DEFAULT is not copied in copy mode
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2298
            if section is self and entry == 'DEFAULT':
2299
                continue
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2300
            if copy:
2301
                section.comments[entry] = section._cs_section_comments[entry]
2302
                section.inline_comments[entry] = (
2303
                    section._cs_section_inline_comments[entry])
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2304
            check = self.validate(validator, preserve_errors=preserve_errors,
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2305
                copy=copy, section=section[entry])
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2306
            out[entry] = check
2307
            if check == False:
2308
                ret_true = False
2309
            elif check == True:
2310
                ret_false = False
2311
            else:
2312
                ret_true = False
2313
                ret_false = False
2314
        #
2315
        if ret_true:
2316
            return True
2317
        elif ret_false:
2318
            return False
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2319
        return out
2320
2321
2322
    def reset(self):
2323
        """Clear ConfigObj instance and restore to 'freshly created' state."""
2324
        self.clear()
2325
        self._initialise()
2326
        # FIXME: Should be done by '_initialise', but ConfigObj constructor (and reload)
2327
        #        requires an empty dictionary
2328
        self.configspec = None
2329
        # Just to be sure ;-)
2330
        self._original_configspec = None
2331
        
2332
        
2333
    def reload(self):
2334
        """
2335
        Reload a ConfigObj from file.
2336
        
2337
        This method raises a ``ReloadError`` if the ConfigObj doesn't have
2338
        a filename attribute pointing to a file.
2339
        """
2340
        if not isinstance(self.filename, StringTypes):
2341
            raise ReloadError()
2342
2343
        filename = self.filename
2344
        current_options = {}
2345
        for entry in OPTION_DEFAULTS:
2346
            if entry == 'configspec':
2347
                continue
2348
            current_options[entry] = getattr(self, entry)
2349
            
2350
        configspec = self._original_configspec
2351
        current_options['configspec'] = configspec
2352
            
2353
        self.clear()
2354
        self._initialise(current_options)
2355
        self._load(filename, configspec)
2356
        
2357
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2358
2359
class SimpleVal(object):
2360
    """
2361
    A simple validator.
2362
    Can be used to check that all members expected are present.
2363
    
2364
    To use it, provide a configspec with all your members in (the value given
2365
    will be ignored). Pass an instance of ``SimpleVal`` to the ``validate``
2366
    method of your ``ConfigObj``. ``validate`` will return ``True`` if all
2367
    members are present, or a dictionary with True/False meaning
2368
    present/missing. (Whole missing sections will be replaced with ``False``)
2369
    """
2370
    
2371
    def __init__(self):
2372
        self.baseErrorClass = ConfigObjError
2373
    
2374
    def check(self, check, member, missing=False):
2375
        """A dummy check method, always returns the value unchanged."""
2376
        if missing:
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2377
            raise self.baseErrorClass()
1185.12.49 by Aaron Bentley
Switched to ConfigObj
2378
        return member
2379
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2380
1556.2.1 by Aaron Bentley
Switched to ConfigObj 4.2.0
2381
# Check / processing functions for options
2382
def flatten_errors(cfg, res, levels=None, results=None):
2383
    """
2384
    An example function that will turn a nested dictionary of results
2385
    (as returned by ``ConfigObj.validate``) into a flat list.
2386
    
2387
    ``cfg`` is the ConfigObj instance being checked, ``res`` is the results
2388
    dictionary returned by ``validate``.
2389
    
2390
    (This is a recursive function, so you shouldn't use the ``levels`` or
2391
    ``results`` arguments - they are used by the function.
2392
    
2393
    Returns a list of keys that failed. Each member of the list is a tuple :
2394
    ::
2395
    
2396
        ([list of sections...], key, result)
2397
    
2398
    If ``validate`` was called with ``preserve_errors=False`` (the default)
2399
    then ``result`` will always be ``False``.
2400
2401
    *list of sections* is a flattened list of sections that the key was found
2402
    in.
2403
    
2404
    If the section was missing then key will be ``None``.
2405
    
2406
    If the value (or section) was missing then ``result`` will be ``False``.
2407
    
2408
    If ``validate`` was called with ``preserve_errors=True`` and a value
2409
    was present, but failed the check, then ``result`` will be the exception
2410
    object returned. You can use this as a string that describes the failure.
2411
    
2412
    For example *The value "3" is of the wrong type*.
2413
    
2414
    >>> import validate
2415
    >>> vtor = validate.Validator()
2416
    >>> my_ini = '''
2417
    ...     option1 = True
2418
    ...     [section1]
2419
    ...     option1 = True
2420
    ...     [section2]
2421
    ...     another_option = Probably
2422
    ...     [section3]
2423
    ...     another_option = True
2424
    ...     [[section3b]]
2425
    ...     value = 3
2426
    ...     value2 = a
2427
    ...     value3 = 11
2428
    ...     '''
2429
    >>> my_cfg = '''
2430
    ...     option1 = boolean()
2431
    ...     option2 = boolean()
2432
    ...     option3 = boolean(default=Bad_value)
2433
    ...     [section1]
2434
    ...     option1 = boolean()
2435
    ...     option2 = boolean()
2436
    ...     option3 = boolean(default=Bad_value)
2437
    ...     [section2]
2438
    ...     another_option = boolean()
2439
    ...     [section3]
2440
    ...     another_option = boolean()
2441
    ...     [[section3b]]
2442
    ...     value = integer
2443
    ...     value2 = integer
2444
    ...     value3 = integer(0, 10)
2445
    ...         [[[section3b-sub]]]
2446
    ...         value = string
2447
    ...     [section4]
2448
    ...     another_option = boolean()
2449
    ...     '''
2450
    >>> cs = my_cfg.split('\\n')
2451
    >>> ini = my_ini.split('\\n')
2452
    >>> cfg = ConfigObj(ini, configspec=cs)
2453
    >>> res = cfg.validate(vtor, preserve_errors=True)
2454
    >>> errors = []
2455
    >>> for entry in flatten_errors(cfg, res):
2456
    ...     section_list, key, error = entry
2457
    ...     section_list.insert(0, '[root]')
2458
    ...     if key is not None:
2459
    ...        section_list.append(key)
2460
    ...     else:
2461
    ...         section_list.append('[missing]')
2462
    ...     section_string = ', '.join(section_list)
2463
    ...     errors.append((section_string, ' = ', error))
2464
    >>> errors.sort()
2465
    >>> for entry in errors:
2466
    ...     print entry[0], entry[1], (entry[2] or 0)
2467
    [root], option2  =  0
2468
    [root], option3  =  the value "Bad_value" is of the wrong type.
2469
    [root], section1, option2  =  0
2470
    [root], section1, option3  =  the value "Bad_value" is of the wrong type.
2471
    [root], section2, another_option  =  the value "Probably" is of the wrong type.
2472
    [root], section3, section3b, section3b-sub, [missing]  =  0
2473
    [root], section3, section3b, value2  =  the value "a" is of the wrong type.
2474
    [root], section3, section3b, value3  =  the value "11" is too big.
2475
    [root], section4, [missing]  =  0
2476
    """
2477
    if levels is None:
2478
        # first time called
2479
        levels = []
2480
        results = []
2481
    if res is True:
2482
        return results
2483
    if res is False:
2484
        results.append((levels[:], None, False))
2485
        if levels:
2486
            levels.pop()
2487
        return results
2488
    for (key, val) in res.items():
2489
        if val == True:
2490
            continue
2491
        if isinstance(cfg.get(key), dict):
2492
            # Go down one level
2493
            levels.append(key)
2494
            flatten_errors(cfg[key], val, levels, results)
2495
            continue
2496
        results.append((levels[:], key, val))
2497
    #
2498
    # Go up one level
2499
    if levels:
2500
        levels.pop()
2501
    #
2502
    return results
2503
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
2504
2991.2.1 by Vincent Ladeuil
Update configobj to version 4.4.0:
2505
"""*A programming language is a medium of expression.* - Paul Graham"""