489
def __newobj__(cls, *args):
491
return cls.__new__(cls, *args)
495
493
class Section(dict):
497
495
A dictionary-like object that represents a section in a config file.
499
497
It does string interpolation if the 'interpolation' attribute
500
498
of the 'main' object is set to True.
502
500
Interpolation is tried first from this object, then from the 'DEFAULT'
503
501
section of this object, next from the parent and its 'DEFAULT' section,
504
502
and so on until the main object is reached.
506
504
A Section will behave like an ordered dictionary - following the
507
505
order of the ``scalars`` and ``sections`` attributes.
508
506
You can use this to change the order of members.
510
508
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)
513
521
def __init__(self, parent, depth, main, indict=None, name=None):
515
523
* parent is the section above
590
593
def __setitem__(self, key, value, unrepr=False):
592
595
Correctly set a value.
594
597
Making dictionary values Section instances.
595
598
(We have to special case 'Section' instances - which are also dicts)
597
600
Keys must be strings.
598
601
Values need only be strings (or lists of strings) if
599
602
``main.stringify`` is set.
601
`unrepr`` must be set when setting a value to a dictionary, without
604
``unrepr`` must be set when setting a value to a dictionary, without
602
605
creating a new sub-section.
604
if not isinstance(key, StringTypes):
607
if not isinstance(key, basestring):
605
608
raise ValueError('The key "%s" is not a string.' % key)
607
610
# add the comment
608
if not self.comments.has_key(key):
611
if key not in self.comments:
609
612
self.comments[key] = []
610
613
self.inline_comments[key] = ''
611
614
# remove the entry from defaults
860
863
call_on_sections=False, **keywargs):
862
865
Walk every member and call a function on the keyword and value.
864
867
Return a dictionary of the return values
866
869
If the function raises an exception, raise the errror
867
870
unless ``raise_errors=False``, in which case set the return value to
870
873
Any unrecognised keyword arguments you pass to walk, will be pased on
871
874
to the function you pass in.
873
876
Note: if ``call_on_sections`` is ``True`` then - on encountering a
874
877
subsection, *first* the function is called for the *whole* subsection,
875
878
and then recurses into it's members. This means your function must be
876
879
able to handle strings, dictionaries and lists. This allows you
877
880
to change the key of subsections as well as for ordinary members. The
878
881
return value when called on the whole subsection has to be discarded.
880
883
See the encode and decode methods for examples, including functions.
885
.. admonition:: caution
884
887
You can use ``walk`` to transform the names of members of a section
885
888
but you mustn't add or delete members.
887
890
>>> config = '''[XXXXsection]
888
891
... XXXXkey = XXXXvalue'''.splitlines()
889
892
>>> cfg = ConfigObj(config)
891
{'XXXXsection': {'XXXXkey': 'XXXXvalue'}}
894
ConfigObj({'XXXXsection': {'XXXXkey': 'XXXXvalue'}})
892
895
>>> def transform(section, key):
893
896
... val = section[key]
894
897
... newkey = key.replace('XXXX', 'CLIENT1')
944
def decode(self, encoding):
946
Decode all strings and values to unicode, using the specified encoding.
948
Works with subsections and list values.
950
Uses the ``walk`` method.
952
Testing ``encode`` and ``decode``.
954
>>> m.decode('ascii')
955
>>> def testuni(val):
956
... for entry in val:
957
... if not isinstance(entry, unicode):
958
... print >> sys.stderr, type(entry)
959
... raise AssertionError, 'decode failed.'
960
... if isinstance(val[entry], dict):
961
... testuni(val[entry])
962
... elif not isinstance(val[entry], unicode):
963
... raise AssertionError, 'decode failed.'
965
>>> m.encode('ascii')
969
warn('use of ``decode`` is deprecated.', DeprecationWarning)
970
def decode(section, key, encoding=encoding, warn=True):
973
if isinstance(val, (list, tuple)):
976
newval.append(entry.decode(encoding))
977
elif isinstance(val, dict):
980
newval = val.decode(encoding)
981
newkey = key.decode(encoding)
982
section.rename(key, newkey)
983
section[newkey] = newval
984
# using ``call_on_sections`` allows us to modify section names
985
self.walk(decode, call_on_sections=True)
988
def encode(self, encoding):
990
Encode all strings and values from unicode,
991
using the specified encoding.
993
Works with subsections and list values.
994
Uses the ``walk`` method.
996
warn('use of ``encode`` is deprecated.', DeprecationWarning)
997
def encode(section, key, encoding=encoding):
1000
if isinstance(val, (list, tuple)):
1003
newval.append(entry.encode(encoding))
1004
elif isinstance(val, dict):
1007
newval = val.encode(encoding)
1008
newkey = key.encode(encoding)
1009
section.rename(key, newkey)
1010
section[newkey] = newval
1011
self.walk(encode, call_on_sections=True)
1014
def istrue(self, key):
1015
"""A deprecated version of ``as_bool``."""
1016
warn('use of ``istrue`` is deprecated. Use ``as_bool`` method '
1017
'instead.', DeprecationWarning)
1018
return self.as_bool(key)
1021
947
def as_bool(self, key):
1023
949
Accepts a key as input. The corresponding value must be a string or
1024
950
the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to
1025
951
retain compatibility with Python 2.2.
1027
If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns
953
If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns
1030
If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns
956
If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns
1033
959
``as_bool`` is not case sensitive.
1035
961
Any other input will raise a ``ValueError``.
1037
963
>>> a = ConfigObj()
1038
964
>>> a['a'] = 'fish'
1039
965
>>> a.as_bool('a')
1246
def __init__(self, infile=None, options=None, **kwargs):
1194
def __init__(self, infile=None, options=None, _inspec=False, **kwargs):
1248
1196
Parse a config file or create a config file object.
1250
1198
``ConfigObj(infile=None, options=None, **kwargs)``
1200
self._inspec = _inspec
1252
1201
# init the superclass
1253
1202
Section.__init__(self, self, 0, self)
1260
options = dict(options)
1204
infile = infile or []
1205
options = dict(options or {})
1262
1207
# keyword arguments take precedence over an options dictionary
1263
1208
options.update(kwargs)
1210
options['list_values'] = False
1265
1212
defaults = OPTION_DEFAULTS.copy()
1266
1213
# TODO: check the values too.
1267
1214
for entry in options:
1268
1215
if entry not in defaults:
1269
1216
raise TypeError('Unrecognised option "%s".' % entry)
1271
1218
# Add any explicit options to the defaults
1272
1219
defaults.update(options)
1273
1220
self._initialise(defaults)
1274
1221
configspec = defaults['configspec']
1275
1222
self._original_configspec = configspec
1276
1223
self._load(infile, configspec)
1279
1226
def _load(self, infile, configspec):
1280
if isinstance(infile, StringTypes):
1227
if isinstance(infile, basestring):
1281
1228
self.filename = infile
1282
1229
if os.path.isfile(infile):
1283
1230
h = open(infile, 'rb')
1299
1246
elif isinstance(infile, (list, tuple)):
1300
1247
infile = list(infile)
1302
1249
elif isinstance(infile, dict):
1303
1250
# initialise self
1304
1251
# the Section class handles creating subsections
1305
1252
if isinstance(infile, ConfigObj):
1306
1253
# get a copy of our ConfigObj
1307
1254
infile = infile.dict()
1309
1256
for entry in infile:
1310
1257
self[entry] = infile[entry]
1311
1258
del self._errors
1313
1260
if configspec is not None:
1314
1261
self._handle_configspec(configspec)
1316
1263
self.configspec = None
1319
elif getattr(infile, 'read', None) is not None:
1266
elif getattr(infile, 'read', MISSING) is not MISSING:
1320
1267
# This supports file like objects
1321
1268
infile = infile.read() or []
1322
1269
# needs splitting into lines - but needs doing *after* decoding
1323
1270
# in case it's not an 8 bit encoding
1325
1272
raise TypeError('infile must be a filename, file like object, or list of lines.')
1328
1275
# don't do it for the empty ConfigObj
1329
1276
infile = self._handle_bom(infile)
1386
1333
self.newlines = None
1387
1334
self.write_empty_values = options['write_empty_values']
1388
1335
self.unrepr = options['unrepr']
1390
1337
self.initial_comment = []
1391
1338
self.final_comment = []
1392
self.configspec = {}
1339
self.configspec = None
1342
self.list_values = False
1394
1344
# Clear section attributes as well
1395
1345
Section._initialise(self)
1398
1348
def __repr__(self):
1399
return ('ConfigObj({%s})' %
1400
', '.join([('%s: %s' % (repr(key), repr(self[key])))
1349
return ('ConfigObj({%s})' %
1350
', '.join([('%s: %s' % (repr(key), repr(self[key])))
1401
1351
for key in (self.scalars + self.sections)]))
1404
1354
def _handle_bom(self, infile):
1406
1356
Handle any BOM, and decode if necessary.
1408
1358
If an encoding is specified, that *must* be used - but the BOM should
1409
1359
still be removed (and the BOM attribute set).
1411
1361
(If the encoding is wrongly specified, then a BOM for an alternative
1412
1362
encoding won't be discovered or removed.)
1414
1364
If an encoding is not specified, UTF8 or UTF16 BOM will be detected and
1415
1365
removed. The BOM attribute will be set. UTF16 will be decoded to
1418
1368
NOTE: This method must not be called with an empty ``infile``.
1420
1370
Specifying the *wrong* encoding is likely to cause a
1421
1371
``UnicodeDecodeError``.
1423
1373
``infile`` must always be returned as a list of lines, but may be
1424
1374
passed in as a single string.
1765
1715
def _quote(self, value, multiline=True):
1767
1717
Return a safely quoted version of a value.
1769
1719
Raise a ConfigObjError if the value cannot be safely quoted.
1770
1720
If multiline is ``True`` (default) then use triple quotes
1773
Don't quote values that don't need it.
1774
Recursively quote members of a list and return a comma joined list.
1775
Multiline is ``False`` for lists.
1776
Obey list syntax for empty and single member lists.
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.
1778
1728
If ``list_values=False`` then the value is only quoted if it contains
1779
a ``\n`` (is multiline) or '#'.
1729
a ``\\n`` (is multiline) or '#'.
1781
1731
If ``write_empty_values`` is set, and the value is an empty string, it
1782
1732
won't be quoted.
1935
1890
def _handle_configspec(self, configspec):
1936
1891
"""Parse the configspec."""
1937
# FIXME: Should we check that the configspec was created with the
1892
# FIXME: Should we check that the configspec was created with the
1938
1893
# correct settings ? (i.e. ``list_values=False``)
1939
1894
if not isinstance(configspec, ConfigObj):
1941
1896
configspec = ConfigObj(configspec,
1942
1897
raise_errors=True,
1943
1898
file_error=True,
1945
1900
except ConfigObjError, e:
1946
1901
# FIXME: Should these errors have a reference
1947
1902
# to the already parsed ConfigObj ?
1948
1903
raise ConfigspecError('Parsing configspec failed: %s' % e)
1949
1904
except IOError, e:
1950
1905
raise IOError('Reading configspec failed: %s' % e)
1952
self._set_configspec_value(configspec, self)
1955
def _set_configspec_value(self, configspec, section):
1956
"""Used to recursively set configspec values."""
1957
if '__many__' in configspec.sections:
1958
section.configspec['__many__'] = configspec['__many__']
1959
if len(configspec.sections) > 1:
1960
# FIXME: can we supply any useful information here ?
1961
raise RepeatSectionError()
1963
if getattr(configspec, 'initial_comment', None) is not None:
1964
section._configspec_initial_comment = configspec.initial_comment
1965
section._configspec_final_comment = configspec.final_comment
1966
section._configspec_encoding = configspec.encoding
1967
section._configspec_BOM = configspec.BOM
1968
section._configspec_newlines = configspec.newlines
1969
section._configspec_indent_type = configspec.indent_type
1971
for entry in configspec.scalars:
1972
section._configspec_comments[entry] = configspec.comments[entry]
1973
section._configspec_inline_comments[entry] = configspec.inline_comments[entry]
1974
section.configspec[entry] = configspec[entry]
1975
section._order.append(entry)
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
1977
1923
for entry in configspec.sections:
1978
1924
if entry == '__many__':
1981
section._cs_section_comments[entry] = configspec.comments[entry]
1982
section._cs_section_inline_comments[entry] = configspec.inline_comments[entry]
1983
if not section.has_key(entry):
1985
self._set_configspec_value(configspec[entry], section[entry])
1988
def _handle_repeat(self, section, configspec):
1989
"""Dynamically assign configspec for repeated section."""
1991
section_keys = configspec.sections
1992
scalar_keys = configspec.scalars
1993
except AttributeError:
1994
section_keys = [entry for entry in configspec
1995
if isinstance(configspec[entry], dict)]
1996
scalar_keys = [entry for entry in configspec
1997
if not isinstance(configspec[entry], dict)]
1999
if '__many__' in section_keys and len(section_keys) > 1:
2000
# FIXME: can we supply any useful information here ?
2001
raise RepeatSectionError()
2005
for entry in scalar_keys:
2006
val = configspec[entry]
2007
scalars[entry] = val
2008
for entry in section_keys:
2009
val = configspec[entry]
2010
if entry == '__many__':
2011
scalars[entry] = val
2013
sections[entry] = val
2015
section.configspec = scalars
2016
for entry in sections:
2017
if not section.has_key(entry):
2019
self._handle_repeat(section[entry], sections[entry])
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]
2022
1938
def _write_line(self, indent_string, entry, this_entry, comment):
2164
2080
Test the ConfigObj against a configspec.
2166
2082
It uses the ``validator`` object from *validate.py*.
2168
2084
To run ``validate`` on the current ConfigObj, call: ::
2170
2086
test = config.validate(validator)
2172
2088
(Normally having previously passed in the configspec when the ConfigObj
2173
2089
was created - you can dynamically assign a dictionary of checks to the
2174
2090
``configspec`` attribute of a section though).
2176
2092
It returns ``True`` if everything passes, or a dictionary of
2177
2093
pass/fails (True/False). If every member of a subsection passes, it
2178
2094
will just have the value ``True``. (It also returns ``False`` if all
2181
2097
In addition, it converts the values from strings to their native
2182
2098
types if their checks pass (and ``stringify`` is set).
2184
2100
If ``preserve_errors`` is ``True`` (``False`` is default) then instead
2185
2101
of a marking a fail with a ``False``, it will preserve the actual
2186
2102
exception object. This can contain info about the reason for failure.
2187
2103
For example the ``VdtValueTooSmallError`` indicates that the value
2188
2104
supplied was too small. If a value (or section) is missing it will
2189
2105
still be marked as ``False``.
2191
2107
You must have the validate module to use ``preserve_errors=True``.
2193
2109
You can then use the ``flatten_errors`` function to turn your nested
2194
2110
results dictionary into a flattened list of failures - useful for
2195
2111
displaying meaningful error messages.
2202
2118
# Which makes importing configobj faster
2203
2119
from validate import VdtMissingValue
2204
2120
self._vdtMissingValue = VdtMissingValue
2207
spec_section = section.configspec
2208
if copy and getattr(section, '_configspec_initial_comment', None) is not None:
2209
section.initial_comment = section._configspec_initial_comment
2210
section.final_comment = section._configspec_final_comment
2211
section.encoding = section._configspec_encoding
2212
section.BOM = section._configspec_BOM
2213
section.newlines = section._configspec_newlines
2214
section.indent_type = section._configspec_indent_type
2216
if '__many__' in section.configspec:
2217
many = spec_section['__many__']
2218
# dynamically assign the configspecs
2219
# for the sections below
2220
for entry in section.sections:
2221
self._handle_repeat(section[entry], many)
2226
order = [k for k in section._order if k in spec_section]
2227
order += [k for k in spec_section if k not in order]
2229
if entry == '__many__':
2231
if (not entry in section.scalars) or (entry in section.defaults):
2233
# or entries from defaults
2236
if copy and not entry in section.scalars:
2238
section.comments[entry] = (
2239
section._configspec_comments.get(entry, []))
2240
section.inline_comments[entry] = (
2241
section._configspec_inline_comments.get(entry, ''))
2245
val = section[entry]
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):
2247
check = validator.check(spec_section[entry],
2138
check = validator.check(spec,
2249
2140
missing=missing
2291
2181
section[entry] = check
2292
2182
if not copy and missing and entry not in section.defaults:
2293
2183
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)
2294
2248
# Missing sections will have been created as empty ones when the
2295
2249
# configspec was read.
2296
2250
for entry in section.sections:
2297
2251
# FIXME: this means DEFAULT is not copied in copy mode
2298
2252
if section is self and entry == 'DEFAULT':
2254
if section[entry].configspec is None:
2301
section.comments[entry] = section._cs_section_comments[entry]
2302
section.inline_comments[entry] = (
2303
section._cs_section_inline_comments[entry])
2304
check = self.validate(validator, preserve_errors=preserve_errors,
2305
copy=copy, section=section[entry])
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])
2306
2260
out[entry] = check
2307
2261
if check == False:
2308
2262
ret_true = False
2346
2300
if entry == 'configspec':
2348
2302
current_options[entry] = getattr(self, entry)
2350
2304
configspec = self._original_configspec
2351
2305
current_options['configspec'] = configspec
2354
2308
self._initialise(current_options)
2355
2309
self._load(filename, configspec)
2359
2313
class SimpleVal(object):
2361
2315
A simple validator.
2362
2316
Can be used to check that all members expected are present.
2364
2318
To use it, provide a configspec with all your members in (the value given
2365
2319
will be ignored). Pass an instance of ``SimpleVal`` to the ``validate``
2366
2320
method of your ``ConfigObj``. ``validate`` will return ``True`` if all
2367
2321
members are present, or a dictionary with True/False meaning
2368
2322
present/missing. (Whole missing sections will be replaced with ``False``)
2371
2325
def __init__(self):
2372
2326
self.baseErrorClass = ConfigObjError
2374
2328
def check(self, check, member, missing=False):
2375
2329
"""A dummy check method, always returns the value unchanged."""
2384
2338
An example function that will turn a nested dictionary of results
2385
2339
(as returned by ``ConfigObj.validate``) into a flat list.
2387
2341
``cfg`` is the ConfigObj instance being checked, ``res`` is the results
2388
2342
dictionary returned by ``validate``.
2390
2344
(This is a recursive function, so you shouldn't use the ``levels`` or
2391
``results`` arguments - they are used by the function.
2345
``results`` arguments - they are used by the function.)
2393
2347
Returns a list of keys that failed. Each member of the list is a tuple :
2396
2351
([list of sections...], key, result)
2398
2353
If ``validate`` was called with ``preserve_errors=False`` (the default)
2399
2354
then ``result`` will always be ``False``.
2401
2356
*list of sections* is a flattened list of sections that the key was found
2404
If the section was missing then key will be ``None``.
2359
If the section was missing (or a section was expected and a scalar provided
2360
- or vice-versa) then key will be ``None``.
2406
2362
If the value (or section) was missing then ``result`` will be ``False``.
2408
2364
If ``validate`` was called with ``preserve_errors=True`` and a value
2409
2365
was present, but failed the check, then ``result`` will be the exception
2410
2366
object returned. You can use this as a string that describes the failure.
2412
2368
For example *The value "3" is of the wrong type*.
2414
2370
>>> import validate
2415
2371
>>> vtor = validate.Validator()
2416
2372
>>> my_ini = '''