238
222
def build_UnaryAdd(self, o):
239
223
return self.build_Const(o.getChildren()[0])
248
return _builder.build(getObj(s))
228
return Builder().build(getObj(s))
230
def _splitlines(instring):
231
"""Split a string on lines, without losing line endings or truncating."""
252
234
class ConfigObjError(SyntaxError):
254
236
This is the base class for all errors that ConfigObj raises.
255
237
It is a subclass of SyntaxError.
257
def __init__(self, msg='', line_number=None, line=''):
239
def __init__(self, message='', line_number=None, line=''):
259
241
self.line_number = line_number
261
SyntaxError.__init__(self, msg)
242
self.message = message
243
SyntaxError.__init__(self, message)
264
245
class NestingError(ConfigObjError):
266
247
This error indicates a level of nesting that doesn't match.
270
250
class ParseError(ConfigObjError):
272
252
This error indicates that a line is badly written.
274
254
nor a valid section marker line.
278
class ReloadError(IOError):
280
A 'reload' operation failed.
281
This exception is a subclass of ``IOError``.
284
IOError.__init__(self, 'reload failed, filename is not set.')
287
257
class DuplicateError(ConfigObjError):
289
259
The keyword or section specified already exists.
293
262
class ConfigspecError(ConfigObjError):
295
264
An error occured whilst parsing a configspec.
299
267
class InterpolationError(ConfigObjError):
300
268
"""Base class for the two interpolation errors."""
303
270
class InterpolationLoopError(InterpolationError):
304
271
"""Maximum interpolation depth exceeded in string interpolation."""
640
586
elif isinstance(value, (list, tuple)):
641
587
for entry in value:
642
588
if not isinstance(entry, StringTypes):
643
raise TypeError('Value is not a string "%s".' % entry)
590
'Value is not a string "%s".' % entry)
645
raise TypeError('Value is not a string "%s".' % value)
592
raise TypeError, 'Value is not a string "%s".' % value
646
593
dict.__setitem__(self, key, value)
649
595
def __delitem__(self, key):
650
596
"""Remove items from the sequence when deleting."""
651
597
dict. __delitem__(self, key)
727
664
self[key] = default
732
"""D.items() -> list of D's (key, value) pairs, as 2-tuples"""
733
669
return zip((self.scalars + self.sections), self.values())
737
"""D.keys() -> list of D's keys"""
738
673
return (self.scalars + self.sections)
741
675
def values(self):
742
"""D.values() -> list of D's values"""
743
677
return [self[key] for key in (self.scalars + self.sections)]
746
679
def iteritems(self):
747
"""D.iteritems() -> an iterator over the (key, value) items of D"""
748
681
return iter(self.items())
751
683
def iterkeys(self):
752
"""D.iterkeys() -> an iterator over the keys of D"""
753
685
return iter((self.scalars + self.sections))
755
687
__iter__ = iterkeys
758
689
def itervalues(self):
759
"""D.itervalues() -> an iterator over the values of D"""
760
691
return iter(self.values())
763
693
def __repr__(self):
764
"""x.__repr__() <==> repr(x)"""
765
694
return '{%s}' % ', '.join([('%s: %s' % (repr(key), repr(self[key])))
766
695
for key in (self.scalars + self.sections)])
768
697
__str__ = __repr__
769
__str__.__doc__ = "x.__str__() <==> str(x)"
772
699
# Extra methods - not in a normal dictionary
1105
1022
3.2000000000000002
1107
1024
return float(self[key])
1110
def restore_default(self, key):
1112
Restore (and return) default value for the specified key.
1114
This method will only work for a ConfigObj that was created
1115
with a configspec and has been validated.
1117
If there is no default value for this key, ``KeyError`` is raised.
1119
default = self.default_values[key]
1120
dict.__setitem__(self, key, default)
1121
if key not in self.defaults:
1122
self.defaults.append(key)
1126
def restore_defaults(self):
1128
Recursively restore default values to all members
1131
This method will only work for a ConfigObj that was created
1132
with a configspec and has been validated.
1134
It doesn't delete or modify entries without default values.
1136
for key in self.default_values:
1137
self.restore_default(key)
1139
for section in self.sections:
1140
self[section].restore_defaults()
1143
1027
class ConfigObj(Section):
1144
1028
"""An object to read, create, and write config files."""
1242
1126
'true': True, 'false': False,
1246
1129
def __init__(self, infile=None, options=None, **kwargs):
1248
Parse a config file or create a config file object.
1131
Parse or create a config file object.
1250
1133
``ConfigObj(infile=None, options=None, **kwargs)``
1252
# init the superclass
1253
Section.__init__(self, self, 0, self)
1255
1135
if infile is None:
1257
1137
if options is None:
1260
1140
options = dict(options)
1262
1141
# keyword arguments take precedence over an options dictionary
1263
1142
options.update(kwargs)
1143
# init the superclass
1144
Section.__init__(self, self, 0, self)
1265
1146
defaults = OPTION_DEFAULTS.copy()
1147
for entry in options.keys():
1148
if entry not in defaults.keys():
1149
raise TypeError, 'Unrecognised option "%s".' % entry
1266
1150
# TODO: check the values too.
1267
for entry in options:
1268
if entry not in defaults:
1269
raise TypeError('Unrecognised option "%s".' % entry)
1271
1152
# Add any explicit options to the defaults
1272
1153
defaults.update(options)
1273
self._initialise(defaults)
1274
configspec = defaults['configspec']
1275
self._original_configspec = configspec
1276
self._load(infile, configspec)
1279
def _load(self, infile, configspec):
1155
# initialise a few variables
1156
self.filename = None
1158
self.raise_errors = defaults['raise_errors']
1159
self.interpolation = defaults['interpolation']
1160
self.list_values = defaults['list_values']
1161
self.create_empty = defaults['create_empty']
1162
self.file_error = defaults['file_error']
1163
self.stringify = defaults['stringify']
1164
self.indent_type = defaults['indent_type']
1165
self.encoding = defaults['encoding']
1166
self.default_encoding = defaults['default_encoding']
1168
self.newlines = None
1169
self.write_empty_values = defaults['write_empty_values']
1170
self.unrepr = defaults['unrepr']
1172
self.initial_comment = []
1173
self.final_comment = []
1175
self._terminated = False
1280
1177
if isinstance(infile, StringTypes):
1281
1178
self.filename = infile
1282
1179
if os.path.isfile(infile):
1283
h = open(infile, 'rb')
1284
infile = h.read() or []
1180
infile = open(infile).read() or []
1286
1181
elif self.file_error:
1287
1182
# raise an error if the file doesn't exist
1288
raise IOError('Config file not found: "%s".' % self.filename)
1183
raise IOError, 'Config file not found: "%s".' % self.filename
1290
1185
# file doesn't already exist
1291
1186
if self.create_empty:
1292
1187
# this is a good test that the filename specified
1293
# isn't impossible - like on a non-existent device
1188
# isn't impossible - like on a non existent device
1294
1189
h = open(infile, 'w')
1299
1193
elif isinstance(infile, (list, tuple)):
1300
1194
infile = list(infile)
1302
1195
elif isinstance(infile, dict):
1303
1196
# initialise self
1304
1197
# the Section class handles creating subsections
1305
1198
if isinstance(infile, ConfigObj):
1306
1199
# get a copy of our ConfigObj
1307
1200
infile = infile.dict()
1309
1201
for entry in infile:
1310
1202
self[entry] = infile[entry]
1311
1203
del self._errors
1313
if configspec is not None:
1314
self._handle_configspec(configspec)
1204
if defaults['configspec'] is not None:
1205
self._handle_configspec(defaults['configspec'])
1316
1207
self.configspec = None
1319
elif getattr(infile, 'read', None) is not None:
1209
elif hasattr(infile, 'read'):
1320
1210
# This supports file like objects
1321
1211
infile = infile.read() or []
1322
1212
# needs splitting into lines - but needs doing *after* decoding
1323
1213
# in case it's not an 8 bit encoding
1325
raise TypeError('infile must be a filename, file like object, or list of lines.')
1215
raise TypeError, ('infile must be a filename,'
1216
' file like object, or list of lines.')
1328
1219
# don't do it for the empty ConfigObj
1329
1220
infile = self._handle_bom(infile)
1360
1253
# delete private attributes
1361
1254
del self._errors
1363
if configspec is None:
1256
if defaults['configspec'] is None:
1364
1257
self.configspec = None
1366
self._handle_configspec(configspec)
1369
def _initialise(self, options=None):
1371
options = OPTION_DEFAULTS
1373
# initialise a few variables
1374
self.filename = None
1376
self.raise_errors = options['raise_errors']
1377
self.interpolation = options['interpolation']
1378
self.list_values = options['list_values']
1379
self.create_empty = options['create_empty']
1380
self.file_error = options['file_error']
1381
self.stringify = options['stringify']
1382
self.indent_type = options['indent_type']
1383
self.encoding = options['encoding']
1384
self.default_encoding = options['default_encoding']
1386
self.newlines = None
1387
self.write_empty_values = options['write_empty_values']
1388
self.unrepr = options['unrepr']
1390
self.initial_comment = []
1391
self.final_comment = []
1392
self.configspec = {}
1394
# Clear section attributes as well
1395
Section._initialise(self)
1259
self._handle_configspec(defaults['configspec'])
1398
1261
def __repr__(self):
1399
return ('ConfigObj({%s})' %
1400
', '.join([('%s: %s' % (repr(key), repr(self[key])))
1401
for key in (self.scalars + self.sections)]))
1262
return 'ConfigObj({%s})' % ', '.join(
1263
[('%s: %s' % (repr(key), repr(self[key]))) for key in
1264
(self.scalars + self.sections)])
1404
1266
def _handle_bom(self, infile):
1573
1429
reset_comment = False
1574
1430
comment_list.append(line)
1577
1432
if not done_start:
1578
1433
# preserve initial comment
1579
1434
self.initial_comment = comment_list
1580
1435
comment_list = []
1581
1436
done_start = True
1583
1437
reset_comment = True
1584
1438
# first we check if it's a section marker
1585
1439
mat = self._sectionmarker.match(line)
1586
1440
if mat is not None:
1587
1441
# is a section line
1588
(indent, sect_open, sect_name, sect_close, comment) = mat.groups()
1442
(indent, sect_open, sect_name, sect_close, comment) = (
1589
1444
if indent and (self.indent_type is None):
1590
1445
self.indent_type = indent
1591
1446
cur_depth = sect_open.count('[')
1592
1447
if cur_depth != sect_close.count(']'):
1593
self._handle_error("Cannot compute the section depth at line %s.",
1594
NestingError, infile, cur_index)
1449
"Cannot compute the section depth at line %s.",
1450
NestingError, infile, cur_index)
1597
1453
if cur_depth < this_section.depth:
1598
1454
# the new section is dropping back to a previous level
1600
parent = self._match_depth(this_section,
1456
parent = self._match_depth(
1602
1459
except SyntaxError:
1603
self._handle_error("Cannot compute nesting level at line %s.",
1604
NestingError, infile, cur_index)
1461
"Cannot compute nesting level at line %s.",
1462
NestingError, infile, cur_index)
1606
1464
elif cur_depth == this_section.depth:
1607
1465
# the new section is a sibling of the current section
1610
1468
# the new section is a child the current section
1611
1469
parent = this_section
1613
self._handle_error("Section too nested at line %s.",
1614
NestingError, infile, cur_index)
1472
"Section too nested at line %s.",
1473
NestingError, infile, cur_index)
1616
1475
sect_name = self._unquote(sect_name)
1617
1476
if parent.has_key(sect_name):
1618
self._handle_error('Duplicate section name at line %s.',
1619
DuplicateError, infile, cur_index)
1478
'Duplicate section name at line %s.',
1479
DuplicateError, infile, cur_index)
1622
1481
# create the new section
1623
1482
this_section = Section(
1797
1653
if self.stringify:
1798
1654
value = str(value)
1800
raise TypeError('Value "%s" is not a string.' % value)
1656
raise TypeError, 'Value "%s" is not a string.' % value
1660
wspace_plus = ' \r\t\n\v\t\'"'
1805
no_lists_no_quotes = not self.list_values and '\n' not in value and '#' not in value
1806
need_triple = multiline and ((("'" in value) and ('"' in value)) or ('\n' in value ))
1807
hash_triple_quote = multiline and not need_triple and ("'" in value) and ('"' in value) and ('#' in value)
1808
check_for_single = (no_lists_no_quotes or not need_triple) and not hash_triple_quote
1810
if check_for_single:
1665
if (not self.list_values and '\n' not in value) or not (multiline and
1666
((("'" in value) and ('"' in value)) or ('\n' in value))):
1811
1667
if not self.list_values:
1812
1668
# we don't quote if ``list_values=False``
1814
1670
# for normal values either single or double quotes will do
1815
1671
elif '\n' in value:
1816
1672
# will only happen if multiline is off - e.g. '\n' in key
1817
raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
1673
raise ConfigObjError, ('Value "%s" cannot be safely quoted.' %
1818
1675
elif ((value[0] not in wspace_plus) and
1819
1676
(value[-1] not in wspace_plus) and
1820
1677
(',' not in value)):
1823
quot = self._get_single_quote(value)
1680
if ("'" in value) and ('"' in value):
1681
raise ConfigObjError, (
1682
'Value "%s" cannot be safely quoted.' % value)
1825
1688
# if value has '\n' or "'" *and* '"', it will need triple quotes
1826
quot = self._get_triple_quote(value)
1828
if quot == noquot and '#' in value and self.list_values:
1829
quot = self._get_single_quote(value)
1689
if (value.find('"""') != -1) and (value.find("'''") != -1):
1690
raise ConfigObjError, (
1691
'Value "%s" cannot be safely quoted.' % value)
1692
if value.find('"""') == -1:
1831
1696
return quot % value
1834
def _get_single_quote(self, value):
1835
if ("'" in value) and ('"' in value):
1836
raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
1844
def _get_triple_quote(self, value):
1845
if (value.find('"""') != -1) and (value.find("'''") != -1):
1846
raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
1847
if value.find('"""') == -1:
1854
1698
def _handle_value(self, value):
1925
1768
# we've got to the end of the config, oops...
1927
1770
mat = multi_line.match(line)
1928
1771
if mat is None:
1929
1772
# a badly formed line
1931
1774
(value, comment) = mat.groups()
1932
1775
return (newvalue + value, comment, cur_index)
1935
1777
def _handle_configspec(self, configspec):
1936
1778
"""Parse the configspec."""
1937
1779
# FIXME: Should we check that the configspec was created with the
1938
# correct settings ? (i.e. ``list_values=False``)
1780
# correct settings ? (i.e. ``list_values=False``)
1939
1781
if not isinstance(configspec, ConfigObj):
1941
configspec = ConfigObj(configspec,
1783
configspec = ConfigObj(
1945
1788
except ConfigObjError, e:
1946
1789
# FIXME: Should these errors have a reference
1947
# to the already parsed ConfigObj ?
1790
# to the already parsed ConfigObj ?
1948
1791
raise ConfigspecError('Parsing configspec failed: %s' % e)
1949
1792
except IOError, e:
1950
1793
raise IOError('Reading configspec failed: %s' % e)
1952
1794
self._set_configspec_value(configspec, self)
1955
1796
def _set_configspec_value(self, configspec, section):
1956
1797
"""Used to recursively set configspec values."""
1957
1798
if '__many__' in configspec.sections:
1958
1799
section.configspec['__many__'] = configspec['__many__']
1959
1800
if len(configspec.sections) > 1:
1960
1801
# FIXME: can we supply any useful information here ?
1961
raise RepeatSectionError()
1963
if getattr(configspec, 'initial_comment', None) is not None:
1802
raise RepeatSectionError
1803
if hasattr(configspec, 'initial_comment'):
1964
1804
section._configspec_initial_comment = configspec.initial_comment
1965
1805
section._configspec_final_comment = configspec.final_comment
1966
1806
section._configspec_encoding = configspec.encoding
1967
1807
section._configspec_BOM = configspec.BOM
1968
1808
section._configspec_newlines = configspec.newlines
1969
1809
section._configspec_indent_type = configspec.indent_type
1971
1810
for entry in configspec.scalars:
1972
1811
section._configspec_comments[entry] = configspec.comments[entry]
1973
section._configspec_inline_comments[entry] = configspec.inline_comments[entry]
1812
section._configspec_inline_comments[entry] = (
1813
configspec.inline_comments[entry])
1974
1814
section.configspec[entry] = configspec[entry]
1975
1815
section._order.append(entry)
1977
1816
for entry in configspec.sections:
1978
1817
if entry == '__many__':
1981
1819
section._cs_section_comments[entry] = configspec.comments[entry]
1982
section._cs_section_inline_comments[entry] = configspec.inline_comments[entry]
1820
section._cs_section_inline_comments[entry] = (
1821
configspec.inline_comments[entry])
1983
1822
if not section.has_key(entry):
1984
1823
section[entry] = {}
1985
1824
self._set_configspec_value(configspec[entry], section[entry])
1988
1826
def _handle_repeat(self, section, configspec):
1989
1827
"""Dynamically assign configspec for repeated section."""
2026
1861
val = self._decode_element(self._quote(this_entry))
2028
1863
val = repr(this_entry)
2029
return '%s%s%s%s%s' % (indent_string,
2030
self._decode_element(self._quote(entry, multiline=False)),
2031
self._a_to_u(' = '),
2033
self._decode_element(comment))
1864
return '%s%s%s%s%s' % (
1866
self._decode_element(self._quote(entry, multiline=False)),
1867
self._a_to_u(' = '),
1869
self._decode_element(comment))
2036
1871
def _write_marker(self, indent_string, depth, entry, comment):
2037
1872
"""Write a section marker line"""
2038
return '%s%s%s%s%s' % (indent_string,
2039
self._a_to_u('[' * depth),
2040
self._quote(self._decode_element(entry), multiline=False),
2041
self._a_to_u(']' * depth),
2042
self._decode_element(comment))
1873
return '%s%s%s%s%s' % (
1875
self._a_to_u('[' * depth),
1876
self._quote(self._decode_element(entry), multiline=False),
1877
self._a_to_u(']' * depth),
1878
self._decode_element(comment))
2045
1880
def _handle_comment(self, comment):
2046
1881
"""Deal with a comment."""
2197
2028
if section is None:
2198
2029
if self.configspec is None:
2199
raise ValueError('No configspec supplied.')
2030
raise ValueError, 'No configspec supplied.'
2200
2031
if preserve_errors:
2201
# We do this once to remove a top level dependency on the validate module
2202
# Which makes importing configobj faster
2203
from validate import VdtMissingValue
2204
self._vdtMissingValue = VdtMissingValue
2032
if VdtMissingValue is None:
2033
raise ImportError('Missing validate module.')
2207
2036
spec_section = section.configspec
2208
if copy and getattr(section, '_configspec_initial_comment', None) is not None:
2037
if copy and hasattr(section, '_configspec_initial_comment'):
2209
2038
section.initial_comment = section._configspec_initial_comment
2210
2039
section.final_comment = section._configspec_final_comment
2211
2040
section.encoding = section._configspec_encoding
2212
2041
section.BOM = section._configspec_BOM
2213
2042
section.newlines = section._configspec_newlines
2214
2043
section.indent_type = section._configspec_indent_type
2216
2044
if '__many__' in section.configspec:
2217
2045
many = spec_section['__many__']
2218
2046
# dynamically assign the configspecs
2317
2130
elif ret_false:
2323
"""Clear ConfigObj instance and restore to 'freshly created' state."""
2326
# FIXME: Should be done by '_initialise', but ConfigObj constructor (and reload)
2327
# requires an empty dictionary
2328
self.configspec = None
2329
# Just to be sure ;-)
2330
self._original_configspec = None
2335
Reload a ConfigObj from file.
2337
This method raises a ``ReloadError`` if the ConfigObj doesn't have
2338
a filename attribute pointing to a file.
2340
if not isinstance(self.filename, StringTypes):
2343
filename = self.filename
2344
current_options = {}
2345
for entry in OPTION_DEFAULTS:
2346
if entry == 'configspec':
2348
current_options[entry] = getattr(self, entry)
2350
configspec = self._original_configspec
2351
current_options['configspec'] = configspec
2354
self._initialise(current_options)
2355
self._load(filename, configspec)
2359
2135
class SimpleVal(object):