16
16
# http://lists.sourceforge.net/lists/listinfo/configobj-develop
17
17
# Comments, suggestions and bug reports welcome.
19
20
from __future__ import generators
22
INTP_VER = sys.version_info[:2]
24
raise RuntimeError("Python v.2.2 or later needed")
33
from types import StringTypes
34
from warnings import warn
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
36
39
from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE
37
40
except ImportError:
489
def __newobj__(cls, *args):
491
return cls.__new__(cls, *args)
491
493
class Section(dict):
493
495
A dictionary-like object that represents a section in a config file.
495
497
It does string interpolation if the 'interpolation' attribute
496
498
of the 'main' object is set to True.
498
500
Interpolation is tried first from this object, then from the 'DEFAULT'
499
501
section of this object, next from the parent and its 'DEFAULT' section,
500
502
and so on until the main object is reached.
502
504
A Section will behave like an ordered dictionary - following the
503
505
order of the ``scalars`` and ``sections`` attributes.
504
506
You can use this to change the order of members.
506
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)
509
521
def __init__(self, parent, depth, main, indict=None, name=None):
511
523
* parent is the section above
586
593
def __setitem__(self, key, value, unrepr=False):
588
595
Correctly set a value.
590
597
Making dictionary values Section instances.
591
598
(We have to special case 'Section' instances - which are also dicts)
593
600
Keys must be strings.
594
601
Values need only be strings (or lists of strings) if
595
602
``main.stringify`` is set.
597
`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
598
605
creating a new sub-section.
600
if not isinstance(key, StringTypes):
607
if not isinstance(key, basestring):
601
608
raise ValueError('The key "%s" is not a string.' % key)
603
610
# add the comment
604
if not self.comments.has_key(key):
611
if key not in self.comments:
605
612
self.comments[key] = []
606
613
self.inline_comments[key] = ''
607
614
# remove the entry from defaults
856
863
call_on_sections=False, **keywargs):
858
865
Walk every member and call a function on the keyword and value.
860
867
Return a dictionary of the return values
862
869
If the function raises an exception, raise the errror
863
870
unless ``raise_errors=False``, in which case set the return value to
866
873
Any unrecognised keyword arguments you pass to walk, will be pased on
867
874
to the function you pass in.
869
876
Note: if ``call_on_sections`` is ``True`` then - on encountering a
870
877
subsection, *first* the function is called for the *whole* subsection,
871
878
and then recurses into it's members. This means your function must be
872
879
able to handle strings, dictionaries and lists. This allows you
873
880
to change the key of subsections as well as for ordinary members. The
874
881
return value when called on the whole subsection has to be discarded.
876
883
See the encode and decode methods for examples, including functions.
885
.. admonition:: caution
880
887
You can use ``walk`` to transform the names of members of a section
881
888
but you mustn't add or delete members.
883
890
>>> config = '''[XXXXsection]
884
891
... XXXXkey = XXXXvalue'''.splitlines()
885
892
>>> cfg = ConfigObj(config)
887
{'XXXXsection': {'XXXXkey': 'XXXXvalue'}}
894
ConfigObj({'XXXXsection': {'XXXXkey': 'XXXXvalue'}})
888
895
>>> def transform(section, key):
889
896
... val = section[key]
890
897
... 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)
1017
947
def as_bool(self, key):
1019
949
Accepts a key as input. The corresponding value must be a string or
1020
950
the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to
1021
951
retain compatibility with Python 2.2.
1023
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
1026
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
1029
959
``as_bool`` is not case sensitive.
1031
961
Any other input will raise a ``ValueError``.
1033
963
>>> a = ConfigObj()
1034
964
>>> a['a'] = 'fish'
1035
965
>>> a.as_bool('a')
1242
def __init__(self, infile=None, options=None, **kwargs):
1194
def __init__(self, infile=None, options=None, _inspec=False, **kwargs):
1244
1196
Parse a config file or create a config file object.
1246
1198
``ConfigObj(infile=None, options=None, **kwargs)``
1200
self._inspec = _inspec
1248
1201
# init the superclass
1249
1202
Section.__init__(self, self, 0, self)
1256
options = dict(options)
1204
infile = infile or []
1205
options = dict(options or {})
1258
1207
# keyword arguments take precedence over an options dictionary
1259
1208
options.update(kwargs)
1210
options['list_values'] = False
1261
1212
defaults = OPTION_DEFAULTS.copy()
1262
1213
# TODO: check the values too.
1263
1214
for entry in options:
1264
1215
if entry not in defaults:
1265
1216
raise TypeError('Unrecognised option "%s".' % entry)
1267
1218
# Add any explicit options to the defaults
1268
1219
defaults.update(options)
1269
1220
self._initialise(defaults)
1270
1221
configspec = defaults['configspec']
1271
1222
self._original_configspec = configspec
1272
1223
self._load(infile, configspec)
1275
1226
def _load(self, infile, configspec):
1276
if isinstance(infile, StringTypes):
1227
if isinstance(infile, basestring):
1277
1228
self.filename = infile
1278
1229
if os.path.isfile(infile):
1279
1230
h = open(infile, 'rb')
1295
1246
elif isinstance(infile, (list, tuple)):
1296
1247
infile = list(infile)
1298
1249
elif isinstance(infile, dict):
1299
1250
# initialise self
1300
1251
# the Section class handles creating subsections
1301
1252
if isinstance(infile, ConfigObj):
1302
1253
# get a copy of our ConfigObj
1303
1254
infile = infile.dict()
1305
1256
for entry in infile:
1306
1257
self[entry] = infile[entry]
1307
1258
del self._errors
1309
1260
if configspec is not None:
1310
1261
self._handle_configspec(configspec)
1312
1263
self.configspec = None
1315
elif getattr(infile, 'read', None) is not None:
1266
elif getattr(infile, 'read', MISSING) is not MISSING:
1316
1267
# This supports file like objects
1317
1268
infile = infile.read() or []
1318
1269
# needs splitting into lines - but needs doing *after* decoding
1319
1270
# in case it's not an 8 bit encoding
1321
1272
raise TypeError('infile must be a filename, file like object, or list of lines.')
1324
1275
# don't do it for the empty ConfigObj
1325
1276
infile = self._handle_bom(infile)
1382
1333
self.newlines = None
1383
1334
self.write_empty_values = options['write_empty_values']
1384
1335
self.unrepr = options['unrepr']
1386
1337
self.initial_comment = []
1387
1338
self.final_comment = []
1388
self.configspec = {}
1339
self.configspec = None
1342
self.list_values = False
1390
1344
# Clear section attributes as well
1391
1345
Section._initialise(self)
1394
1348
def __repr__(self):
1395
return ('ConfigObj({%s})' %
1396
', '.join([('%s: %s' % (repr(key), repr(self[key])))
1349
return ('ConfigObj({%s})' %
1350
', '.join([('%s: %s' % (repr(key), repr(self[key])))
1397
1351
for key in (self.scalars + self.sections)]))
1400
1354
def _handle_bom(self, infile):
1402
1356
Handle any BOM, and decode if necessary.
1404
1358
If an encoding is specified, that *must* be used - but the BOM should
1405
1359
still be removed (and the BOM attribute set).
1407
1361
(If the encoding is wrongly specified, then a BOM for an alternative
1408
1362
encoding won't be discovered or removed.)
1410
1364
If an encoding is not specified, UTF8 or UTF16 BOM will be detected and
1411
1365
removed. The BOM attribute will be set. UTF16 will be decoded to
1414
1368
NOTE: This method must not be called with an empty ``infile``.
1416
1370
Specifying the *wrong* encoding is likely to cause a
1417
1371
``UnicodeDecodeError``.
1419
1373
``infile`` must always be returned as a list of lines, but may be
1420
1374
passed in as a single string.
1761
1715
def _quote(self, value, multiline=True):
1763
1717
Return a safely quoted version of a value.
1765
1719
Raise a ConfigObjError if the value cannot be safely quoted.
1766
1720
If multiline is ``True`` (default) then use triple quotes
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.
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.
1774
1728
If ``list_values=False`` then the value is only quoted if it contains
1775
a ``\n`` (is multiline) or '#'.
1729
a ``\\n`` (is multiline) or '#'.
1777
1731
If ``write_empty_values`` is set, and the value is an empty string, it
1778
1732
won't be quoted.
1931
1888
def _handle_configspec(self, configspec):
1932
1889
"""Parse the configspec."""
1933
# FIXME: Should we check that the configspec was created with the
1890
# FIXME: Should we check that the configspec was created with the
1934
1891
# correct settings ? (i.e. ``list_values=False``)
1935
1892
if not isinstance(configspec, ConfigObj):
1937
1894
configspec = ConfigObj(configspec,
1938
1895
raise_errors=True,
1939
1896
file_error=True,
1941
1898
except ConfigObjError, e:
1942
1899
# FIXME: Should these errors have a reference
1943
1900
# to the already parsed ConfigObj ?
1944
1901
raise ConfigspecError('Parsing configspec failed: %s' % e)
1945
1902
except IOError, e:
1946
1903
raise IOError('Reading configspec failed: %s' % e)
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)
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
1973
1921
for entry in configspec.sections:
1974
1922
if entry == '__many__':
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])
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]
2018
1936
def _write_line(self, indent_string, entry, this_entry, comment):
2160
2078
Test the ConfigObj against a configspec.
2162
2080
It uses the ``validator`` object from *validate.py*.
2164
2082
To run ``validate`` on the current ConfigObj, call: ::
2166
2084
test = config.validate(validator)
2168
2086
(Normally having previously passed in the configspec when the ConfigObj
2169
2087
was created - you can dynamically assign a dictionary of checks to the
2170
2088
``configspec`` attribute of a section though).
2172
2090
It returns ``True`` if everything passes, or a dictionary of
2173
2091
pass/fails (True/False). If every member of a subsection passes, it
2174
2092
will just have the value ``True``. (It also returns ``False`` if all
2177
2095
In addition, it converts the values from strings to their native
2178
2096
types if their checks pass (and ``stringify`` is set).
2180
2098
If ``preserve_errors`` is ``True`` (``False`` is default) then instead
2181
2099
of a marking a fail with a ``False``, it will preserve the actual
2182
2100
exception object. This can contain info about the reason for failure.
2183
2101
For example the ``VdtValueTooSmallError`` indicates that the value
2184
2102
supplied was too small. If a value (or section) is missing it will
2185
2103
still be marked as ``False``.
2187
2105
You must have the validate module to use ``preserve_errors=True``.
2189
2107
You can then use the ``flatten_errors`` function to turn your nested
2190
2108
results dictionary into a flattened list of failures - useful for
2191
2109
displaying meaningful error messages.
2198
2116
# Which makes importing configobj faster
2199
2117
from validate import VdtMissingValue
2200
2118
self._vdtMissingValue = VdtMissingValue
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]
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):
2243
check = validator.check(spec_section[entry],
2136
check = validator.check(spec,
2245
2138
missing=missing
2287
2179
section[entry] = check
2288
2180
if not copy and missing and entry not in section.defaults:
2289
2181
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)
2290
2246
# Missing sections will have been created as empty ones when the
2291
2247
# configspec was read.
2292
2248
for entry in section.sections:
2293
2249
# FIXME: this means DEFAULT is not copied in copy mode
2294
2250
if section is self and entry == 'DEFAULT':
2252
if section[entry].configspec is None:
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])
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])
2302
2258
out[entry] = check
2303
2259
if check == False:
2304
2260
ret_true = False
2342
2298
if entry == 'configspec':
2344
2300
current_options[entry] = getattr(self, entry)
2346
2302
configspec = self._original_configspec
2347
2303
current_options['configspec'] = configspec
2350
2306
self._initialise(current_options)
2351
2307
self._load(filename, configspec)
2355
2311
class SimpleVal(object):
2357
2313
A simple validator.
2358
2314
Can be used to check that all members expected are present.
2360
2316
To use it, provide a configspec with all your members in (the value given
2361
2317
will be ignored). Pass an instance of ``SimpleVal`` to the ``validate``
2362
2318
method of your ``ConfigObj``. ``validate`` will return ``True`` if all
2363
2319
members are present, or a dictionary with True/False meaning
2364
2320
present/missing. (Whole missing sections will be replaced with ``False``)
2367
2323
def __init__(self):
2368
2324
self.baseErrorClass = ConfigObjError
2370
2326
def check(self, check, member, missing=False):
2371
2327
"""A dummy check method, always returns the value unchanged."""
2380
2336
An example function that will turn a nested dictionary of results
2381
2337
(as returned by ``ConfigObj.validate``) into a flat list.
2383
2339
``cfg`` is the ConfigObj instance being checked, ``res`` is the results
2384
2340
dictionary returned by ``validate``.
2386
2342
(This is a recursive function, so you shouldn't use the ``levels`` or
2387
``results`` arguments - they are used by the function.
2343
``results`` arguments - they are used by the function.)
2389
2345
Returns a list of keys that failed. Each member of the list is a tuple :
2392
2349
([list of sections...], key, result)
2394
2351
If ``validate`` was called with ``preserve_errors=False`` (the default)
2395
2352
then ``result`` will always be ``False``.
2397
2354
*list of sections* is a flattened list of sections that the key was found
2400
If the section was missing then key will be ``None``.
2357
If the section was missing (or a section was expected and a scalar provided
2358
- or vice-versa) then key will be ``None``.
2402
2360
If the value (or section) was missing then ``result`` will be ``False``.
2404
2362
If ``validate`` was called with ``preserve_errors=True`` and a value
2405
2363
was present, but failed the check, then ``result`` will be the exception
2406
2364
object returned. You can use this as a string that describes the failure.
2408
2366
For example *The value "3" is of the wrong type*.
2410
2368
>>> import validate
2411
2369
>>> vtor = validate.Validator()
2412
2370
>>> my_ini = '''