~jelmer/ubuntu/maverick/bzr/2.2.5

« back to all changes in this revision

Viewing changes to bzrlib/util/configobj/configobj.py

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2009-03-10 14:11:59 UTC
  • mfrom: (1.2.1 upstream) (3.1.68 jaunty)
  • Revision ID: james.westby@ubuntu.com-20090310141159-lwzzo5c1fwrtzgj4
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
import os, re
27
27
compiler = None
28
 
try:
29
 
    import compiler
30
 
except ImportError:
31
 
    # for IronPython
32
 
    pass
 
28
# Bzr modification: Disabled import of 'compiler' module
 
29
# bzr doesn't use the 'unrepr' feature of configobj, so importing compiler just
 
30
# wastes several milliseconds on every single bzr invocation.
 
31
#   -- Andrew Bennetts, 2008-10-14
 
32
#try:
 
33
#    import compiler
 
34
#except ImportError:
 
35
#    # for IronPython
 
36
#    pass
33
37
from types import StringTypes
34
38
from warnings import warn
35
39
try:
180
184
 
181
185
 
182
186
class Builder(object):
183
 
    
 
187
 
184
188
    def build(self, o):
185
189
        m = getattr(self, 'build_' + o.__class__.__name__, None)
186
190
        if m is None:
187
191
            raise UnknownType(o.__class__.__name__)
188
192
        return m(o)
189
 
    
 
193
 
190
194
    def build_List(self, o):
191
195
        return map(self.build, o.getChildren())
192
 
    
 
196
 
193
197
    def build_Const(self, o):
194
198
        return o.value
195
 
    
 
199
 
196
200
    def build_Dict(self, o):
197
201
        d = {}
198
202
        i = iter(map(self.build, o.getChildren()))
199
203
        for el in i:
200
204
            d[el] = i.next()
201
205
        return d
202
 
    
 
206
 
203
207
    def build_Tuple(self, o):
204
208
        return tuple(self.build_List(o))
205
 
    
 
209
 
206
210
    def build_Name(self, o):
207
211
        if o.name == 'None':
208
212
            return None
210
214
            return True
211
215
        if o.name == 'False':
212
216
            return False
213
 
        
 
217
 
214
218
        # An undefined Name
215
219
        raise UnknownType('Undefined Name')
216
 
    
 
220
 
217
221
    def build_Add(self, o):
218
222
        real, imag = map(self.build_Const, o.getChildren())
219
223
        try:
223
227
        if not isinstance(imag, complex) or imag.real != 0.0:
224
228
            raise UnknownType('Add')
225
229
        return real+imag
226
 
    
 
230
 
227
231
    def build_Getattr(self, o):
228
232
        parent = self.build(o.expr)
229
233
        return getattr(parent, o.attrname)
230
 
    
 
234
 
231
235
    def build_UnarySub(self, o):
232
236
        return -self.build_Const(o.getChildren()[0])
233
 
    
 
237
 
234
238
    def build_UnaryAdd(self, o):
235
239
        return self.build_Const(o.getChildren()[0])
236
240
 
250
254
    This is the base class for all errors that ConfigObj raises.
251
255
    It is a subclass of SyntaxError.
252
256
    """
253
 
    def __init__(self, message='', line_number=None, line=''):
 
257
    def __init__(self, msg='', line_number=None, line=''):
254
258
        self.line = line
255
259
        self.line_number = line_number
256
 
        self.message = message
257
 
        SyntaxError.__init__(self, message)
 
260
        self.msg = msg
 
261
        SyntaxError.__init__(self, msg)
258
262
 
259
263
 
260
264
class NestingError(ConfigObjError):
442
446
        (e.g., if we interpolated "$$" and returned "$").
443
447
        """
444
448
        raise NotImplementedError()
445
 
    
 
449
 
446
450
 
447
451
 
448
452
class ConfigParserInterpolation(InterpolationEngine):
491
495
class Section(dict):
492
496
    """
493
497
    A dictionary-like object that represents a section in a config file.
494
 
    
 
498
 
495
499
    It does string interpolation if the 'interpolation' attribute
496
500
    of the 'main' object is set to True.
497
 
    
 
501
 
498
502
    Interpolation is tried first from this object, then from the 'DEFAULT'
499
503
    section of this object, next from the parent and its 'DEFAULT' section,
500
504
    and so on until the main object is reached.
501
 
    
 
505
 
502
506
    A Section will behave like an ordered dictionary - following the
503
507
    order of the ``scalars`` and ``sections`` attributes.
504
508
    You can use this to change the order of members.
505
 
    
 
509
 
506
510
    Iteration follows the order: scalars, then sections.
507
511
    """
508
512
 
530
534
        # (rather than just passing to ``dict.__init__``)
531
535
        for entry, value in indict.iteritems():
532
536
            self[entry] = value
533
 
            
534
 
            
 
537
 
 
538
 
535
539
    def _initialise(self):
536
540
        # the sequence of scalar values in this Section
537
541
        self.scalars = []
586
590
    def __setitem__(self, key, value, unrepr=False):
587
591
        """
588
592
        Correctly set a value.
589
 
        
 
593
 
590
594
        Making dictionary values Section instances.
591
595
        (We have to special case 'Section' instances - which are also dicts)
592
 
        
 
596
 
593
597
        Keys must be strings.
594
598
        Values need only be strings (or lists of strings) if
595
599
        ``main.stringify`` is set.
596
 
        
 
600
 
597
601
        `unrepr`` must be set when setting a value to a dictionary, without
598
602
        creating a new sub-section.
599
603
        """
600
604
        if not isinstance(key, StringTypes):
601
605
            raise ValueError('The key "%s" is not a string.' % key)
602
 
        
 
606
 
603
607
        # add the comment
604
608
        if not self.comments.has_key(key):
605
609
            self.comments[key] = []
703
707
        """
704
708
        A version of clear that also affects scalars/sections
705
709
        Also clears comments and configspec.
706
 
        
 
710
 
707
711
        Leaves other attributes alone :
708
712
            depth/main/parent are not affected
709
713
        """
770
774
    def dict(self):
771
775
        """
772
776
        Return a deepcopy of self as a dictionary.
773
 
        
 
777
 
774
778
        All members that are ``Section`` instances are recursively turned to
775
779
        ordinary dictionaries - by calling their ``dict`` method.
776
 
        
 
780
 
777
781
        >>> n = a.dict()
778
782
        >>> n == a
779
783
        1
798
802
    def merge(self, indict):
799
803
        """
800
804
        A recursive update - useful for merging config files.
801
 
        
 
805
 
802
806
        >>> a = '''[section1]
803
807
        ...     option1 = True
804
808
        ...     [[subsection]]
818
822
            if (key in self and isinstance(self[key], dict) and
819
823
                                isinstance(val, dict)):
820
824
                self[key].merge(val)
821
 
            else:   
 
825
            else:
822
826
                self[key] = val
823
827
 
824
828
 
825
829
    def rename(self, oldkey, newkey):
826
830
        """
827
831
        Change a keyname to another, without changing position in sequence.
828
 
        
 
832
 
829
833
        Implemented so that transformations can be made on keys,
830
834
        as well as on values. (used by encode and decode)
831
 
        
 
835
 
832
836
        Also renames comments.
833
837
        """
834
838
        if oldkey in self.scalars:
856
860
            call_on_sections=False, **keywargs):
857
861
        """
858
862
        Walk every member and call a function on the keyword and value.
859
 
        
 
863
 
860
864
        Return a dictionary of the return values
861
 
        
 
865
 
862
866
        If the function raises an exception, raise the errror
863
867
        unless ``raise_errors=False``, in which case set the return value to
864
868
        ``False``.
865
 
        
 
869
 
866
870
        Any unrecognised keyword arguments you pass to walk, will be pased on
867
871
        to the function you pass in.
868
 
        
 
872
 
869
873
        Note: if ``call_on_sections`` is ``True`` then - on encountering a
870
874
        subsection, *first* the function is called for the *whole* subsection,
871
875
        and then recurses into it's members. This means your function must be
872
876
        able to handle strings, dictionaries and lists. This allows you
873
877
        to change the key of subsections as well as for ordinary members. The
874
878
        return value when called on the whole subsection has to be discarded.
875
 
        
 
879
 
876
880
        See  the encode and decode methods for examples, including functions.
877
 
        
 
881
 
878
882
        .. caution::
879
 
        
 
883
 
880
884
            You can use ``walk`` to transform the names of members of a section
881
885
            but you mustn't add or delete members.
882
 
        
 
886
 
883
887
        >>> config = '''[XXXXsection]
884
888
        ... XXXXkey = XXXXvalue'''.splitlines()
885
889
        >>> cfg = ConfigObj(config)
940
944
    def decode(self, encoding):
941
945
        """
942
946
        Decode all strings and values to unicode, using the specified encoding.
943
 
        
 
947
 
944
948
        Works with subsections and list values.
945
 
        
 
949
 
946
950
        Uses the ``walk`` method.
947
 
        
 
951
 
948
952
        Testing ``encode`` and ``decode``.
949
953
        >>> m = ConfigObj(a)
950
954
        >>> m.decode('ascii')
985
989
        """
986
990
        Encode all strings and values from unicode,
987
991
        using the specified encoding.
988
 
        
 
992
 
989
993
        Works with subsections and list values.
990
994
        Uses the ``walk`` method.
991
995
        """
1019
1023
        Accepts a key as input. The corresponding value must be a string or
1020
1024
        the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to
1021
1025
        retain compatibility with Python 2.2.
1022
 
        
1023
 
        If the string is one of  ``True``, ``On``, ``Yes``, or ``1`` it returns 
 
1026
 
 
1027
        If the string is one of  ``True``, ``On``, ``Yes``, or ``1`` it returns
1024
1028
        ``True``.
1025
 
        
1026
 
        If the string is one of  ``False``, ``Off``, ``No``, or ``0`` it returns 
 
1029
 
 
1030
        If the string is one of  ``False``, ``Off``, ``No``, or ``0`` it returns
1027
1031
        ``False``.
1028
 
        
 
1032
 
1029
1033
        ``as_bool`` is not case sensitive.
1030
 
        
 
1034
 
1031
1035
        Any other input will raise a ``ValueError``.
1032
 
        
 
1036
 
1033
1037
        >>> a = ConfigObj()
1034
1038
        >>> a['a'] = 'fish'
1035
1039
        >>> a.as_bool('a')
1061
1065
    def as_int(self, key):
1062
1066
        """
1063
1067
        A convenience method which coerces the specified value to an integer.
1064
 
        
 
1068
 
1065
1069
        If the value is an invalid literal for ``int``, a ``ValueError`` will
1066
1070
        be raised.
1067
 
        
 
1071
 
1068
1072
        >>> a = ConfigObj()
1069
1073
        >>> a['a'] = 'fish'
1070
1074
        >>> a.as_int('a')
1084
1088
    def as_float(self, key):
1085
1089
        """
1086
1090
        A convenience method which coerces the specified value to a float.
1087
 
        
 
1091
 
1088
1092
        If the value is an invalid literal for ``float``, a ``ValueError`` will
1089
1093
        be raised.
1090
 
        
 
1094
 
1091
1095
        >>> a = ConfigObj()
1092
1096
        >>> a['a'] = 'fish'
1093
1097
        >>> a.as_float('a')
1106
1110
    def restore_default(self, key):
1107
1111
        """
1108
1112
        Restore (and return) default value for the specified key.
1109
 
        
 
1113
 
1110
1114
        This method will only work for a ConfigObj that was created
1111
1115
        with a configspec and has been validated.
1112
 
        
 
1116
 
1113
1117
        If there is no default value for this key, ``KeyError`` is raised.
1114
1118
        """
1115
1119
        default = self.default_values[key]
1118
1122
            self.defaults.append(key)
1119
1123
        return default
1120
1124
 
1121
 
    
 
1125
 
1122
1126
    def restore_defaults(self):
1123
1127
        """
1124
1128
        Recursively restore default values to all members
1125
1129
        that have them.
1126
 
        
 
1130
 
1127
1131
        This method will only work for a ConfigObj that was created
1128
1132
        with a configspec and has been validated.
1129
 
        
 
1133
 
1130
1134
        It doesn't delete or modify entries without default values.
1131
1135
        """
1132
1136
        for key in self.default_values:
1133
1137
            self.restore_default(key)
1134
 
            
 
1138
 
1135
1139
        for section in self.sections:
1136
1140
            self[section].restore_defaults()
1137
1141
 
1242
1246
    def __init__(self, infile=None, options=None, **kwargs):
1243
1247
        """
1244
1248
        Parse a config file or create a config file object.
1245
 
        
 
1249
 
1246
1250
        ``ConfigObj(infile=None, options=None, **kwargs)``
1247
1251
        """
1248
1252
        # init the superclass
1249
1253
        Section.__init__(self, self, 0, self)
1250
 
        
 
1254
 
1251
1255
        if infile is None:
1252
1256
            infile = []
1253
1257
        if options is None:
1254
1258
            options = {}
1255
1259
        else:
1256
1260
            options = dict(options)
1257
 
            
 
1261
 
1258
1262
        # keyword arguments take precedence over an options dictionary
1259
1263
        options.update(kwargs)
1260
 
        
 
1264
 
1261
1265
        defaults = OPTION_DEFAULTS.copy()
1262
1266
        # TODO: check the values too.
1263
1267
        for entry in options:
1264
1268
            if entry not in defaults:
1265
1269
                raise TypeError('Unrecognised option "%s".' % entry)
1266
 
        
 
1270
 
1267
1271
        # Add any explicit options to the defaults
1268
1272
        defaults.update(options)
1269
1273
        self._initialise(defaults)
1270
1274
        configspec = defaults['configspec']
1271
1275
        self._original_configspec = configspec
1272
1276
        self._load(infile, configspec)
1273
 
        
1274
 
        
 
1277
 
 
1278
 
1275
1279
    def _load(self, infile, configspec):
1276
1280
        if isinstance(infile, StringTypes):
1277
1281
            self.filename = infile
1291
1295
                    h.write('')
1292
1296
                    h.close()
1293
1297
                infile = []
1294
 
                
 
1298
 
1295
1299
        elif isinstance(infile, (list, tuple)):
1296
1300
            infile = list(infile)
1297
 
            
 
1301
 
1298
1302
        elif isinstance(infile, dict):
1299
1303
            # initialise self
1300
1304
            # the Section class handles creating subsections
1301
1305
            if isinstance(infile, ConfigObj):
1302
1306
                # get a copy of our ConfigObj
1303
1307
                infile = infile.dict()
1304
 
                
 
1308
 
1305
1309
            for entry in infile:
1306
1310
                self[entry] = infile[entry]
1307
1311
            del self._errors
1308
 
            
 
1312
 
1309
1313
            if configspec is not None:
1310
1314
                self._handle_configspec(configspec)
1311
1315
            else:
1312
1316
                self.configspec = None
1313
1317
            return
1314
 
        
 
1318
 
1315
1319
        elif getattr(infile, 'read', None) is not None:
1316
1320
            # This supports file like objects
1317
1321
            infile = infile.read() or []
1319
1323
            # in case it's not an 8 bit encoding
1320
1324
        else:
1321
1325
            raise TypeError('infile must be a filename, file like object, or list of lines.')
1322
 
        
 
1326
 
1323
1327
        if infile:
1324
1328
            # don't do it for the empty ConfigObj
1325
1329
            infile = self._handle_bom(infile)
1337
1341
                break
1338
1342
 
1339
1343
            infile = [line.rstrip('\r\n') for line in infile]
1340
 
            
 
1344
 
1341
1345
        self._parse(infile)
1342
1346
        # if we had any errors, now is the time to raise them
1343
1347
        if self._errors:
1355
1359
            raise error
1356
1360
        # delete private attributes
1357
1361
        del self._errors
1358
 
        
 
1362
 
1359
1363
        if configspec is None:
1360
1364
            self.configspec = None
1361
1365
        else:
1362
1366
            self._handle_configspec(configspec)
1363
 
    
1364
 
    
 
1367
 
 
1368
 
1365
1369
    def _initialise(self, options=None):
1366
1370
        if options is None:
1367
1371
            options = OPTION_DEFAULTS
1368
 
            
 
1372
 
1369
1373
        # initialise a few variables
1370
1374
        self.filename = None
1371
1375
        self._errors = []
1382
1386
        self.newlines = None
1383
1387
        self.write_empty_values = options['write_empty_values']
1384
1388
        self.unrepr = options['unrepr']
1385
 
        
 
1389
 
1386
1390
        self.initial_comment = []
1387
1391
        self.final_comment = []
1388
1392
        self.configspec = {}
1389
 
        
 
1393
 
1390
1394
        # Clear section attributes as well
1391
1395
        Section._initialise(self)
1392
 
        
1393
 
        
 
1396
 
 
1397
 
1394
1398
    def __repr__(self):
1395
 
        return ('ConfigObj({%s})' % 
1396
 
                ', '.join([('%s: %s' % (repr(key), repr(self[key]))) 
 
1399
        return ('ConfigObj({%s})' %
 
1400
                ', '.join([('%s: %s' % (repr(key), repr(self[key])))
1397
1401
                for key in (self.scalars + self.sections)]))
1398
 
    
1399
 
    
 
1402
 
 
1403
 
1400
1404
    def _handle_bom(self, infile):
1401
1405
        """
1402
1406
        Handle any BOM, and decode if necessary.
1403
 
        
 
1407
 
1404
1408
        If an encoding is specified, that *must* be used - but the BOM should
1405
1409
        still be removed (and the BOM attribute set).
1406
 
        
 
1410
 
1407
1411
        (If the encoding is wrongly specified, then a BOM for an alternative
1408
1412
        encoding won't be discovered or removed.)
1409
 
        
 
1413
 
1410
1414
        If an encoding is not specified, UTF8 or UTF16 BOM will be detected and
1411
1415
        removed. The BOM attribute will be set. UTF16 will be decoded to
1412
1416
        unicode.
1413
 
        
 
1417
 
1414
1418
        NOTE: This method must not be called with an empty ``infile``.
1415
 
        
 
1419
 
1416
1420
        Specifying the *wrong* encoding is likely to cause a
1417
1421
        ``UnicodeDecodeError``.
1418
 
        
 
1422
 
1419
1423
        ``infile`` must always be returned as a list of lines, but may be
1420
1424
        passed in as a single string.
1421
1425
        """
1425
1429
            # the encoding specified doesn't have one
1426
1430
            # just decode
1427
1431
            return self._decode(infile, self.encoding)
1428
 
        
 
1432
 
1429
1433
        if isinstance(infile, (list, tuple)):
1430
1434
            line = infile[0]
1431
1435
        else:
1447
1451
                        ##self.BOM = True
1448
1452
                        # Don't need to remove BOM
1449
1453
                        return self._decode(infile, encoding)
1450
 
                    
 
1454
 
1451
1455
                # If we get this far, will *probably* raise a DecodeError
1452
1456
                # As it doesn't appear to start with a BOM
1453
1457
                return self._decode(infile, self.encoding)
1454
 
            
 
1458
 
1455
1459
            # Must be UTF8
1456
1460
            BOM = BOM_SET[enc]
1457
1461
            if not line.startswith(BOM):
1458
1462
                return self._decode(infile, self.encoding)
1459
 
            
 
1463
 
1460
1464
            newline = line[len(BOM):]
1461
 
            
 
1465
 
1462
1466
            # BOM removed
1463
1467
            if isinstance(infile, (list, tuple)):
1464
1468
                infile[0] = newline
1466
1470
                infile = newline
1467
1471
            self.BOM = True
1468
1472
            return self._decode(infile, self.encoding)
1469
 
        
 
1473
 
1470
1474
        # No encoding specified - so we need to check for UTF8/UTF16
1471
1475
        for BOM, (encoding, final_encoding) in BOMS.items():
1472
1476
            if not line.startswith(BOM):
1490
1494
                        return infile
1491
1495
                # UTF16 - have to decode
1492
1496
                return self._decode(infile, encoding)
1493
 
            
 
1497
 
1494
1498
        # No BOM discovered and no encoding specified, just return
1495
1499
        if isinstance(infile, StringTypes):
1496
1500
            # infile read from a file will be a single string
1509
1513
    def _decode(self, infile, encoding):
1510
1514
        """
1511
1515
        Decode infile to unicode. Using the specified encoding.
1512
 
        
 
1516
 
1513
1517
        if is a string, it also needs converting to a list.
1514
1518
        """
1515
1519
        if isinstance(infile, StringTypes):
1550
1554
        temp_list_values = self.list_values
1551
1555
        if self.unrepr:
1552
1556
            self.list_values = False
1553
 
            
 
1557
 
1554
1558
        comment_list = []
1555
1559
        done_start = False
1556
1560
        this_section = self
1557
1561
        maxline = len(infile) - 1
1558
1562
        cur_index = -1
1559
1563
        reset_comment = False
1560
 
        
 
1564
 
1561
1565
        while cur_index < maxline:
1562
1566
            if reset_comment:
1563
1567
                comment_list = []
1569
1573
                reset_comment = False
1570
1574
                comment_list.append(line)
1571
1575
                continue
1572
 
            
 
1576
 
1573
1577
            if not done_start:
1574
1578
                # preserve initial comment
1575
1579
                self.initial_comment = comment_list
1576
1580
                comment_list = []
1577
1581
                done_start = True
1578
 
                
 
1582
 
1579
1583
            reset_comment = True
1580
1584
            # first we check if it's a section marker
1581
1585
            mat = self._sectionmarker.match(line)
1589
1593
                    self._handle_error("Cannot compute the section depth at line %s.",
1590
1594
                                       NestingError, infile, cur_index)
1591
1595
                    continue
1592
 
                
 
1596
 
1593
1597
                if cur_depth < this_section.depth:
1594
1598
                    # the new section is dropping back to a previous level
1595
1599
                    try:
1608
1612
                else:
1609
1613
                    self._handle_error("Section too nested at line %s.",
1610
1614
                                       NestingError, infile, cur_index)
1611
 
                    
 
1615
 
1612
1616
                sect_name = self._unquote(sect_name)
1613
1617
                if parent.has_key(sect_name):
1614
1618
                    self._handle_error('Duplicate section name at line %s.',
1615
1619
                                       DuplicateError, infile, cur_index)
1616
1620
                    continue
1617
 
                
 
1621
 
1618
1622
                # create the new section
1619
1623
                this_section = Section(
1620
1624
                    parent,
1717
1721
        """
1718
1722
        Given a section and a depth level, walk back through the sections
1719
1723
        parents to see if the depth level matches a previous section.
1720
 
        
 
1724
 
1721
1725
        Return a reference to the right section,
1722
1726
        or raise a SyntaxError.
1723
1727
        """
1735
1739
    def _handle_error(self, text, ErrorClass, infile, cur_index):
1736
1740
        """
1737
1741
        Handle an error according to the error settings.
1738
 
        
 
1742
 
1739
1743
        Either raise the error or store it.
1740
1744
        The error will have occured at ``cur_index``
1741
1745
        """
1761
1765
    def _quote(self, value, multiline=True):
1762
1766
        """
1763
1767
        Return a safely quoted version of a value.
1764
 
        
 
1768
 
1765
1769
        Raise a ConfigObjError if the value cannot be safely quoted.
1766
1770
        If multiline is ``True`` (default) then use triple quotes
1767
1771
        if necessary.
1768
 
        
 
1772
 
1769
1773
        Don't quote values that don't need it.
1770
1774
        Recursively quote members of a list and return a comma joined list.
1771
1775
        Multiline is ``False`` for lists.
1772
1776
        Obey list syntax for empty and single member lists.
1773
 
        
 
1777
 
1774
1778
        If ``list_values=False`` then the value is only quoted if it contains
1775
1779
        a ``\n`` (is multiline) or '#'.
1776
 
        
 
1780
 
1777
1781
        If ``write_empty_values`` is set, and the value is an empty string, it
1778
1782
        won't be quoted.
1779
1783
        """
1781
1785
            # Only if multiline is set, so that it is used for values not
1782
1786
            # keys, and not values that are part of a list
1783
1787
            return ''
1784
 
        
 
1788
 
1785
1789
        if multiline and isinstance(value, (list, tuple)):
1786
1790
            if not value:
1787
1791
                return ','
1797
1801
 
1798
1802
        if not value:
1799
1803
            return '""'
1800
 
        
 
1804
 
1801
1805
        no_lists_no_quotes = not self.list_values and '\n' not in value and '#' not in value
1802
1806
        need_triple = multiline and ((("'" in value) and ('"' in value)) or ('\n' in value ))
1803
1807
        hash_triple_quote = multiline and not need_triple and ("'" in value) and ('"' in value) and ('#' in value)
1804
1808
        check_for_single = (no_lists_no_quotes or not need_triple) and not hash_triple_quote
1805
 
        
 
1809
 
1806
1810
        if check_for_single:
1807
1811
            if not self.list_values:
1808
1812
                # we don't quote if ``list_values=False``
1820
1824
        else:
1821
1825
            # if value has '\n' or "'" *and* '"', it will need triple quotes
1822
1826
            quot = self._get_triple_quote(value)
1823
 
        
 
1827
 
1824
1828
        if quot == noquot and '#' in value and self.list_values:
1825
1829
            quot = self._get_single_quote(value)
1826
 
                
 
1830
 
1827
1831
        return quot % value
1828
 
    
1829
 
    
 
1832
 
 
1833
 
1830
1834
    def _get_single_quote(self, value):
1831
1835
        if ("'" in value) and ('"' in value):
1832
1836
            raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
1835
1839
        else:
1836
1840
            quot = dquot
1837
1841
        return quot
1838
 
    
1839
 
    
 
1842
 
 
1843
 
1840
1844
    def _get_triple_quote(self, value):
1841
1845
        if (value.find('"""') != -1) and (value.find("'''") != -1):
1842
1846
            raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
1843
1847
        if value.find('"""') == -1:
1844
1848
            quot = tdquot
1845
1849
        else:
1846
 
            quot = tsquot 
 
1850
            quot = tsquot
1847
1851
        return quot
1848
1852
 
1849
1853
 
1930
1934
 
1931
1935
    def _handle_configspec(self, configspec):
1932
1936
        """Parse the configspec."""
1933
 
        # FIXME: Should we check that the configspec was created with the 
 
1937
        # FIXME: Should we check that the configspec was created with the
1934
1938
        #        correct settings ? (i.e. ``list_values=False``)
1935
1939
        if not isinstance(configspec, ConfigObj):
1936
1940
            try:
1944
1948
                raise ConfigspecError('Parsing configspec failed: %s' % e)
1945
1949
            except IOError, e:
1946
1950
                raise IOError('Reading configspec failed: %s' % e)
1947
 
        
 
1951
 
1948
1952
        self._set_configspec_value(configspec, self)
1949
1953
 
1950
1954
 
1955
1959
            if len(configspec.sections) > 1:
1956
1960
                # FIXME: can we supply any useful information here ?
1957
1961
                raise RepeatSectionError()
1958
 
            
 
1962
 
1959
1963
        if getattr(configspec, 'initial_comment', None) is not None:
1960
1964
            section._configspec_initial_comment = configspec.initial_comment
1961
1965
            section._configspec_final_comment = configspec.final_comment
1963
1967
            section._configspec_BOM = configspec.BOM
1964
1968
            section._configspec_newlines = configspec.newlines
1965
1969
            section._configspec_indent_type = configspec.indent_type
1966
 
            
 
1970
 
1967
1971
        for entry in configspec.scalars:
1968
1972
            section._configspec_comments[entry] = configspec.comments[entry]
1969
1973
            section._configspec_inline_comments[entry] = configspec.inline_comments[entry]
1970
1974
            section.configspec[entry] = configspec[entry]
1971
1975
            section._order.append(entry)
1972
 
            
 
1976
 
1973
1977
        for entry in configspec.sections:
1974
1978
            if entry == '__many__':
1975
1979
                continue
1976
 
            
 
1980
 
1977
1981
            section._cs_section_comments[entry] = configspec.comments[entry]
1978
1982
            section._cs_section_inline_comments[entry] = configspec.inline_comments[entry]
1979
1983
            if not section.has_key(entry):
1987
1991
            section_keys = configspec.sections
1988
1992
            scalar_keys = configspec.scalars
1989
1993
        except AttributeError:
1990
 
            section_keys = [entry for entry in configspec 
 
1994
            section_keys = [entry for entry in configspec
1991
1995
                                if isinstance(configspec[entry], dict)]
1992
 
            scalar_keys = [entry for entry in configspec 
 
1996
            scalar_keys = [entry for entry in configspec
1993
1997
                                if not isinstance(configspec[entry], dict)]
1994
 
            
 
1998
 
1995
1999
        if '__many__' in section_keys and len(section_keys) > 1:
1996
2000
            # FIXME: can we supply any useful information here ?
1997
2001
            raise RepeatSectionError()
1998
 
        
 
2002
 
1999
2003
        scalars = {}
2000
2004
        sections = {}
2001
2005
        for entry in scalar_keys:
2007
2011
                scalars[entry] = val
2008
2012
                continue
2009
2013
            sections[entry] = val
2010
 
            
 
2014
 
2011
2015
        section.configspec = scalars
2012
2016
        for entry in sections:
2013
2017
            if not section.has_key(entry):
2053
2057
    def write(self, outfile=None, section=None):
2054
2058
        """
2055
2059
        Write the current ConfigObj as a file
2056
 
        
 
2060
 
2057
2061
        tekNico: FIXME: use StringIO instead of real files
2058
 
        
 
2062
 
2059
2063
        >>> filename = a.filename
2060
2064
        >>> a.filename = 'test.ini'
2061
2065
        >>> a.write()
2066
2070
        if self.indent_type is None:
2067
2071
            # this can be true if initialised from a dictionary
2068
2072
            self.indent_type = DEFAULT_INDENT_TYPE
2069
 
            
 
2073
 
2070
2074
        out = []
2071
2075
        cs = self._a_to_u('#')
2072
2076
        csp = self._a_to_u('# ')
2080
2084
                if stripped_line and not stripped_line.startswith(cs):
2081
2085
                    line = csp + line
2082
2086
                out.append(line)
2083
 
                
 
2087
 
2084
2088
        indent_string = self.indent_type * section.depth
2085
2089
        for entry in (section.scalars + section.sections):
2086
2090
            if entry in section.defaults:
2093
2097
                out.append(indent_string + comment_line)
2094
2098
            this_entry = section[entry]
2095
2099
            comment = self._handle_comment(section.inline_comments[entry])
2096
 
            
 
2100
 
2097
2101
            if isinstance(this_entry, dict):
2098
2102
                # a section
2099
2103
                out.append(self._write_marker(
2108
2112
                    entry,
2109
2113
                    this_entry,
2110
2114
                    comment))
2111
 
                
 
2115
 
2112
2116
        if section is self:
2113
2117
            for line in self.final_comment:
2114
2118
                line = self._decode_element(line)
2117
2121
                    line = csp + line
2118
2122
                out.append(line)
2119
2123
            self.interpolation = int_val
2120
 
            
 
2124
 
2121
2125
        if section is not self:
2122
2126
            return out
2123
 
        
 
2127
 
2124
2128
        if (self.filename is None) and (outfile is None):
2125
2129
            # output a list of lines
2126
2130
            # might need to encode
2134
2138
                    out.append('')
2135
2139
                out[0] = BOM_UTF8 + out[0]
2136
2140
            return out
2137
 
        
 
2141
 
2138
2142
        # Turn the list to a string, joined with correct newlines
2139
2143
        newline = self.newlines or os.linesep
2140
2144
        output = self._a_to_u(newline).join(out)
2143
2147
        if self.BOM and ((self.encoding is None) or match_utf8(self.encoding)):
2144
2148
            # Add the UTF8 BOM
2145
2149
            output = BOM_UTF8 + output
2146
 
            
 
2150
 
2147
2151
        if not output.endswith(newline):
2148
2152
            output += newline
2149
2153
        if outfile is not None:
2158
2162
                 section=None):
2159
2163
        """
2160
2164
        Test the ConfigObj against a configspec.
2161
 
        
 
2165
 
2162
2166
        It uses the ``validator`` object from *validate.py*.
2163
 
        
 
2167
 
2164
2168
        To run ``validate`` on the current ConfigObj, call: ::
2165
 
        
 
2169
 
2166
2170
            test = config.validate(validator)
2167
 
        
 
2171
 
2168
2172
        (Normally having previously passed in the configspec when the ConfigObj
2169
2173
        was created - you can dynamically assign a dictionary of checks to the
2170
2174
        ``configspec`` attribute of a section though).
2171
 
        
 
2175
 
2172
2176
        It returns ``True`` if everything passes, or a dictionary of
2173
2177
        pass/fails (True/False). If every member of a subsection passes, it
2174
2178
        will just have the value ``True``. (It also returns ``False`` if all
2175
2179
        members fail).
2176
 
        
 
2180
 
2177
2181
        In addition, it converts the values from strings to their native
2178
2182
        types if their checks pass (and ``stringify`` is set).
2179
 
        
 
2183
 
2180
2184
        If ``preserve_errors`` is ``True`` (``False`` is default) then instead
2181
2185
        of a marking a fail with a ``False``, it will preserve the actual
2182
2186
        exception object. This can contain info about the reason for failure.
2183
2187
        For example the ``VdtValueTooSmallError`` indicates that the value
2184
2188
        supplied was too small. If a value (or section) is missing it will
2185
2189
        still be marked as ``False``.
2186
 
        
 
2190
 
2187
2191
        You must have the validate module to use ``preserve_errors=True``.
2188
 
        
 
2192
 
2189
2193
        You can then use the ``flatten_errors`` function to turn your nested
2190
2194
        results dictionary into a flattened list of failures - useful for
2191
2195
        displaying meaningful error messages.
2208
2212
            section.BOM = section._configspec_BOM
2209
2213
            section.newlines = section._configspec_newlines
2210
2214
            section.indent_type = section._configspec_indent_type
2211
 
            
 
2215
 
2212
2216
        if '__many__' in section.configspec:
2213
2217
            many = spec_section['__many__']
2214
2218
            # dynamically assign the configspecs
2253
2257
                    ret_false = False
2254
2258
                ret_true = False
2255
2259
            else:
2256
 
                try: 
 
2260
                try:
2257
2261
                    section.default_values.pop(entry, None)
2258
 
                except AttributeError: 
 
2262
                except AttributeError:
2259
2263
                    # For Python 2.2 compatibility
2260
2264
                    try:
2261
2265
                        del section.default_values[entry]
2262
2266
                    except KeyError:
2263
2267
                        pass
2264
 
                    
 
2268
 
2265
2269
                if getattr(validator, 'get_default_value', None) is not None:
2266
 
                    try: 
 
2270
                    try:
2267
2271
                        section.default_values[entry] = validator.get_default_value(spec_section[entry])
2268
2272
                    except KeyError:
2269
2273
                        # No default
2270
2274
                        pass
2271
 
                    
 
2275
 
2272
2276
                ret_false = False
2273
2277
                out[entry] = True
2274
2278
                if self.stringify or missing:
2324
2328
        self.configspec = None
2325
2329
        # Just to be sure ;-)
2326
2330
        self._original_configspec = None
2327
 
        
2328
 
        
 
2331
 
 
2332
 
2329
2333
    def reload(self):
2330
2334
        """
2331
2335
        Reload a ConfigObj from file.
2332
 
        
 
2336
 
2333
2337
        This method raises a ``ReloadError`` if the ConfigObj doesn't have
2334
2338
        a filename attribute pointing to a file.
2335
2339
        """
2342
2346
            if entry == 'configspec':
2343
2347
                continue
2344
2348
            current_options[entry] = getattr(self, entry)
2345
 
            
 
2349
 
2346
2350
        configspec = self._original_configspec
2347
2351
        current_options['configspec'] = configspec
2348
 
            
 
2352
 
2349
2353
        self.clear()
2350
2354
        self._initialise(current_options)
2351
2355
        self._load(filename, configspec)
2352
 
        
 
2356
 
2353
2357
 
2354
2358
 
2355
2359
class SimpleVal(object):
2356
2360
    """
2357
2361
    A simple validator.
2358
2362
    Can be used to check that all members expected are present.
2359
 
    
 
2363
 
2360
2364
    To use it, provide a configspec with all your members in (the value given
2361
2365
    will be ignored). Pass an instance of ``SimpleVal`` to the ``validate``
2362
2366
    method of your ``ConfigObj``. ``validate`` will return ``True`` if all
2363
2367
    members are present, or a dictionary with True/False meaning
2364
2368
    present/missing. (Whole missing sections will be replaced with ``False``)
2365
2369
    """
2366
 
    
 
2370
 
2367
2371
    def __init__(self):
2368
2372
        self.baseErrorClass = ConfigObjError
2369
 
    
 
2373
 
2370
2374
    def check(self, check, member, missing=False):
2371
2375
        """A dummy check method, always returns the value unchanged."""
2372
2376
        if missing:
2379
2383
    """
2380
2384
    An example function that will turn a nested dictionary of results
2381
2385
    (as returned by ``ConfigObj.validate``) into a flat list.
2382
 
    
 
2386
 
2383
2387
    ``cfg`` is the ConfigObj instance being checked, ``res`` is the results
2384
2388
    dictionary returned by ``validate``.
2385
 
    
 
2389
 
2386
2390
    (This is a recursive function, so you shouldn't use the ``levels`` or
2387
2391
    ``results`` arguments - they are used by the function.
2388
 
    
 
2392
 
2389
2393
    Returns a list of keys that failed. Each member of the list is a tuple :
2390
2394
    ::
2391
 
    
 
2395
 
2392
2396
        ([list of sections...], key, result)
2393
 
    
 
2397
 
2394
2398
    If ``validate`` was called with ``preserve_errors=False`` (the default)
2395
2399
    then ``result`` will always be ``False``.
2396
2400
 
2397
2401
    *list of sections* is a flattened list of sections that the key was found
2398
2402
    in.
2399
 
    
 
2403
 
2400
2404
    If the section was missing then key will be ``None``.
2401
 
    
 
2405
 
2402
2406
    If the value (or section) was missing then ``result`` will be ``False``.
2403
 
    
 
2407
 
2404
2408
    If ``validate`` was called with ``preserve_errors=True`` and a value
2405
2409
    was present, but failed the check, then ``result`` will be the exception
2406
2410
    object returned. You can use this as a string that describes the failure.
2407
 
    
 
2411
 
2408
2412
    For example *The value "3" is of the wrong type*.
2409
 
    
 
2413
 
2410
2414
    >>> import validate
2411
2415
    >>> vtor = validate.Validator()
2412
2416
    >>> my_ini = '''