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