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.
1888
1931
def _handle_configspec(self, configspec):
1889
1932
"""Parse the configspec."""
1890
# FIXME: Should we check that the configspec was created with the
1933
# FIXME: Should we check that the configspec was created with the
1891
1934
# correct settings ? (i.e. ``list_values=False``)
1892
1935
if not isinstance(configspec, ConfigObj):
1894
1937
configspec = ConfigObj(configspec,
1895
1938
raise_errors=True,
1896
1939
file_error=True,
1898
1941
except ConfigObjError, e:
1899
1942
# FIXME: Should these errors have a reference
1900
1943
# to the already parsed ConfigObj ?
1901
1944
raise ConfigspecError('Parsing configspec failed: %s' % e)
1902
1945
except IOError, e:
1903
1946
raise IOError('Reading configspec failed: %s' % e)
1905
self.configspec = configspec
1909
def _set_configspec(self, section, copy):
1911
Called by validate. Handles setting the configspec on subsections
1912
including sections to be validated by __many__
1914
configspec = section.configspec
1915
many = configspec.get('__many__')
1916
if isinstance(many, dict):
1917
for entry in section.sections:
1918
if entry not in configspec:
1919
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)
1921
1973
for entry in configspec.sections:
1922
1974
if entry == '__many__':
1924
if entry not in section:
1928
section.comments[entry] = configspec.comments.get(entry, [])
1929
section.inline_comments[entry] = configspec.inline_comments.get(entry, '')
1931
# Could be a scalar when we expect a section
1932
if isinstance(section[entry], Section):
1933
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])
1936
2018
def _write_line(self, indent_string, entry, this_entry, comment):
2078
2160
Test the ConfigObj against a configspec.
2080
2162
It uses the ``validator`` object from *validate.py*.
2082
2164
To run ``validate`` on the current ConfigObj, call: ::
2084
2166
test = config.validate(validator)
2086
2168
(Normally having previously passed in the configspec when the ConfigObj
2087
2169
was created - you can dynamically assign a dictionary of checks to the
2088
2170
``configspec`` attribute of a section though).
2090
2172
It returns ``True`` if everything passes, or a dictionary of
2091
2173
pass/fails (True/False). If every member of a subsection passes, it
2092
2174
will just have the value ``True``. (It also returns ``False`` if all
2095
2177
In addition, it converts the values from strings to their native
2096
2178
types if their checks pass (and ``stringify`` is set).
2098
2180
If ``preserve_errors`` is ``True`` (``False`` is default) then instead
2099
2181
of a marking a fail with a ``False``, it will preserve the actual
2100
2182
exception object. This can contain info about the reason for failure.
2101
2183
For example the ``VdtValueTooSmallError`` indicates that the value
2102
2184
supplied was too small. If a value (or section) is missing it will
2103
2185
still be marked as ``False``.
2105
2187
You must have the validate module to use ``preserve_errors=True``.
2107
2189
You can then use the ``flatten_errors`` function to turn your nested
2108
2190
results dictionary into a flattened list of failures - useful for
2109
2191
displaying meaningful error messages.
2116
2198
# Which makes importing configobj faster
2117
2199
from validate import VdtMissingValue
2118
2200
self._vdtMissingValue = VdtMissingValue
2123
section.initial_comment = section.configspec.initial_comment
2124
section.final_comment = section.configspec.final_comment
2125
section.encoding = section.configspec.encoding
2126
section.BOM = section.configspec.BOM
2127
section.newlines = section.configspec.newlines
2128
section.indent_type = section.configspec.indent_type
2131
configspec = section.configspec
2132
self._set_configspec(section, copy)
2134
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]
2136
check = validator.check(spec,
2243
check = validator.check(spec_section[entry],
2138
2245
missing=missing
2179
2287
section[entry] = check
2180
2288
if not copy and missing and entry not in section.defaults:
2181
2289
section.defaults.append(entry)
2182
return ret_true, ret_false
2189
unvalidated = [k for k in section.scalars if k not in configspec]
2190
incorrect_sections = [k for k in configspec.sections if k in section.scalars]
2191
incorrect_scalars = [k for k in configspec.scalars if k in section.sections]
2193
for entry in configspec.scalars:
2194
if entry in ('__many__', '___many___'):
2198
if (not entry in section.scalars) or (entry in section.defaults):
2200
# or entries from defaults
2203
if copy and not entry in section.scalars:
2205
section.comments[entry] = (
2206
configspec.comments.get(entry, []))
2207
section.inline_comments[entry] = (
2208
configspec.inline_comments.get(entry, ''))
2212
val = section[entry]
2214
ret_true, ret_false = validate_entry(entry, configspec[entry], val,
2215
missing, ret_true, ret_false)
2218
if '__many__' in configspec.scalars:
2219
many = configspec['__many__']
2220
elif '___many___' in configspec.scalars:
2221
many = configspec['___many___']
2223
if many is not None:
2224
for entry in unvalidated:
2225
val = section[entry]
2226
ret_true, ret_false = validate_entry(entry, many, val, False,
2227
ret_true, ret_false)
2229
for entry in incorrect_scalars:
2231
if not preserve_errors:
2235
msg = 'Value %r was provided as a section' % entry
2236
out[entry] = validator.baseErrorClass(msg)
2237
for entry in incorrect_sections:
2239
if not preserve_errors:
2243
msg = 'Section %r was provided as a single value' % entry
2244
out[entry] = validator.baseErrorClass(msg)
2246
2290
# Missing sections will have been created as empty ones when the
2247
2291
# configspec was read.
2248
2292
for entry in section.sections:
2249
2293
# FIXME: this means DEFAULT is not copied in copy mode
2250
2294
if section is self and entry == 'DEFAULT':
2252
if section[entry].configspec is None:
2255
section.comments[entry] = configspec.comments.get(entry, [])
2256
section.inline_comments[entry] = configspec.inline_comments.get(entry, '')
2257
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])
2258
2302
out[entry] = check
2259
2303
if check == False:
2260
2304
ret_true = False
2298
2342
if entry == 'configspec':
2300
2344
current_options[entry] = getattr(self, entry)
2302
2346
configspec = self._original_configspec
2303
2347
current_options['configspec'] = configspec
2306
2350
self._initialise(current_options)
2307
2351
self._load(filename, configspec)
2311
2355
class SimpleVal(object):
2313
2357
A simple validator.
2314
2358
Can be used to check that all members expected are present.
2316
2360
To use it, provide a configspec with all your members in (the value given
2317
2361
will be ignored). Pass an instance of ``SimpleVal`` to the ``validate``
2318
2362
method of your ``ConfigObj``. ``validate`` will return ``True`` if all
2319
2363
members are present, or a dictionary with True/False meaning
2320
2364
present/missing. (Whole missing sections will be replaced with ``False``)
2323
2367
def __init__(self):
2324
2368
self.baseErrorClass = ConfigObjError
2326
2370
def check(self, check, member, missing=False):
2327
2371
"""A dummy check method, always returns the value unchanged."""
2336
2380
An example function that will turn a nested dictionary of results
2337
2381
(as returned by ``ConfigObj.validate``) into a flat list.
2339
2383
``cfg`` is the ConfigObj instance being checked, ``res`` is the results
2340
2384
dictionary returned by ``validate``.
2342
2386
(This is a recursive function, so you shouldn't use the ``levels`` or
2343
``results`` arguments - they are used by the function.)
2387
``results`` arguments - they are used by the function.
2345
2389
Returns a list of keys that failed. Each member of the list is a tuple :
2349
2392
([list of sections...], key, result)
2351
2394
If ``validate`` was called with ``preserve_errors=False`` (the default)
2352
2395
then ``result`` will always be ``False``.
2354
2397
*list of sections* is a flattened list of sections that the key was found
2357
If the section was missing (or a section was expected and a scalar provided
2358
- or vice-versa) then key will be ``None``.
2400
If the section was missing then key will be ``None``.
2360
2402
If the value (or section) was missing then ``result`` will be ``False``.
2362
2404
If ``validate`` was called with ``preserve_errors=True`` and a value
2363
2405
was present, but failed the check, then ``result`` will be the exception
2364
2406
object returned. You can use this as a string that describes the failure.
2366
2408
For example *The value "3" is of the wrong type*.
2368
2410
>>> import validate
2369
2411
>>> vtor = validate.Validator()
2370
2412
>>> my_ini = '''