Sections

ConfigObj objects are sub-classes of the Section class (which is itself a sub-class of the dict). Besides the dictionary methods that Section inherits, it also contributes some of its own. I’m not planning to use most of them so I’ll just look at the type-casting and merge methods here.

Type Casting

Section(parent, depth, main[, indict, name]) A dictionary-like object that represents a section in a config file.
Section.as_bool(key) Accepts a key as input.
Section.as_int(key) A convenience method which coerces the specified value to an integer.
Section.as_float(key) A convenience method which coerces the specified value to a float.
Section.as_list(key) A convenience method which fetches the specified value, guaranteeing that it is a list.

The type-casting methods for the Section behave pretty much like the ConfigParser get methods except with the addition of a list option.

text = """
[test]
ape = grape
turned = on
count = 10
weight = 32.3
tarts = apple, rhubarb
"""

Since ConfigObj will break the list up (‘tarts’) when the object is created I’ll set list_values to False in the constructor.

parser = SafeConfigParser()
parser.readfp(StringIO(text))

config = ConfigObj(text.splitlines(), list_values=False)

First ConfigParser.

print 'ape: ', parser.get('test', 'ape')
print 'turned: ', parser.getboolean('test', 'turned')
print 'count: ', parser.getint('test', 'count')
print 'weight: ', parser.getfloat('test', 'weight')
try:
    print 'tarts: ', parser.getlist('test', 'tarts')
except AttributeError as error:
    print error
ape:  grape
turned:  True
count:  10
weight:  32.3
tarts:  SafeConfigParser instance has no attribute 'getlist'

Now ConfigObj.

section = config['test']
print 'ape: ', section['ape']
print 'turned: ', section.as_bool('turned')
print 'count: ', section.as_int('count')
print 'weight: ', section.as_float('weight')
print 'tarts: ', section.as_list('tarts')
ape:  grape
turned:  True
count:  10
weight:  32.3
tarts:  ['apple, rhubarb']

The as_list method doesn’t work the way I thought it would, all it did was put the string into a list, it didn’t split the value into a comma-separated list. I’m not really sure why this is useful.

Merge

Section.merge(indict) A recursive update - useful for merging config files.

An interesting method is the merge method. It updates an existing Section with values from another, allowing you to create a default ConfigObj and replace only the values that the user set.

update_text = """
[test]
tarts = Sally, Jessie, Rhubarb
""".splitlines()

update_config = ConfigObj(update_text)
config.merge(update_config)

section = config['test']

for key, value in section.iteritems():
    print "{0}: {1}".format(key, value)
ape: grape
turned: on
count: 10
weight: 32.3
tarts: ['Sally', 'Jessie', 'Rhubarb']

Merging Sub-Sections

default = """
[ape]
cow = boy
 [[chimp]]
 boy = howdy
""".splitlines()
config = ConfigObj(default)

update = """
cow = man
boy = girl
""".splitlines()

update_config = ConfigObj(update)

config.merge(update_config)

for key, value in config.iteritems():
    print "{0}: {1}".format(key, value)
cow: man
boy: girl
ape: {'cow': 'boy', 'chimp': {'boy': 'howdy'}}

Well, that didn’t work. It looks like ConfigObj respects nesting when updating (which seems a good thing) so it added the key-value pairs to the root section.

# first get rid of the mistake
del(config['cow'])
del(config['boy'])

update = """
[[chimp]]
boy = girl
""".splitlines()

try:
    update_config = ConfigObj(update)
except NestingError as error:
    print error
Section too nested at line 2.

Oops. Even though we’re changing only the value in the ‘chimp’ section we have to create the tree-structure for ConfigObj (once again this seems a good thing).

update = """
[ape]
[[chimp]]
boy = girl
""".splitlines()

update_config = ConfigObj(update)

config.merge(update_config)

for key, value in config.iteritems():
    print "{0} {1}".format(key, value)
ape {'cow': 'boy', 'chimp': {'boy': 'girl'}}

There are other methods as well, but I can’t see a use for them right now. Even the type-casting seem superfluous, especiall if you’re using schema-validation, but I thought they’d be interesting to see.