16
16
# http://lists.sourceforge.net/lists/listinfo/configobj-develop
17
17
# Comments, suggestions and bug reports welcome.
20
19
from __future__ import generators
22
INTP_VER = sys.version_info[:2]
24
raise RuntimeError("Python v.2.2 or later needed")
27
# Bzr modification: Disabled import of 'compiler' module
28
# bzr doesn't use the 'unrepr' feature of configobj, so importing compiler just
29
# wastes several milliseconds on every single bzr invocation.
30
# -- Andrew Bennetts, 2008-10-14
33
from types import StringTypes
34
from warnings import warn
39
36
from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE
40
37
except ImportError:
489
def __newobj__(cls, *args):
491
return cls.__new__(cls, *args)
493
491
class Section(dict):
495
493
A dictionary-like object that represents a section in a config file.
497
495
It does string interpolation if the 'interpolation' attribute
498
496
of the 'main' object is set to True.
500
498
Interpolation is tried first from this object, then from the 'DEFAULT'
501
499
section of this object, next from the parent and its 'DEFAULT' section,
502
500
and so on until the main object is reached.
504
502
A Section will behave like an ordered dictionary - following the
505
503
order of the ``scalars`` and ``sections`` attributes.
506
504
You can use this to change the order of members.
508
506
Iteration follows the order: scalars, then sections.
512
def __setstate__(self, state):
513
dict.update(self, state[0])
514
self.__dict__.update(state[1])
516
def __reduce__(self):
517
state = (dict(self), self.__dict__)
518
return (__newobj__, (self.__class__,), state)
521
509
def __init__(self, parent, depth, main, indict=None, name=None):
523
511
* parent is the section above
593
586
def __setitem__(self, key, value, unrepr=False):
595
588
Correctly set a value.
597
590
Making dictionary values Section instances.
598
591
(We have to special case 'Section' instances - which are also dicts)
600
593
Keys must be strings.
601
594
Values need only be strings (or lists of strings) if
602
595
``main.stringify`` is set.
604
``unrepr`` must be set when setting a value to a dictionary, without
597
`unrepr`` must be set when setting a value to a dictionary, without
605
598
creating a new sub-section.
607
if not isinstance(key, basestring):
600
if not isinstance(key, StringTypes):
608
601
raise ValueError('The key "%s" is not a string.' % key)
610
603
# add the comment
611
if key not in self.comments:
604
if not self.comments.has_key(key):
612
605
self.comments[key] = []
613
606
self.inline_comments[key] = ''
614
607
# remove the entry from defaults
863
856
call_on_sections=False, **keywargs):
865
858
Walk every member and call a function on the keyword and value.
867
860
Return a dictionary of the return values
869
862
If the function raises an exception, raise the errror
870
863
unless ``raise_errors=False``, in which case set the return value to
873
866
Any unrecognised keyword arguments you pass to walk, will be pased on
874
867
to the function you pass in.
876
869
Note: if ``call_on_sections`` is ``True`` then - on encountering a
877
870
subsection, *first* the function is called for the *whole* subsection,
878
871
and then recurses into it's members. This means your function must be
879
872
able to handle strings, dictionaries and lists. This allows you
880
873
to change the key of subsections as well as for ordinary members. The
881
874
return value when called on the whole subsection has to be discarded.
883
876
See the encode and decode methods for examples, including functions.
885
.. admonition:: caution
887
880
You can use ``walk`` to transform the names of members of a section
888
881
but you mustn't add or delete members.
890
883
>>> config = '''[XXXXsection]
891
884
... XXXXkey = XXXXvalue'''.splitlines()
892
885
>>> cfg = ConfigObj(config)
894
ConfigObj({'XXXXsection': {'XXXXkey': 'XXXXvalue'}})
887
{'XXXXsection': {'XXXXkey': 'XXXXvalue'}}
895
888
>>> def transform(section, key):
896
889
... val = section[key]
897
890
... newkey = key.replace('XXXX', 'CLIENT1')
940
def decode(self, encoding):
942
Decode all strings and values to unicode, using the specified encoding.
944
Works with subsections and list values.
946
Uses the ``walk`` method.
948
Testing ``encode`` and ``decode``.
950
>>> m.decode('ascii')
951
>>> def testuni(val):
952
... for entry in val:
953
... if not isinstance(entry, unicode):
954
... print >> sys.stderr, type(entry)
955
... raise AssertionError, 'decode failed.'
956
... if isinstance(val[entry], dict):
957
... testuni(val[entry])
958
... elif not isinstance(val[entry], unicode):
959
... raise AssertionError, 'decode failed.'
961
>>> m.encode('ascii')
965
warn('use of ``decode`` is deprecated.', DeprecationWarning)
966
def decode(section, key, encoding=encoding, warn=True):
969
if isinstance(val, (list, tuple)):
972
newval.append(entry.decode(encoding))
973
elif isinstance(val, dict):
976
newval = val.decode(encoding)
977
newkey = key.decode(encoding)
978
section.rename(key, newkey)
979
section[newkey] = newval
980
# using ``call_on_sections`` allows us to modify section names
981
self.walk(decode, call_on_sections=True)
984
def encode(self, encoding):
986
Encode all strings and values from unicode,
987
using the specified encoding.
989
Works with subsections and list values.
990
Uses the ``walk`` method.
992
warn('use of ``encode`` is deprecated.', DeprecationWarning)
993
def encode(section, key, encoding=encoding):
996
if isinstance(val, (list, tuple)):
999
newval.append(entry.encode(encoding))
1000
elif isinstance(val, dict):
1003
newval = val.encode(encoding)
1004
newkey = key.encode(encoding)
1005
section.rename(key, newkey)
1006
section[newkey] = newval
1007
self.walk(encode, call_on_sections=True)
1010
def istrue(self, key):
1011
"""A deprecated version of ``as_bool``."""
1012
warn('use of ``istrue`` is deprecated. Use ``as_bool`` method '
1013
'instead.', DeprecationWarning)
1014
return self.as_bool(key)
947
1017
def as_bool(self, key):
949
1019
Accepts a key as input. The corresponding value must be a string or
950
1020
the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to
951
1021
retain compatibility with Python 2.2.
953
If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns
1023
If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns
956
If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns
1026
If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns
959
1029
``as_bool`` is not case sensitive.
961
1031
Any other input will raise a ``ValueError``.
963
1033
>>> a = ConfigObj()
964
1034
>>> a['a'] = 'fish'
965
1035
>>> a.as_bool('a')
1194
def __init__(self, infile=None, options=None, _inspec=False, **kwargs):
1242
def __init__(self, infile=None, options=None, **kwargs):
1196
1244
Parse a config file or create a config file object.
1198
1246
``ConfigObj(infile=None, options=None, **kwargs)``
1200
self._inspec = _inspec
1201
1248
# init the superclass
1202
1249
Section.__init__(self, self, 0, self)
1204
infile = infile or []
1205
options = dict(options or {})
1256
options = dict(options)
1207
1258
# keyword arguments take precedence over an options dictionary
1208
1259
options.update(kwargs)
1210
options['list_values'] = False
1212
1261
defaults = OPTION_DEFAULTS.copy()
1213
1262
# TODO: check the values too.
1214
1263
for entry in options:
1215
1264
if entry not in defaults:
1216
1265
raise TypeError('Unrecognised option "%s".' % entry)
1218
1267
# Add any explicit options to the defaults
1219
1268
defaults.update(options)
1220
1269
self._initialise(defaults)
1221
1270
configspec = defaults['configspec']
1222
1271
self._original_configspec = configspec
1223
1272
self._load(infile, configspec)
1226
1275
def _load(self, infile, configspec):
1227
if isinstance(infile, basestring):
1276
if isinstance(infile, StringTypes):
1228
1277
self.filename = infile
1229
1278
if os.path.isfile(infile):
1230
1279
h = open(infile, 'rb')
1246
1295
elif isinstance(infile, (list, tuple)):
1247
1296
infile = list(infile)
1249
1298
elif isinstance(infile, dict):
1250
1299
# initialise self
1251
1300
# the Section class handles creating subsections
1252
1301
if isinstance(infile, ConfigObj):
1253
1302
# get a copy of our ConfigObj
1254
1303
infile = infile.dict()
1256
1305
for entry in infile:
1257
1306
self[entry] = infile[entry]
1258
1307
del self._errors
1260
1309
if configspec is not None:
1261
1310
self._handle_configspec(configspec)
1263
1312
self.configspec = None
1266
elif getattr(infile, 'read', MISSING) is not MISSING:
1315
elif getattr(infile, 'read', None) is not None:
1267
1316
# This supports file like objects
1268
1317
infile = infile.read() or []
1269
1318
# needs splitting into lines - but needs doing *after* decoding
1270
1319
# in case it's not an 8 bit encoding
1272
1321
raise TypeError('infile must be a filename, file like object, or list of lines.')
1275
1324
# don't do it for the empty ConfigObj
1276
1325
infile = self._handle_bom(infile)
1333
1382
self.newlines = None
1334
1383
self.write_empty_values = options['write_empty_values']
1335
1384
self.unrepr = options['unrepr']
1337
1386
self.initial_comment = []
1338
1387
self.final_comment = []
1339
self.configspec = None
1342
self.list_values = False
1388
self.configspec = {}
1344
1390
# Clear section attributes as well
1345
1391
Section._initialise(self)
1348
1394
def __repr__(self):
1349
return ('ConfigObj({%s})' %
1350
', '.join([('%s: %s' % (repr(key), repr(self[key])))
1395
return ('ConfigObj({%s})' %
1396
', '.join([('%s: %s' % (repr(key), repr(self[key])))
1351
1397
for key in (self.scalars + self.sections)]))
1354
1400
def _handle_bom(self, infile):
1356
1402
Handle any BOM, and decode if necessary.
1358
1404
If an encoding is specified, that *must* be used - but the BOM should
1359
1405
still be removed (and the BOM attribute set).
1361
1407
(If the encoding is wrongly specified, then a BOM for an alternative
1362
1408
encoding won't be discovered or removed.)
1364
1410
If an encoding is not specified, UTF8 or UTF16 BOM will be detected and
1365
1411
removed. The BOM attribute will be set. UTF16 will be decoded to
1368
1414
NOTE: This method must not be called with an empty ``infile``.
1370
1416
Specifying the *wrong* encoding is likely to cause a
1371
1417
``UnicodeDecodeError``.
1373
1419
``infile`` must always be returned as a list of lines, but may be
1374
1420
passed in as a single string.
1715
1761
def _quote(self, value, multiline=True):
1717
1763
Return a safely quoted version of a value.
1719
1765
Raise a ConfigObjError if the value cannot be safely quoted.
1720
1766
If multiline is ``True`` (default) then use triple quotes
1723
* Don't quote values that don't need it.
1724
* Recursively quote members of a list and return a comma joined list.
1725
* Multiline is ``False`` for lists.
1726
* Obey list syntax for empty and single member lists.
1769
Don't quote values that don't need it.
1770
Recursively quote members of a list and return a comma joined list.
1771
Multiline is ``False`` for lists.
1772
Obey list syntax for empty and single member lists.
1728
1774
If ``list_values=False`` then the value is only quoted if it contains
1729
a ``\\n`` (is multiline) or '#'.
1775
a ``\n`` (is multiline) or '#'.
1731
1777
If ``write_empty_values`` is set, and the value is an empty string, it
1732
1778
won't be quoted.
1890
1931
def _handle_configspec(self, configspec):
1891
1932
"""Parse the configspec."""
1892
# FIXME: Should we check that the configspec was created with the
1933
# FIXME: Should we check that the configspec was created with the
1893
1934
# correct settings ? (i.e. ``list_values=False``)
1894
1935
if not isinstance(configspec, ConfigObj):
1896
1937
configspec = ConfigObj(configspec,
1897
1938
raise_errors=True,
1898
1939
file_error=True,
1900
1941
except ConfigObjError, e:
1901
1942
# FIXME: Should these errors have a reference
1902
1943
# to the already parsed ConfigObj ?
1903
1944
raise ConfigspecError('Parsing configspec failed: %s' % e)
1904
1945
except IOError, e:
1905
1946
raise IOError('Reading configspec failed: %s' % e)
1907
self.configspec = configspec
1911
def _set_configspec(self, section, copy):
1913
Called by validate. Handles setting the configspec on subsections
1914
including sections to be validated by __many__
1916
configspec = section.configspec
1917
many = configspec.get('__many__')
1918
if isinstance(many, dict):
1919
for entry in section.sections:
1920
if entry not in configspec:
1921
section[entry].configspec = many
1948
self._set_configspec_value(configspec, self)
1951
def _set_configspec_value(self, configspec, section):
1952
"""Used to recursively set configspec values."""
1953
if '__many__' in configspec.sections:
1954
section.configspec['__many__'] = configspec['__many__']
1955
if len(configspec.sections) > 1:
1956
# FIXME: can we supply any useful information here ?
1957
raise RepeatSectionError()
1959
if getattr(configspec, 'initial_comment', None) is not None:
1960
section._configspec_initial_comment = configspec.initial_comment
1961
section._configspec_final_comment = configspec.final_comment
1962
section._configspec_encoding = configspec.encoding
1963
section._configspec_BOM = configspec.BOM
1964
section._configspec_newlines = configspec.newlines
1965
section._configspec_indent_type = configspec.indent_type
1967
for entry in configspec.scalars:
1968
section._configspec_comments[entry] = configspec.comments[entry]
1969
section._configspec_inline_comments[entry] = configspec.inline_comments[entry]
1970
section.configspec[entry] = configspec[entry]
1971
section._order.append(entry)
1923
1973
for entry in configspec.sections:
1924
1974
if entry == '__many__':
1926
if entry not in section:
1930
section.comments[entry] = configspec.comments.get(entry, [])
1931
section.inline_comments[entry] = configspec.inline_comments.get(entry, '')
1933
# Could be a scalar when we expect a section
1934
if isinstance(section[entry], Section):
1935
section[entry].configspec = configspec[entry]
1977
section._cs_section_comments[entry] = configspec.comments[entry]
1978
section._cs_section_inline_comments[entry] = configspec.inline_comments[entry]
1979
if not section.has_key(entry):
1981
self._set_configspec_value(configspec[entry], section[entry])
1984
def _handle_repeat(self, section, configspec):
1985
"""Dynamically assign configspec for repeated section."""
1987
section_keys = configspec.sections
1988
scalar_keys = configspec.scalars
1989
except AttributeError:
1990
section_keys = [entry for entry in configspec
1991
if isinstance(configspec[entry], dict)]
1992
scalar_keys = [entry for entry in configspec
1993
if not isinstance(configspec[entry], dict)]
1995
if '__many__' in section_keys and len(section_keys) > 1:
1996
# FIXME: can we supply any useful information here ?
1997
raise RepeatSectionError()
2001
for entry in scalar_keys:
2002
val = configspec[entry]
2003
scalars[entry] = val
2004
for entry in section_keys:
2005
val = configspec[entry]
2006
if entry == '__many__':
2007
scalars[entry] = val
2009
sections[entry] = val
2011
section.configspec = scalars
2012
for entry in sections:
2013
if not section.has_key(entry):
2015
self._handle_repeat(section[entry], sections[entry])
1938
2018
def _write_line(self, indent_string, entry, this_entry, comment):
2080
2160
Test the ConfigObj against a configspec.
2082
2162
It uses the ``validator`` object from *validate.py*.
2084
2164
To run ``validate`` on the current ConfigObj, call: ::
2086
2166
test = config.validate(validator)
2088
2168
(Normally having previously passed in the configspec when the ConfigObj
2089
2169
was created - you can dynamically assign a dictionary of checks to the
2090
2170
``configspec`` attribute of a section though).
2092
2172
It returns ``True`` if everything passes, or a dictionary of
2093
2173
pass/fails (True/False). If every member of a subsection passes, it
2094
2174
will just have the value ``True``. (It also returns ``False`` if all
2097
2177
In addition, it converts the values from strings to their native
2098
2178
types if their checks pass (and ``stringify`` is set).
2100
2180
If ``preserve_errors`` is ``True`` (``False`` is default) then instead
2101
2181
of a marking a fail with a ``False``, it will preserve the actual
2102
2182
exception object. This can contain info about the reason for failure.
2103
2183
For example the ``VdtValueTooSmallError`` indicates that the value
2104
2184
supplied was too small. If a value (or section) is missing it will
2105
2185
still be marked as ``False``.
2107
2187
You must have the validate module to use ``preserve_errors=True``.
2109
2189
You can then use the ``flatten_errors`` function to turn your nested
2110
2190
results dictionary into a flattened list of failures - useful for
2111
2191
displaying meaningful error messages.
2118
2198
# Which makes importing configobj faster
2119
2199
from validate import VdtMissingValue
2120
2200
self._vdtMissingValue = VdtMissingValue
2125
section.initial_comment = section.configspec.initial_comment
2126
section.final_comment = section.configspec.final_comment
2127
section.encoding = section.configspec.encoding
2128
section.BOM = section.configspec.BOM
2129
section.newlines = section.configspec.newlines
2130
section.indent_type = section.configspec.indent_type
2133
configspec = section.configspec
2134
self._set_configspec(section, copy)
2136
def validate_entry(entry, spec, val, missing, ret_true, ret_false):
2203
spec_section = section.configspec
2204
if copy and getattr(section, '_configspec_initial_comment', None) is not None:
2205
section.initial_comment = section._configspec_initial_comment
2206
section.final_comment = section._configspec_final_comment
2207
section.encoding = section._configspec_encoding
2208
section.BOM = section._configspec_BOM
2209
section.newlines = section._configspec_newlines
2210
section.indent_type = section._configspec_indent_type
2212
if '__many__' in section.configspec:
2213
many = spec_section['__many__']
2214
# dynamically assign the configspecs
2215
# for the sections below
2216
for entry in section.sections:
2217
self._handle_repeat(section[entry], many)
2222
order = [k for k in section._order if k in spec_section]
2223
order += [k for k in spec_section if k not in order]
2225
if entry == '__many__':
2227
if (not entry in section.scalars) or (entry in section.defaults):
2229
# or entries from defaults
2232
if copy and not entry in section.scalars:
2234
section.comments[entry] = (
2235
section._configspec_comments.get(entry, []))
2236
section.inline_comments[entry] = (
2237
section._configspec_inline_comments.get(entry, ''))
2241
val = section[entry]
2138
check = validator.check(spec,
2243
check = validator.check(spec_section[entry],
2140
2245
missing=missing
2181
2287
section[entry] = check
2182
2288
if not copy and missing and entry not in section.defaults:
2183
2289
section.defaults.append(entry)
2184
return ret_true, ret_false
2191
unvalidated = [k for k in section.scalars if k not in configspec]
2192
incorrect_sections = [k for k in configspec.sections if k in section.scalars]
2193
incorrect_scalars = [k for k in configspec.scalars if k in section.sections]
2195
for entry in configspec.scalars:
2196
if entry in ('__many__', '___many___'):
2200
if (not entry in section.scalars) or (entry in section.defaults):
2202
# or entries from defaults
2205
if copy and not entry in section.scalars:
2207
section.comments[entry] = (
2208
configspec.comments.get(entry, []))
2209
section.inline_comments[entry] = (
2210
configspec.inline_comments.get(entry, ''))
2214
val = section[entry]
2216
ret_true, ret_false = validate_entry(entry, configspec[entry], val,
2217
missing, ret_true, ret_false)
2220
if '__many__' in configspec.scalars:
2221
many = configspec['__many__']
2222
elif '___many___' in configspec.scalars:
2223
many = configspec['___many___']
2225
if many is not None:
2226
for entry in unvalidated:
2227
val = section[entry]
2228
ret_true, ret_false = validate_entry(entry, many, val, False,
2229
ret_true, ret_false)
2231
for entry in incorrect_scalars:
2233
if not preserve_errors:
2237
msg = 'Value %r was provided as a section' % entry
2238
out[entry] = validator.baseErrorClass(msg)
2239
for entry in incorrect_sections:
2241
if not preserve_errors:
2245
msg = 'Section %r was provided as a single value' % entry
2246
out[entry] = validator.baseErrorClass(msg)
2248
2290
# Missing sections will have been created as empty ones when the
2249
2291
# configspec was read.
2250
2292
for entry in section.sections:
2251
2293
# FIXME: this means DEFAULT is not copied in copy mode
2252
2294
if section is self and entry == 'DEFAULT':
2254
if section[entry].configspec is None:
2257
section.comments[entry] = configspec.comments.get(entry, [])
2258
section.inline_comments[entry] = configspec.inline_comments.get(entry, '')
2259
check = self.validate(validator, preserve_errors=preserve_errors, copy=copy, section=section[entry])
2297
section.comments[entry] = section._cs_section_comments[entry]
2298
section.inline_comments[entry] = (
2299
section._cs_section_inline_comments[entry])
2300
check = self.validate(validator, preserve_errors=preserve_errors,
2301
copy=copy, section=section[entry])
2260
2302
out[entry] = check
2261
2303
if check == False:
2262
2304
ret_true = False
2300
2342
if entry == 'configspec':
2302
2344
current_options[entry] = getattr(self, entry)
2304
2346
configspec = self._original_configspec
2305
2347
current_options['configspec'] = configspec
2308
2350
self._initialise(current_options)
2309
2351
self._load(filename, configspec)
2313
2355
class SimpleVal(object):
2315
2357
A simple validator.
2316
2358
Can be used to check that all members expected are present.
2318
2360
To use it, provide a configspec with all your members in (the value given
2319
2361
will be ignored). Pass an instance of ``SimpleVal`` to the ``validate``
2320
2362
method of your ``ConfigObj``. ``validate`` will return ``True`` if all
2321
2363
members are present, or a dictionary with True/False meaning
2322
2364
present/missing. (Whole missing sections will be replaced with ``False``)
2325
2367
def __init__(self):
2326
2368
self.baseErrorClass = ConfigObjError
2328
2370
def check(self, check, member, missing=False):
2329
2371
"""A dummy check method, always returns the value unchanged."""
2338
2380
An example function that will turn a nested dictionary of results
2339
2381
(as returned by ``ConfigObj.validate``) into a flat list.
2341
2383
``cfg`` is the ConfigObj instance being checked, ``res`` is the results
2342
2384
dictionary returned by ``validate``.
2344
2386
(This is a recursive function, so you shouldn't use the ``levels`` or
2345
``results`` arguments - they are used by the function.)
2387
``results`` arguments - they are used by the function.
2347
2389
Returns a list of keys that failed. Each member of the list is a tuple :
2351
2392
([list of sections...], key, result)
2353
2394
If ``validate`` was called with ``preserve_errors=False`` (the default)
2354
2395
then ``result`` will always be ``False``.
2356
2397
*list of sections* is a flattened list of sections that the key was found
2359
If the section was missing (or a section was expected and a scalar provided
2360
- or vice-versa) then key will be ``None``.
2400
If the section was missing then key will be ``None``.
2362
2402
If the value (or section) was missing then ``result`` will be ``False``.
2364
2404
If ``validate`` was called with ``preserve_errors=True`` and a value
2365
2405
was present, but failed the check, then ``result`` will be the exception
2366
2406
object returned. You can use this as a string that describes the failure.
2368
2408
For example *The value "3" is of the wrong type*.
2370
2410
>>> import validate
2371
2411
>>> vtor = validate.Validator()
2372
2412
>>> my_ini = '''