~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Matt Nordhoff
  • Date: 2009-04-04 02:50:01 UTC
  • mfrom: (4253 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4256.
  • Revision ID: mnordhoff@mattnordhoff.com-20090404025001-z1403k0tatmc8l91
Merge bzr.dev, fixing conflicts.

Show diffs side-by-side

added added

removed removed

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