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
33
37
from types import StringTypes
34
38
from warnings import warn
182
186
class Builder(object):
184
188
def build(self, o):
185
189
m = getattr(self, 'build_' + o.__class__.__name__, None)
187
191
raise UnknownType(o.__class__.__name__)
190
194
def build_List(self, o):
191
195
return map(self.build, o.getChildren())
193
197
def build_Const(self, o):
196
200
def build_Dict(self, o):
198
202
i = iter(map(self.build, o.getChildren()))
203
207
def build_Tuple(self, o):
204
208
return tuple(self.build_List(o))
206
210
def build_Name(self, o):
207
211
if o.name == 'None':
223
227
if not isinstance(imag, complex) or imag.real != 0.0:
224
228
raise UnknownType('Add')
227
231
def build_Getattr(self, o):
228
232
parent = self.build(o.expr)
229
233
return getattr(parent, o.attrname)
231
235
def build_UnarySub(self, o):
232
236
return -self.build_Const(o.getChildren()[0])
234
238
def build_UnaryAdd(self, o):
235
239
return self.build_Const(o.getChildren()[0])
250
254
This is the base class for all errors that ConfigObj raises.
251
255
It is a subclass of SyntaxError.
253
def __init__(self, message='', line_number=None, line=''):
257
def __init__(self, msg='', line_number=None, line=''):
255
259
self.line_number = line_number
256
self.message = message
257
SyntaxError.__init__(self, message)
261
SyntaxError.__init__(self, msg)
260
264
class NestingError(ConfigObjError):
491
495
class Section(dict):
493
497
A dictionary-like object that represents a section in a config file.
495
499
It does string interpolation if the 'interpolation' attribute
496
500
of the 'main' object is set to True.
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.
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.
506
510
Iteration follows the order: scalars, then sections.
586
590
def __setitem__(self, key, value, unrepr=False):
588
592
Correctly set a value.
590
594
Making dictionary values Section instances.
591
595
(We have to special case 'Section' instances - which are also dicts)
593
597
Keys must be strings.
594
598
Values need only be strings (or lists of strings) if
595
599
``main.stringify`` is set.
597
601
`unrepr`` must be set when setting a value to a dictionary, without
598
602
creating a new sub-section.
600
604
if not isinstance(key, StringTypes):
601
605
raise ValueError('The key "%s" is not a string.' % key)
603
607
# add the comment
604
608
if not self.comments.has_key(key):
605
609
self.comments[key] = []
818
822
if (key in self and isinstance(self[key], dict) and
819
823
isinstance(val, dict)):
820
824
self[key].merge(val)
825
829
def rename(self, oldkey, newkey):
827
831
Change a keyname to another, without changing position in sequence.
829
833
Implemented so that transformations can be made on keys,
830
834
as well as on values. (used by encode and decode)
832
836
Also renames comments.
834
838
if oldkey in self.scalars:
856
860
call_on_sections=False, **keywargs):
858
862
Walk every member and call a function on the keyword and value.
860
864
Return a dictionary of the return values
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
866
870
Any unrecognised keyword arguments you pass to walk, will be pased on
867
871
to the function you pass in.
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.
876
880
See the encode and decode methods for examples, including functions.
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.
883
887
>>> config = '''[XXXXsection]
884
888
... XXXXkey = XXXXvalue'''.splitlines()
885
889
>>> cfg = ConfigObj(config)
940
944
def decode(self, encoding):
942
946
Decode all strings and values to unicode, using the specified encoding.
944
948
Works with subsections and list values.
946
950
Uses the ``walk`` method.
948
952
Testing ``encode`` and ``decode``.
949
953
>>> m = ConfigObj(a)
950
954
>>> m.decode('ascii')
986
990
Encode all strings and values from unicode,
987
991
using the specified encoding.
989
993
Works with subsections and list values.
990
994
Uses the ``walk`` method.
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.
1023
If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns
1027
If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns
1026
If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns
1030
If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns
1029
1033
``as_bool`` is not case sensitive.
1031
1035
Any other input will raise a ``ValueError``.
1033
1037
>>> a = ConfigObj()
1034
1038
>>> a['a'] = 'fish'
1035
1039
>>> a.as_bool('a')
1106
1110
def restore_default(self, key):
1108
1112
Restore (and return) default value for the specified key.
1110
1114
This method will only work for a ConfigObj that was created
1111
1115
with a configspec and has been validated.
1113
1117
If there is no default value for this key, ``KeyError`` is raised.
1115
1119
default = self.default_values[key]
1118
1122
self.defaults.append(key)
1122
1126
def restore_defaults(self):
1124
1128
Recursively restore default values to all members
1125
1129
that have them.
1127
1131
This method will only work for a ConfigObj that was created
1128
1132
with a configspec and has been validated.
1130
1134
It doesn't delete or modify entries without default values.
1132
1136
for key in self.default_values:
1133
1137
self.restore_default(key)
1135
1139
for section in self.sections:
1136
1140
self[section].restore_defaults()
1242
1246
def __init__(self, infile=None, options=None, **kwargs):
1244
1248
Parse a config file or create a config file object.
1246
1250
``ConfigObj(infile=None, options=None, **kwargs)``
1248
1252
# init the superclass
1249
1253
Section.__init__(self, self, 0, self)
1251
1255
if infile is None:
1253
1257
if options is None:
1256
1260
options = dict(options)
1258
1262
# keyword arguments take precedence over an options dictionary
1259
1263
options.update(kwargs)
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)
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)
1275
1279
def _load(self, infile, configspec):
1276
1280
if isinstance(infile, StringTypes):
1277
1281
self.filename = infile
1295
1299
elif isinstance(infile, (list, tuple)):
1296
1300
infile = list(infile)
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()
1305
1309
for entry in infile:
1306
1310
self[entry] = infile[entry]
1307
1311
del self._errors
1309
1313
if configspec is not None:
1310
1314
self._handle_configspec(configspec)
1312
1316
self.configspec = None
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
1321
1325
raise TypeError('infile must be a filename, file like object, or list of lines.')
1324
1328
# don't do it for the empty ConfigObj
1325
1329
infile = self._handle_bom(infile)
1356
1360
# delete private attributes
1357
1361
del self._errors
1359
1363
if configspec is None:
1360
1364
self.configspec = None
1362
1366
self._handle_configspec(configspec)
1365
1369
def _initialise(self, options=None):
1366
1370
if options is None:
1367
1371
options = OPTION_DEFAULTS
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']
1386
1390
self.initial_comment = []
1387
1391
self.final_comment = []
1388
1392
self.configspec = {}
1390
1394
# Clear section attributes as well
1391
1395
Section._initialise(self)
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)]))
1400
1404
def _handle_bom(self, infile):
1402
1406
Handle any BOM, and decode if necessary.
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).
1407
1411
(If the encoding is wrongly specified, then a BOM for an alternative
1408
1412
encoding won't be discovered or removed.)
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
1414
1418
NOTE: This method must not be called with an empty ``infile``.
1416
1420
Specifying the *wrong* encoding is likely to cause a
1417
1421
``UnicodeDecodeError``.
1419
1423
``infile`` must always be returned as a list of lines, but may be
1420
1424
passed in as a single string.
1425
1429
# the encoding specified doesn't have one
1427
1431
return self._decode(infile, self.encoding)
1429
1433
if isinstance(infile, (list, tuple)):
1430
1434
line = infile[0]
1447
1451
##self.BOM = True
1448
1452
# Don't need to remove BOM
1449
1453
return self._decode(infile, encoding)
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)
1456
1460
BOM = BOM_SET[enc]
1457
1461
if not line.startswith(BOM):
1458
1462
return self._decode(infile, self.encoding)
1460
1464
newline = line[len(BOM):]
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)
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):
1491
1495
# UTF16 - have to decode
1492
1496
return self._decode(infile, encoding)
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):
1511
1515
Decode infile to unicode. Using the specified encoding.
1513
1517
if is a string, it also needs converting to a list.
1515
1519
if isinstance(infile, StringTypes):
1569
1573
reset_comment = False
1570
1574
comment_list.append(line)
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
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)
1593
1597
if cur_depth < this_section.depth:
1594
1598
# the new section is dropping back to a previous level
1609
1613
self._handle_error("Section too nested at line %s.",
1610
1614
NestingError, infile, cur_index)
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)
1618
1622
# create the new section
1619
1623
this_section = Section(
1735
1739
def _handle_error(self, text, ErrorClass, infile, cur_index):
1737
1741
Handle an error according to the error settings.
1739
1743
Either raise the error or store it.
1740
1744
The error will have occured at ``cur_index``
1761
1765
def _quote(self, value, multiline=True):
1763
1767
Return a safely quoted version of a value.
1765
1769
Raise a ConfigObjError if the value cannot be safely quoted.
1766
1770
If multiline is ``True`` (default) then use triple quotes
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.
1774
1778
If ``list_values=False`` then the value is only quoted if it contains
1775
1779
a ``\n`` (is multiline) or '#'.
1777
1781
If ``write_empty_values`` is set, and the value is an empty string, it
1778
1782
won't be quoted.
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
1785
1789
if multiline and isinstance(value, (list, tuple)):
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
1806
1810
if check_for_single:
1807
1811
if not self.list_values:
1808
1812
# we don't quote if ``list_values=False``
1821
1825
# if value has '\n' or "'" *and* '"', it will need triple quotes
1822
1826
quot = self._get_triple_quote(value)
1824
1828
if quot == noquot and '#' in value and self.list_values:
1825
1829
quot = self._get_single_quote(value)
1827
1831
return quot % value
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)
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:
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):
1955
1959
if len(configspec.sections) > 1:
1956
1960
# FIXME: can we supply any useful information here ?
1957
1961
raise RepeatSectionError()
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
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)
1973
1977
for entry in configspec.sections:
1974
1978
if entry == '__many__':
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)]
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()
2001
2005
for entry in scalar_keys:
2053
2057
def write(self, outfile=None, section=None):
2055
2059
Write the current ConfigObj as a file
2057
2061
tekNico: FIXME: use StringIO instead of real files
2059
2063
>>> filename = a.filename
2060
2064
>>> a.filename = 'test.ini'
2093
2097
out.append(indent_string + comment_line)
2094
2098
this_entry = section[entry]
2095
2099
comment = self._handle_comment(section.inline_comments[entry])
2097
2101
if isinstance(this_entry, dict):
2099
2103
out.append(self._write_marker(
2135
2139
out[0] = BOM_UTF8 + out[0]
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)
2160
2164
Test the ConfigObj against a configspec.
2162
2166
It uses the ``validator`` object from *validate.py*.
2164
2168
To run ``validate`` on the current ConfigObj, call: ::
2166
2170
test = config.validate(validator)
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).
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
2177
2181
In addition, it converts the values from strings to their native
2178
2182
types if their checks pass (and ``stringify`` is set).
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``.
2187
2191
You must have the validate module to use ``preserve_errors=True``.
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
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
2257
2261
section.default_values.pop(entry, None)
2258
except AttributeError:
2262
except AttributeError:
2259
2263
# For Python 2.2 compatibility
2261
2265
del section.default_values[entry]
2262
2266
except KeyError:
2265
2269
if getattr(validator, 'get_default_value', None) is not None:
2267
2271
section.default_values[entry] = validator.get_default_value(spec_section[entry])
2268
2272
except KeyError:
2272
2276
ret_false = False
2273
2277
out[entry] = True
2274
2278
if self.stringify or missing:
2342
2346
if entry == 'configspec':
2344
2348
current_options[entry] = getattr(self, entry)
2346
2350
configspec = self._original_configspec
2347
2351
current_options['configspec'] = configspec
2350
2354
self._initialise(current_options)
2351
2355
self._load(filename, configspec)
2355
2359
class SimpleVal(object):
2357
2361
A simple validator.
2358
2362
Can be used to check that all members expected are present.
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``)
2367
2371
def __init__(self):
2368
2372
self.baseErrorClass = ConfigObjError
2370
2374
def check(self, check, member, missing=False):
2371
2375
"""A dummy check method, always returns the value unchanged."""
2380
2384
An example function that will turn a nested dictionary of results
2381
2385
(as returned by ``ConfigObj.validate``) into a flat list.
2383
2387
``cfg`` is the ConfigObj instance being checked, ``res`` is the results
2384
2388
dictionary returned by ``validate``.
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.
2389
2393
Returns a list of keys that failed. Each member of the list is a tuple :
2392
2396
([list of sections...], key, result)
2394
2398
If ``validate`` was called with ``preserve_errors=False`` (the default)
2395
2399
then ``result`` will always be ``False``.
2397
2401
*list of sections* is a flattened list of sections that the key was found
2400
2404
If the section was missing then key will be ``None``.
2402
2406
If the value (or section) was missing then ``result`` will be ``False``.
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.
2408
2412
For example *The value "3" is of the wrong type*.
2410
2414
>>> import validate
2411
2415
>>> vtor = validate.Validator()
2412
2416
>>> my_ini = '''