/brz/remove-bazaar

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