ConfigObj Documentation

Config Files Made Easy

Author: Michael Foord
Contact: fuzzyman AT voidspace DOT org DOT uk
Version: ConfigObj v3.3.0
Date: 2004/08/16
License:BSD License
Doc Revision:7, 2005/03/03
Home Page:ConfigObj Homepage
API Documentation:
 ConfigObj API Docs
Support and Bug Reports:
 Pythonutils Mailing List

Contents

1   An Introduction

ConfigObj allows you to read and write config files, from Python, with the greatest of ease. Usually this means single line commands. For this reason it is also handy for storing data in a human readable way [1]. ConfigObj has gone through several permutations. It can read config files with sections, like windows INI files, and makes it very easy for users to write config files for programs that use it.

In a nutshell, if you give it a filename it will read all the keyword/value pairs from it. You access or change the values by treating it like a dictionary. You can then call the write method to save any changes made. Keywords are case insensitive, but ConfigObj preserves the original case when writing out. It is ease of use that gives ConfigObj the advantage over ConfigParser, but; ConfigObj also has the following features :

  • Ease of use - dictionary like access
  • Sections are optional - flat config files if you want them
  • Multiple (list) values for keywords
  • Easy to create, modify, and write files
  • Human readable
  • Comments are preserved
  • Quoting is optional [where unambiguous]
  • Will understand several keyword/value dividers
  • Many options for parsing and writing
  • Powerful integrated Validation scheme
  • lines (including lists) can be split over more than one line
  • Support for unicode and input/output encoding
  • String interpolation - similar to ConfigParser
  • Optional attribute access for shorthand access to keywords/sections

Feedback on this module, including this document, is very much welcomed. Support for ConfigObj, along with bug reports, comments, etc, happens at the PythonUtils Mailing List. Bugs do pop up from time to time - but if you have problems I can usually sort them out within a few days.

ConfigObj needs python 2.2 or higher.

PythonUtils home page

This documentation is a guide on how to use ConfigObj in your programs. You may also be interested in the ConfigObj API Docs.

2   Downloading

Download Links
configobj.zip fullconfigobj.zip
configobj.py configobj.txt
fullconfigobj.py caseless.py
validate.py The Pythonutils Package

validate.py is maintained at the Validate Home. There may be additional documentation or resources relating to it. The Pythonutils Package is a python package that includes ConfigObj and all dependencies. It comes with a setup.py and is simpler if you use ConfigObj regularly.

3   Basic Usage

from configobj import ConfigObj
config = ConfigObj(infile=[], indict = {}, **keywargs)

from configobj import ConfigObj
config = ConfigObj(filename)

You create a basic configobj by giving it a filename. You can also pass in any options you want to set. The options can either be in the form of keyword arguments, or as a dictionary. A useful default dictionary is available to modify - but we'll look more at the options later.

ConfigObj then reads the file and parses the values from it. Values are always read in as strings - or lists of strings. The file can either be a straightforward config file with just keywords and values - in which case we call it a flatfile. Alternatively it can be divided into sections. Each section then has it's own set of keywords. See the paragraph on config files to see the difference.

You can then access the keywords in the same way as you access a dictionary :

value1 = config['keyword1']
value2 = config['keyword2']
.
.

You can even use the normal dictionary method to change the values, and then write it out using the write method :

config['keyword1'] = value1
config['keyword2'] = value2
.
.
config.write()

ConfigObj inherits from the built in type dictionary - so all the normal dictionary methods are available. Keywords in ConfigObj are case insensitive. This is done using a class called caseless. If you ever need a case insensitive dictionary or list, you can use these ! ConfigObj does preserve your original casing when it writes back out. [2]

This means that the following two lines are equivalent :

print config['FISH']
print config['fish']

If the config file has sections in it, then each section will be a dictionary of keywords and values.

print config['section1']

{'keyword1': 'value 1', 'keyword2': 'value 2', 'keyword3': 'value 3'}

You can create new sections in the following two ways :

config['section 2'] = None           # this is the same as config['section 2'] = {}
config['section 2'] = {'keyword1': 'value 1', 'keyword2': 'value 2', 
                       'keyword3': 'value 3'}

You access values in a section with :

value1 = config['section 1']['keyword 1']
value2 = config['section 1']['keyword 2']

You can also use ConfigObj to just read in some values from a file, and then just update those values in the file. This is done using a configspec when you read a file and the writein method to write it out again. But we'll see more about those later.

You can even create a completely empty configobj from scratch :

config = ConfigObj()
config.filename = filename
config['keyword1'] = value
config['keyword2'] = value
.
.
configobj.write()

It can then be read back in with :

config = ConfigObj(filename)

Easy hey !! This will be a flatfile by default. The same applies if you specify a filename which doesn't yet exist. To make it a configobj with sections you need to specify :

config = ConfigObj(flatfile=False)

The last thing I'll mention when covering the basics is list values in config files. Values are always strings - if you want integers, or anything else, you can do the conversion yourself ! They can however be comma separated lists of strings. The following three lines all represent the same list :

'keyword' = [value1, value2, value3]    
'keyword' = (value1, value2, value3)    
'keyword' = value1, value2, value3

These are read in, and turned into lists using the listquote module. If you pass in a list to a configobj then it will be written out as a list. This includes nested lists !! (lists of lists !! - unless you turn recursivelist off - see the options section). This means that the following line is perfectly valid :

config['keyword'] = [ value1, [value2, value3], value4 ]

The next few sections cover the options and more complex possibilities in greater detail. If you just want a list and brief description of all the options, methods and attributes associated with a configobj object then go to the summary section.

4   The infile

Before we look at config files themselves, which are easy enough, I'll mention the different types of object that ConfigObj can read a config file from. You create a new ConfigObj using config = ConfigObj(infile). infile can be a list of lines, a filename, a dictionary, or a StringIO instance. Because we support StringIO objects, it can actually use any object with the 'getvalue', 'seek', 'readlines', and 'writelines' methods. Beware that if you use cStringIO [3], you won't be able to use the 'write' or 'writein' methods. Whatever infile is (other than a dictionary), each line will be 'rstripped' to remove any trailing 'n'.

If infile is a filename, the file will be automatically read - and can be automatically written to. ConfigObj will attempt to work out for itself whether the file is a flatfile or a sectionfile. You can override this by passing in the 'flatfile' argument. If the file doesn't exist, ConfigObj will assume that you want a flatfile unless you tell it otherwise.

If infile is a list of lines (unicode strings or normal strings, possibly with encoding specified) then the write and writein methods will always return lists of lines. You can change this by setting config.filename

Passing in a dictionary is a convenient way of quickly creating a config file. In this case, ConfigObj will also attempt to work out whether the dictionary represents a flatfile or not. For it to be a flatfile, every member must be a string, tuple, or list. For it to be a sectionfile every member must be a dictionary - a section. If you mix types, or have members of other types, a TypeError will be raised and the object won't be created. If you pass in the wrong value for flatfile (or a configspec that tests for the opposite of the dictionary) then a ValueError will be raised. Currently the configspec isn't used when you create a ConfigObj from a dictionary - this is likely to change. Also input encodings aren't used when a dictionary is passed in. This could create problems when you try to output. For the moment, if you want an output encoding then make sure you have already converted keys and values to unicode.

5   Config Files

There are two types of config files that ConfigObj can read.

Basic files with just keyword = value pairs - we call these 'flatfiles'. Each keyword must be unique. The second type are slightly more complicated - we'll call these 'sectionfiles'.

These are config files with sections. Each section is separated with a section marker : [section 1]

Each section has it's own list of keyword = value pairs. Keywords that appear in one section can be repeated in another section. Any keywords that appear at the start - before any section marker - go in the 'empty section'.

Example 'flatfile' (normal config file) :

# this is a comment line 
; so is this 
# The initial comments in a file are preserved as config.inital_comment (a list of lines)

'keyword 1'   =   'value 1'          # this is a comment for keyword1
keyword2=value2
keyword3    :    value3                      ; this is a comment for keyword3
'keyword 4'      value 4         # quotes are optional if unambiguous
keyword5, value5                 # notice the different sorts of dividers 
"keyword '6'"     :     "value6"
"keyword 7" "value 7"
'keyword 8'         'A very long entry for value 8 \
so long that it goes over onto two lines'

# this comment is not on a keyword line - so gets ignored

'keyword 9'          '&mjf-quot;value 9&mjf-quot;&mjf-lf;'
'keyword 10'         [value1, 'value 2', "value3", [value1, (value1, value2)]]
'keyword 11'     =     (value1, value2, value3)
'keyword 12'     =     value1, value2, value3, \
                       value4, value5 

/* This marker starts a multi line comment. It must be the first thing on the line.
The last few comment lines are preserved as config.final_comment (a list of lines)
This is all still a comment, but it ends, here. */

It looks a bit of a mess, but I've tried to illustrate the variety of ways to separate keyword and value. It looks a lot neater if you stay consistent within a file ! Keywords can be quoted with either single quotes ' or double quotes ". The quoting is optional; but if the keyword name has spaces in it then it must be quoted.

You can also have comments on the same line as keywords and values; perhaps to explain what that keyword is for. Comments on the same line as a keyword are preserved. They can also be modified and will be written back out if the config file is saved. See the section on comments for more details.

In keyword 9, you can see the strange values '&mjf-quot;' and '&mjf-lf;'. These are what ConfigObj uses to escape double quotes and line feeds. If a value just uses " it can be quoted with ' (and vice-versa). If it uses both then it will be quoted with " and any double quotes inside the value will be translated into '&mjf-quot;'. Any line-feeds in a value will automatically be translated into '&mjf-lf;' when written out. These special escapes will automatically be translated back when read in. This means you can use them yourself when writing config files by hand.

Keywords 10-12 show lists of values. Individual members of the list can also be lists - ConfigObj preserves the list structure when it reads it back in. This can be useful for preserving data in a config file. A list can be just comma separated values or enclosed between '(..)' or '[..]'. Obviously nested lists must be between brackets.

ConfigObj will also allow multi-line comments using /* long comments */. This allows you to put an introduction or a description into your config files - or even embed other data structures ! These will only function properly if the first marker /* is the first thing on the line and the last one */ is the last thing on a line. This allows for a much simpler implementation !

Keyword 8 and 12 illustrate that you can split lines over two lines by ending the line with \. This just joins the two lines together. Because whitespace isn't significant in lists, you can indent the entries. For a single string value, the extra whitespace would get included. We don't support RFC822 style continuations like ConfigParser does. This is because it is incompatible with allowing nested sections, based on indentation. At some point ConfigObj will allow multiple levels of sections (subsections), where whitespace will be significant. The current method of splitting a long line will still work. The way to include a 'n' in a value is to use the escape '&mjf-lf;'.

Example 'sectionfile' :

'keyword1'    'value 1'
'keyword2'    'value 2'
'keyword3'    'value 3'

[section 1]                         # comments on section marker lines are discarded
'keyword1'    'value 1'             ; other comments will be preserved, as with flatfiles
'keyword2'    'value 2'
'keyword3'    'value 3'

; empty lines
# and ones with just comments on
; are ignored

['section 2']
'keyword1'    'value 1'
'keyword2'    'value 2'
'keyword3'    'value 3'

["section 3"]
'keyword1'    'value 1'
'keyword2'    'value 2'
'keyword3'    'value 3'

[ section 4   ]
keyword1    =    'value 1'

As you can see the keyword names can be repeated across the sections. Sections must be unique though, and only defined once in a file. The keywords that appear at the top of the file, before a section marker, are put in a special section called the 'empty section'. This is accessed by using '' as the key.

Parsing the above file would result in :

config = ConfigObj(linelist)
print config

{'': {'keyword3': 'value 3', 'keyword2': 'value 2', 'keyword1': 'value 1'}, 
'section 4': {'keyword1': 'value 1'}, 'section 1': {'keyword3': 'value 3', 
'keyword2': 'value 2', 'keyword1': 'value 1'}, 'section 2': {'keyword3': 'value 3',
'keyword2': 'value 2', 'keyword1': 'value 1'}, 'section 3': {'keyword3': 'value 3', 
'keyword2': 'value 2', 'keyword1': 'value 1'}}

so the empty section is :

print config['']

{'keyword3': 'value 3', 'keyword2': 'value 2', 'keyword1': 'value 1'}

section 1 is accessed with :

print config['section 1']

{'keyword3': 'value 3', 'keyword2': 'value 2', 'keyword1': 'value 1'}

Each section is a dictionary of keywords/values. So you access individual keywords in a section using :

print config['section 1']['keyword1']

value 1

You can also use ordinary dictionary methods on each section - like has_key, update, get and setdefault etc.... In actual fact each section is a caselessDict rather than a normal dictionary. This means that keywords in a section are case insensitive too - it also means that sections have a couple of extra methods associated with caselessDict that ordinary dictionaries don't. See the docs in the caseless module if you are curious.

Note that the last section, 'section 4', doesn't have quotes inside the section marker. The leading and trailing spaces in the name are removed. This means that [section 4] and [   section 4   ] are identical !!

You can create a new-section either by giving a configobj a dictionary of keyword/values or initialise a new, empty section by passing it None. Both the following work :

config['section 2'] = None
config['section 2'] = {'keyword1': 'value 1', 'keyword2': 'value 2',
                       'keyword3': 'value 3'}

6   Configspec

Configspecs are optional. They can be used for several purposes :

There are various attributes that affect their behaviour, including how your ConfigObj handles errors. These attributes can be set when the ConfigObj is created and/or changed afterwards. If you don't provide a configspec then it will be set to None - this means parse/write everything from the file.

When first reading a config file, a configspec is used to specify exactly which keywords/sections should be read from a file. Any missing ones will have a default value filled in. This avoids key errors if your user provides an incorrectly filled in config file and your program tries to access values that ought to be there. It also allows you to just read a subset of keywords from a larger config file. Alternatively they could be used to specify just a subset of values to write out or the order you want them to be written out in. Normally a dictionary is an unordered object. When writing out a ConfigObj there is no guarantee about what order the keyword-values will get written out in. A configspec allows you to present a consistent and readable config file for your user.

Validation is a bit more complicated. This allows you to use another object - an instance of the Validator class to check that all the entries make sense. This uses the validate module written by Michael Foord and Mark Andrews. The validate module is available from http://www.la-la.com, but is also distributed with ConfigObj. See the Validation section for the further details. Also see the Other Methods section for details of the 'parseconfigspec', 'stripconfigspec', and 'validate' methods which are relevant.

It does mean that a configspec can either be a list of keywords, or it can be a full configspec with validation information. We will refer to the simpler configspecs as 'simple configspecs' or 'stripped configspecs'. The more complicated ones we will call 'full configspecs' or 'configspecs with validation info'.

You pass in a configspec when you create a ConfigObj, by using the configspec option. config = ConfigObj(filename, configspec=configspec). The configspec you pass in can either be a filename, StringIO instance, or a list of lines. If you have specified an encoding, that will be used to decode the configspec.

6.1   Simple Configspecs

When reading a file, a simple configspec is just a list of which keywords to parse (one per line). If the configspec is for a 'sectionfile' then it contains section markers and keywords. The ConfigObj will only read keywords that are present in the configspec, and ignore additional values. When writing a file it specifies the order to write out the keywords. Inside a configspec, you can specify that the configobj is to parse/write everything from a particular section - by listing just the section marker and no keywords.

By default ConfigObj will work out for itself whether the file it is reading is a flatfile or has sections. It first checks the configspec, if there are any sections in it, it decides it's supposed to be parsing a 'sectionfile'. You can override the default behaviour and tell ConfigObj to expect a flatfile or sectionfile - but passing in a configspec that contradicts that setting is a guaranteed way to cause problems. Alternatively passing in a configspec that looks like a flatfile and giving it a sectionfile is another sure way to disaster !

The way this works is easy in practice. Before we look at settings that affect it's behaviour, I'll show you some examples. One configspec for a flatfile and one for a sectionfile configobj.

flatfile configspec :

keyword1
keyword2
keyword3
keyword4

sectionfile configspec :

keyword1
keyword2
keyword3
keyword4
[section1]
keyword1
keyword2
keyword3
keyword4
[section2]
keyword1
keyword2
keyword3
keyword4
[section3]
keyword1
keyword2
keyword3
keyword4

When a config file is read it will only read in values that are in the configspec. Any keywords that are in the configspec but are missing from the config file will be set to a default value. This is normally None rather than an empty string (''). This means you can tell which values were missing from the file by testing if they are None. (A blank value of '' may be a perfectly valid entry in a config file, but to have the keyword missing might not be !!). You can change this default value with the 'default' keyword when you create the configobj.

As I mentioned earlier you can also specify everything from a particular section by providing just the section marker. For example :

[section 1]
[section 2]
[section 3]

Means parse everything from 'section 1', 'section 2' and 'section 3'. This isn't quite the end of the story though....

You can see in the first sectionfile configspec that some of the keywords occurred before the first section marker. These obviously relate to keywords in the 'empty section'. There is a marker that means the 'empty section'. Unsurprisingly it's : [] or [ ] (whitespace in markers is removed). This is so that you can specify 'parse everything in the empty section'. To parse everything from the empty section and section 1-3 the config spec becomes :

[ ]
[section 1]
[section 2]
[section 3]

You can also explicitly specify keywords in the empty section using this marker :

[ ] 
keyword1
keyword2

Means keywords 1 and 2 from the empty section. In fact the empty section marker is optional in this case - any keywords before the first section marker are automatically in the empty section.

The empty section marker can only be used at the start of a configspec and must never be used inside a config file. Using it anywhere else in a configspec will raise an EmptyError - "Empty section defined in the wrong place." What effect this has on your program is determined by the settings you passed in to the exceptions keyword. The default is to print the error and carry on - see the exceptions section.

It's worth noting that there are a few errors that can be raised from a configspec - from badly built lines to duplicate keywords to badly built section markers. Whilst these aren't necessarily fatal, they're guaranteed to confuse your user who will think there is something wrong with his config file... when in fact it's your fault. configspecs are so simple that there is no need to make mistakes !!

Two attributes of ConfigObj are particularly relevant to configspecs :

configspec_only : Raise errors if there are extra/missing values from the configspec ?
write_full : Write out all values and sections (even if missing from the configspec) ?

configspec_only,     default : False
write_full,          default : True

You can either set these with keywords when you create the object or by setting the attribute directly. e.g. config.write_full = False

If you want your config file to contain all the keywords defined in your configspec, and nothing more, then set configspec_only to True. This causes a conspecerror to be raised if there are any extra/missing keywords or sections. It applies both when reading and when writing a configobj. How ConfigObj responds to this error is determined by your exceptions settings ! See the exceptions section. If it's not set then missing keywords will have the default set when reading (or not be output when writing) and extra ones will be ignored (when reading) or output (when writing - but also dependent on the write_full attribute).

Unlike the configspec_only keyword, the write_full keyword is only relevant when writing files out. The default is for the write and writein methods to write out all the values in the config object. This means that if you have added values and they aren't in the configspec, they will simply be added at the end (or the end of that section). If you only want to write out the ones in the configspec then set write_full to False.

If you pass in a configspec when you read a file, that configspec will be preserved in the object - as the attribute config.configspec. If you later use the write method without passing in a different configspec then the original will be used. At any time you can update the configspec by changing config.configspec - or even just setting it to None (which means write everything).

In order to help you create a configspec, a configobj has a method called makeconfigspec. You call it without arguments and it returns a full configspec for that configobj. Obviously the ordering of keywords/sections will be random (except the empty section always appears first).

configspec = config.makeconfigspec()

If you have a full configspec (with validation info) and you want to turn it into a simple configspec, you can use the stripconfigspec method. This also removes all comments etc.

stripped_spec = config.stripconfigspec(configspec)

7   Validation

As we've mentioned, specifying which keywords to read, and the order to write them, isn't the whole story with configspecs. They can also be used for validating your config files. It may be important to your program that the user supplies a valid IP address as one of the options, or that his shoe size is specified as a number. The Validation interface provides a way for you to automatically specify these checks. It uses a new Validator class created by Mark Andrews and myself for this purpose, although it has wider application than just ConfigObj.

This system allows you to create a config file that specifies a check for each keyword/value in your ConfigObj. This config file is your configspec. The check is specified as a function call with parameters, using basically the same syntax as Python. You register the functions you want to use with your Validator instance and then call the validate method of your ConfigObj. This walks the configspec and returns a list of keywords, or (section, keyword) tuples, that failed. If they all pass then it returns True. Validator can also use regular expressions (which you give a name to) and test for a match. validate.py comes with a battery of functions and regular expressions included and examples of how to use them.

7.1   Creating Your Validator Instance

from validate import Validator
val = Validator()

def test_range(value, min, max):
    value = float(value)
    min = float(min)
    max = float(max)
    return (min <= value <= max)

val.functions['range'] = test_range
print val.test('range(20, 50)', '30')3
    True

In the above example we define a function and set it in the 'functions' attribute of val. We give it the name 'range'. [5] Our actual test is the string 'range(20, 50)'. This means that any value tested will be tested by calling the range function with min set to '20' and max set to '50'. Because we are parsing from strings the values will always be passed in as strings. The actual value being tested is always passed as the first argument to the function. In this case '30' is between '20' and '50' so it returns True. Normally you won't directly call the test method, but call config.validate(val).

You can pass named keyword arguments using this system. There is a standard test called 'none' which always passes. There is also a standard test called 'multiple' that allows you to choose several tests - which are all parameters to the multiple function. This can be an 'and' test (where all the tests must pass) or an 'or' test, where a single pass will suffice.

See the examples, and the functions used, for more details. [6] The Validator class has many more methods and can be used in situations other than just with ConfigObj. Because the configspec is easily expressed as a config file it is convenient to use ConfigObj to parse it though.

7.2   A Full configspec

An example full configspec will look something like :

test1 = range(25, 75)
test2 = length(3)

[fish]
fish1 = upper
fish2 = upper()

[eggs and ham]
eggs = multiple('and', none, "frange(1.1, 2.3)", digit)
ham = option('bum', 'bim', 'bam')

[out]
oforder = string

This specifies validation info for several keywords, over several sections. For example the 'test1' keyword in the empty section must have a value between 25 and 75. The 'ham' keyword in the 'eggs and ham' section must be either 'bum', 'bim', or 'bam'. The 'fish1' keyword in the 'fish' section must be upper case. The 'eggs' keyword in the 'eggs and ham' section must pass three tests. One of these, 'none' is an automatic pass - so it's a pretty dumb test.

7.3   Doing the Validation

Using the configspec is done in the same way as with a stripped configspec. It can be used for all the same purposes. :

from validate import Validator
val = Validator()

config = ConfigObj(filename, configspec=filename2)
print config.validate(val)
    True

Having created a ConfigObj instance, you get it to validate itself by passing the 'validate' method your Validator instance. For flatfiles it returns either True (everything passed) or a list of keywords that failed. For sectionfiles it returns a list of tuples (section, keyword).

When you give ConfigObj a configspec it first checks to see if it contains validation information. If parsing it fails, then it assumes it doesn't ! [7] This means a badly built configspec will cause weird errors ! It parses the configspec as a ConfigObj instance, saved at config.__configspec__. It then strips the validation information and saves the stripped configspec at config.configspec. The functions to do this are available to you as methods of ConfigObj.

For example, if you are confident your configspec is valid, you can call config.__configspec__, config.configspec = config.parseconfigspec(configspec)

When you call the validate method, only sections/keywords with an entry in config.__configspec__ will be checked. Any entries in config.__configspec__ that don't exist (raise KeyError) will be marked as fail. If your functions raise exceptions the test will be marked as a fail (so check them carefully).

You can also manually parse and add your configspec for validation. If you do this you must use the lists=False option. (Because the function calls look like badly built lists unless they have quotes round them). Whether you do it manually or when the ConfigObj is created, you have all the usual ConfigObj methods available on your configspec :

config.__configspec__ = ConfigObj(filename, lists=False)
config.__configspec__['section 1']['value 1'] = 'frange(0, 1.0)'
config.__configspec__.write()

7.4   Validation Methods

The ConfigObj methods and attributes relevant to validation are : the parseconfigspec method, the stripconfigspec method, the validate method,and the __configspec__ attribute.

7.4.1   validate

We've basically covered this method. :

config.validate(val)

If there is no config.__configspec__ attribute it returns None. If every test passes it returns True. Otherwise it returns a list of failed tests. A list of keywords for a flatfile, and a list of (section, keyword) tuples for a section file. Missing keywords, or tests that raise exceptions, are counted as fails. If you parsed your config file with the configspec and their were missing keywords these will have been given the default value - usually None. Some tests expect a string, i.e. they call upper or some other string method. These will raise an AttributeError if passed None and therefore automatically (and probably rightly) fail. Your functions could automatically fail if passed None - or you could parse with 'configspec_only' on.

7.4.2   __configspec__

We've also covered this attribute. __configspec__ is your configspec turned into a ConfigObj. This is used by the validate method to do the validation.

7.4.3   parseconfigspec

This method takes a full configspec and parses it, then strips it. It calls 'ConfigObj' and then 'stripconfigspec'.

__configspec__, configspec = config.parseconfigspec(configspec, encoding=None)

If configspec is not a full configspec (or ConfigObj raises an exception whilst parsing) then __configspec__ will be None. 'configspec' is the stripped version of the configspec you pass it. By default it uses config.encoding (if set) to decode the configspec you supply. You can override this by passing in an encoding. Setting encoding=False forces no decoding to be done. The configspec you give it must be a list of lines, filename, or StringIO instance. Anything else will raise a TypeError.

7.4.4   stripconfigspec

This method takes a full configspec and removes comments and validation information. It returns a stripped configspec. :

strippedspec = config.stripconfigspec(configspec)

8   Options

When you create a configobj there are various options you can set, either as keywords or by passing in a dictionary of options.

Every configobj has the default values built in. You only need to specify any options that you are different from the defaults. In the configobj module there is also a copy of this dictionary. This is called pref_dict - it is probably more useful to copy and modify it than import it.

The options are (shown with the default setting) :

'configspec' : None
The keywords or sections/keywords to parse for - None means parse everything in the file. This also specifies the order to write out the file in.
'recursivelist' : True
Can list keywords have nested lists in them ?
'fileerror' : False
If set to True, raises IOError if the specified filename doesn't exist.
'createempty' : False
If set to True, creates an empty file if the specified filename doesn't exist (which also checks that the filename is a possible, valid path).
'newline' : False
If set to True - it writes a newline with every line, when force_return is on or infile was a list of lines.
'force_return' : False
If True the write and writein methods return lists of lines rather than writing to file.
'default' : None
The default value to set missing keywords to from the configspec - may be helpful to set to ''.
'flatfile' : None
Is the config file a 'flatfile' (True) or does it have sections ? (False) - None means it will work it out for itself. If the file doesn't exist and flatfile is set to None - it will create a flatfile (same as flatfile True)
'exceptions' : None
What to do with errors - see the section on exceptions.
'divider' : ' = '
The divider to use when writing out keyword - value pairs (whitespace is optional !).
'configspec_only' : False
Expect the configspec to contain all keywords ? (extra/missing ones will raise an error).
'write_full' : True
Write out all the keywords/sections in the configobj - add ones missing from the configspec ?
'stringify' : True
Convert all non-string values to strings before writing (otherwise non-string values will raise a TypeError).
'encoding' : None
The encoding to decode strings from and to when reading from files, the configspec, etc. This means that the sections and values will be unicode internally.
'backup_encoding' : 'latin1'
If we have an encoding set, and some values are strings (rather than unicode) what encoding should we assume they are in ?
'lists' : True
Do we allow interpret lists in values ? (if set to False they are left as strings - only when reading)

So to read a config file, or cause an IOError if the filename specified doesn't exist, use :

config = ConfigObj(filename, fileerror=True)

To change the default divider when writing files, you could use :

config = ConfigObj(filename, divider=' : ')

Or you can put the options in a dictionary and pass that in :

config = ConfigObj(filename, pref_dict)

If you pass in a dictionary and keywords, the keywords will take precedence over the options set in the dictionary.

Most of these options (except the ones that are only relevant to the initial reading of files) remain as attributes of the created configobj. For example you can set 'force_return'=True when you create the configobj. You can later amend this by setting config.force_return = False

'configspec'
This is a list of keywords and sections, potentially with validation information. See the configspec section. When reading a file, it is used as a list of keywords to read in. When writing it specifies the order to write them out. The default is for configspec to be set to None, which means parse/write everything. If 'flatfile' is set to None then ConfigObj will attempt to decide for itself if the config file is a flatfile or if it has sections. The first place it checks is the configspec - if the configspec has sections then ConfigObj will decide it's supposed to be parsing a 'sectionfile'. Once the config file has been read the configspec remains, and will be used by the write method to specify the order that the keywords are written out in. If the configspec contains validation info, it will be parsed to make config.__configspec__. You can set the configspec attribute directly if you want to.
'recursivelist'
This is set to True by default. As you know ConfigObj can handle values that are lists. Each member of the list can itself be a list - this is because the listquote module uses recursion to read the lists. It can also make for some potentially very complicated lists ! If you want to turn off this ability to read lists of lists then set 'recursivelist' to False. This means that only straight lists of vales can be read - a list member that is a list will throw an error.
'fileerror'
It is perfectly legal to create empty configobjs. if you intend to save the file later you can pass it a filename that doesn't yet exist. When you use the write or writein method the file will be created. However if you want to read a config file that the user should have created - maybe they pass in the path to the config file at the command line - it might matter a great deal if the file doesn't exist. If you set fileerror to True then passing in a non existent filename will immediately raise an IOError.
'createempty'
Because it is possible to pass in a non-existent filename, it is also possible to pass in an impossible (invalid) path. If you then modify the contents of the ConfigObj and try to save it... the contents will be lost. In this case it might be better to know that the file path is invalid earlier rather than later. If you set 'createempty' to True then it will attempt to create an empty configobj when you create it. If the file path is invalid then it will fail at that point - rather than later when you attempt to save the config.
'newline'
When you create a configobj you can either pass in the filename or a list of lines. If you pass in the config file as a list of lines then the write and writein method will return a modified list of lines. (Unless you set config.filename later). If you want each line terminated with a '\n' (newline) - so that it can be written straight back out using writelines - then set 'newline' to True.
'force_return'
If you want ConfigObj to return the config file as a list of lines, rather than use the filename attribute - set force_return to True. If force_return is on then newline is observed.
'default'
If you pass in a configspec when you create a configobj it is possible that some of the keywords in the configspec will be missing from the config file. By default these will be set to None - this is so that you can tell which vales were missing. If you intend to use the values without checking them, it may be more useful to you to have them set to some other default - e.g. ''. You set this using the default keyword.
'flatfile'

This keyword is particularly useful when creating empty configobjs'. It doesn't just apply to new ones though. This option specifies whether the config file is to be a flatfile or a sectionfile. If set to False it is a configobj with sections. If True it is a flatfile. If the filename you pass in doesn't exist then it defaults to True. If you leave it at the default value of None then ConfigObj will attempt to work out for itself whether a config file it reads is a flatfile or not. It first checks the configspec for section markers - if you haven't passed in a configspec then it checks the file itself. This value exists as an attribute of the configobj after creation - config.flatfile. However it is read only, changing it has no effect other than causing spectacular crashes the next time you use the configobj !! If you want to create a blank configobj that is a 'sectionfile', use :

``config = ConfigObj(flatfile=False)``
'exceptions'
For a detailed description see the exceptions section. The default is None which means print all errors but don't raise the exceptions. True means print the error and raise the exception, False means silently ignore all errors. You can pass in a general setting or a different setting for each type of error. If you want to add logging of error messages or even add user configurable 'verbosity' levels - you can use the StandOut module and normal print statements. See StandOut at : http://www.voidspace.org.uk/python/modules.shtml#standout
'divider'

When ConfigObj writes out a config file using the write or writein methods it writes lines using the keyword divider value format. By default divider is set to '  =  ', so lines it writes look like keyword  =  value. You can alter this divider to be anything you want - make sure it's a valid one though ! The valid dividers are :

' ', ',', ':', '\t', '='                ('\t' means TAB)  

Any extra whitespace is ignored and can be used for formatting purposes.

'configspec_only'
If this is set, then any additional keywords or sections in the config file will cause a 'conspecerror' to be raised when parsing. When writing, any additional keywords or sections in the configobj will also cause this error to be raised. How this error is handled depends on your settings in the exceptions option.
'write_full'
The default is to have this set to True. This only applies to writing a file out. When using the write method, configobj will follow the order of the configspec (if one is supplied). If keywords are missing from the configspec then the configobj will just add them at the end of that section. Any missing sections it will add at the end. If you are using the writein method then ConfigObj follows the order of the file it is writing into. Similarly, if write_full is set to True it will add missing keywords/sections at the end. If this is set to False then only sections/keywords in the configspec [8] will be written out.
'stringify'
The default is to have this set to True. This also only applies when writing a file out. If set, non-string values (like integers) are automatically converted to strings. If it's not set, then attempting to write out with a non-string value will raise a TypeError.
'encoding' : None
The encoding to decode strings from when reading from config files, the configspec, etc. This means that the sections and values will be unicode internally. The encoding is also used when writing files back out. If this is set to UTF8, then a BOM at the start of a file will be preserved when you use the write and writein methods. For example, if encoding='utf8' is passed in as an option - then the config file will be decoded from 'utf8' to unicode when it is read. If it is written back out it will be encoded back into utf8 (unless an alternative encoding is specified).
'backup_encoding' : 'latin1'
If we have an encoding set, and some values are strings (rather than unicode) what encoding should we assume they are in ? If this is set to None then the 'encoding' value will be used as the 'backup_encoding'. This value is actually used to decode all strings into unicode before they are then encoded again at the output. It is only used when writing, and the stored strings are not altered.
'lists' : True
Do we allow interpret lists in values ? (if set to False they are left as strings - only when reading). This option was actually added for the new Validation schema - to allow functions and arguments to be passed as strings. It may however be generally useful if you don't want ConfigObj to allow lists at all, but to treat all values as strings. It doesn't prevent you setting list values though.

9   Exceptions

I've mentioned exception handling several times now. Whilst parsing the config file, or even reading the configspec, there are several errors that can occur. ConfigObj defines a general base class of exceptions - the ConfigObjError. All the errors mentioned here are subclasses of this exception. The exceptions option can be used to define what ConfigObj does when it encounters the various possible errors. This enables you to make some errors fatal (raise an exception), some issue warnings (just print the error) or even ignore some errors altogether.

Before I describe the different errors - note that it is possible to make ConfigObj raise an error if the config file doesn't exist, using the fileerror option. It is also possible to cause an exception if we attempt to create an empty file with an invalid pathname, because the createempty option is set. In both these cases it is probably an IOError that will be raised - and in neither case will it be handled by this exception system.

You can either set a general error handling value, or set individual values for each of the different error types.

False means ignore errors.
None means print the error message
True means raise the exception.

If you choose to set individual error values, the default value is None and you only need to pass in values for errors you wish to change. Instead of setting the exceptions option to a single value - you give it a dictionary. Each keyword is the name of the error and the value is either False, None, True. Again, the configobj module has a default one defined that you can modify. It's called exceptionlist :

exceptionlist = {'duplicate' : None,            
                   # the same keyword being defined twice in the file, or a section
                 'badquote' : None,             
                 # a keyword or value with unbalanced quotes
                 'badline' : None,              
                 # a badly formatted line - couldn't work out a proper keyword or value
                 'badlist' : None,              
                 # Badly formed list
                 'badsection' : None,           
                 # badly formed section line - note, this is probably a serious error 
                 # if a section marker is invalid then keywords following will be put in the wrong section
                 'badconspec' : None,           
                 # Error in configspec - badly built line
                 'conspecerror' : None,         
                 # Error in configspec - missing or extra keywords (generated when parsing/writing a file)
                 'emptyerror' : None,           
                 # Empty section defined in wrong place in configspec, defined at all in config file
                 }

The following list, is the actual exceptions raised when these errors occur (if you have it set to raise exceptions !) and a brief explanation of the error :

'duplicate' : DuplicateKey
The same keyword is duplicated in a flatfile, or in the same section in a sectionfile. If you don't raise an exception then the first value will be used and the second discarded.
'badquote' : BadlyQuoted
A keyword or value is incorrectly quoted. The line will be ignored.

'badline': FormatError The line doesn't appear to be a keyword-value, section marker or comment line.

'badlist' : FormatError
A list value is badly formed. See the listquote module for the full details of this. It can include badly quoted elements or no closing ']'.
'badconspec' : badconspec
An error actually in the configspec. Duplicate keys or sections and badly quoted keywords for example.
'conspecerror' : conspecerror
Usually an error raised by the configspec_only option being set. It means there was a keyword in the config file that was missing or extra to the ones in the configspec. The message printed with the exception ought to give the full details.
'badsection' : BadSection
A badly formed section marker line. Can occur inside the configspec or inside the config file. If you allow it to happen inside your configspec you will really confuse your user. This is really a serious error, every keyword after this error is going to be in the wrong section !
'emptyerror' : EmptyError
The empty section has been defined in the wrong place. i.e. after another section marker in the configspec or used at all actually in a config file. As with badsection it's a pretty serious error as keywords below this will no longer be put in the section the user thought they would.

10   Writing Files

The two methods associated with a configobj object for writing out config files - are the write and writein methods. Both methods write out the comments associated with any keywords they write, but are slightly different in the way they work.

The write method just creates a new config file. If the config has a filename set - config.filename - then any existing file will be overwritten. The write method uses the configspec (or a new configspec explicitly given to it) as an orderlist.

The writein method will read an existing file, and will only modify lines that it needs to. This means you can use a configobj to parse and modify a few keywords from a larger config file. This could be useful if your application is divided into several programs, each of which only use part of the config file.

Both methods use several of the attributes to determine their behaviour. Ones common to both of them are :

config.filename
config.write_full
config.configspec_only
config.force_return
config.newline
config.stringify
config.encoding
config.backup_encoding

For the write method, if no config.filename is defined (i.e. it is set to None) it will return the config file as list of lines. Whether they are terminated with a newline or not depends on the newline attribute. If you pass it a configspec it will use that, otherwise it will use config.configspec. If this is set to None it means 'write everything'. If you pass write a configspec it will use it, but it won't remove any configspec that was already in place. If you want a new configspec to affect all further write operations then use :

config.configspec = newconfigspec
config.write()

rather than

config.write(newconfigspec)

Alternatively, if you want to write out a large configobj as several files, you can use several configspecs - where each of the configspecs only contains a few keywords..... Turn write_full off first :

 config.write_full = False
 config.filename = filename1
 config.write(configspec1)
 config.filename = filename2
 config.write(configspec2)
.
.

The write method adds the contents of config.initial_comment to the start of the file and config.final_comment to the end.

The writein method doesn't use configspec, but instead expects to be given an existing file to update the values (and comments) for. It goes through the file line by line and only changes lines where the line has a valid keyword and that keyword is in the configobj. If write_full is on, then it will write any missing keywords in at the end of the section and also add any missing sections at the end of the file. If configspec_only is set, then extra or missing keywords/sections will cause an error to be raised.

You can pass the infile in as a filename or a list of lines. By default it uses config.filename. If you pass in another filename it will modify that, without changing config.filename. (Neither the original file, nor the configobj attribute will be changed - config.filename will still be the same after the writein operation !!).

One use for this, is for a configobj to only represent a small subset of large config file - perhaps one program out of several that all share a config file. The program can have a configspec containing a few keywords that it needs to read :

config = ConfigObj(filename, configspec=['keyword1', 'keyword2', 'keyword3'])

This just parses a few values from the config file. If any of these values are modified, then they can be written back into the config file without affecting keywords that we didn't read. config.writein() does the job......

10.1   Writing and Unicode

For more details on this subject see the Character Encoding section. Both write and writein now take an optional 'encoding' keyword argument. By default they use the config.encoding attribute to do output encoding. (But only if the attribute is set). You can force no encoding to be done by setting encoding=False, or pass in an alternative encoding. In addition the writein method uses this value to decode the file it reads, the write method will use it to decode any configspec you pass it.

Both write and writein will recognise and preserve the UTF8 'BOM' [9].

11   Comments

ConfigObj will preserve any comments at the start and end of the config file. These will then be written back out when the write method is used. They are stored as lists of lines in the config.initial_comment and config.final_comment attributes.

Comments on the same line as a keyword are also preserved. It stores them in a dictionary of comments : config.__comments__

The __comments__ dictionary is also a caselessDict (case insensitive) and follows the structure of the configobj. When you parse a file, every keyword will have an entry in the __comments__ dictionary, even if it's blank. If the configobj is a sectionfile, then each section in __comments__ will also be a caselessDict - and each keyword will have an entry in that.

i.e. for config['keyword1'] the matching comment is stored at config.__comments__['keyword1'] for config['section1']['keyword1'] the matching comment is stored at config.__comments__['section1']['keyword1']

The comments that are preserved in this way are comments on the same line as the keyword :

'keyword1' = 'value1'         # this comment is preserved

The reason for this, is so that you can have a comment associated with each keyword explaining what it is for. When the write and writein methods are used, this comment will be preserved.

e.g. 'tablesize' = '32k'                   # the amount of memory to allocate per table. 32k is recommended

One thing to be careful of, it is easy to create additional entries in a configobj without creating corresponding entries in the __comments__ dictionary. The write and writein methods use a method called sortcomments, to ensure that every keyword at least has a blank entry. If you intend to do anything with the comments, it's worth either calling sortcomments or making careful use of the has_key method..... sortcomments also turns any occurrence of '\n' in the comments to '&mjf-lf;' - if they were written out as '\n' they would cause an invalid line in the config file.

The sortcomments method is called without arguments : config.sortcomments()

The write method adds the contents of config.initial_comment to the start of the file and config.final_comment to the end.

See the note in config Files about multi-line comments - /*...*/. Unless they are at the start or end of a file they aren't saved by ConfigObj. They are however preserved in a file if you use the writein method.

12   Character Encoding

ConfigObj has support for python character encodings, both when reading files and when saving. When encodings are enabled, keywords and values will be unicode internally. Character encoding is handled by passing in the 'encoding' keyword. It can subsequently be altered as the 'encoding' attribute of the ConfigObj. :

config = ConfigObj(filename, encoding='UTF8')
print config.encoding
    UTF8

If an encoding is specified then any config file or configspec will be turned into unicode objects internally using that encoding.

If the config file starts with the UTF8 BOM, then this will be preserved as the 'BOM' attribute of the ConfigObj and used if the write method is called. In future updates the other BOM will be supported. The UTF8 BOM is also recognised in configspecs and by the writein method.

When you use the write and writein methods it is possible to specify an alternative encoding for the output config file. If you don't specify one then the encoding attribute will be used instead (if any). If you specify False then no encoding is done.

When reading in with an encoding, the config file keywords and values are stored as unicode strings. It is possible that keywords or values that have been set may be normal byte strings instead of unicode strings. In order to encode these strings for outputting, ConfigObj must first turn them into unicode strings. The 'backup_encoding' option specifies which encoding is used to decode those strings. It does not directly alter them in the ConfigObj, but just decodes them for outputting. If this is set to None it reverts to using 'encoding'. If it is set to False then no conversion is done. The default is 'latin1'.

13   Attribute Access

The normal way to access values/sections stored in a ConfigObj is using the dictionary syntax. Through a little magic you can also access and set values as attributes. Keywords in sections can also be accessed as attributes of the sections. This means the following constructs are all valid and equivalent :

print config['keyword'] 
print config.keyword

config['keyword'] = value
config.keyword = value

print config['section']
print config.section

print config['section']['keyword']
print config['section'].keyword
print config.section['keyword']
print config.section.keyword

config['section']['keyword'] = value
config['section'].keyword = value
config.section['keyword'] = value
config.section.keyword = value

The attribute method of access doesn't work for names with spaces in them, names that contain characters that are invalid in attribute names, and also any existing attributes. As the ConfigObj already has attributes like 'default', 'errors', etc, the dictionary syntax is preferred and attribute access is for convenience only.

14   Interpolation

ConfigObj supports interpolation from the 'default' section into any other value. This can be turned off by setting the 'interpolation' option/attribute to False. Each ConfigObj also has an 'interpolate' method for manually performing interpolation on a value, even when interpolation is switched off. The syntax is similar to the interpolation done by the ConfigParser module. It only applies to config files with sections.

You can specify any keyword from the 'default' section of the ConfigObj to be inserted into a value. The syntax is '%(keyword)s'. If your ConfigObj doesn't have a defaults section, or that keyword isn't present, then no interpolation is done. If keyword' is in the 'default' section, then the value for that keyword will be used to replace '%(keyword)s' in your value. If the value it is replaced with also has an interpolation string, then that will be replaced too. This kind of 'nested interpolation' can be done up to a maximum of ten levels deep. This prevents infinite recursion ! Unlike ConfigParser we don't raise an error after reaching this depth, the value is just left.

If you want to create your own default section then you can simply assign to it. To add a set of defaults to any that might be in the config file already you can use the update method (which will over write any existing ones !). Below is an example of string interpolation. This also illustrates attribute access. It also shows what happens when an interpolated value also contains a value to be interpolated (a), a recursive value (c and d), and a value that isn't there (%(not present)s) :

config = ConfigObj(flatfile=False)
config.filename = 'config.ini'
defaults = {'a' : 'hello - %(b)s', 'b' : 'goodbye', 'datadir' : 'c:\\test', 'c' : '%(d)s', 'd' : '%(c)s' }
config['default'] = None        # create a new, blank, section
config['default'].update(defaults)

config['section'] = {'a' : '%(datadir)s\\some path\\file.py', 'b' : 'Yo %(a)s, %(datadir)s, %(not present)s, recursion %(c)s'}
print config.section.a
    c:\test\some path\file.py
    
print config.section.b
    Yo hello - goodbye, c:\test, %(not present)s, recursion %(c)s

config.interpolation = False
print config.section.a
    %(datadir)s\some path\file.py
print config.section.b
    Yo %(a)s, %(datadir)s, %(not present)s, recursion %(c)s

14.1   interpolate Function

Values fetched from the default section will have interpolation done, unless interpolation is switched off. You may need to switch interpolation off to work on the raw values. If you still want to do interpolation, but with it off by default, you can use the 'interpolate' function. This just receives a raw value and returns the string after any interpolation has been done. newvalue = config.interpolate(rawvalue)

config = ConfigObj(filename)
config.interpolation = False    # could have done ConfigObj(filename, interpolation=False)
rawvalue = config['section']['keyword']
value = config.interpolate(rawvalue)

15   Other Methods

We've already covered the methods write, writein, validate, parseconfigspec, stripconfigspec, makeconfigspec, interpolate and sortcomments. There are currently four other methods that are defined in ConfigObj. Additionally, any of the dictionary and caslessDict methods can be used on a configobj, it's sections and the __comments__ dictionary. If it isn't None the __configspec__ attribute will be a full ConfigObj.

isflatfile(self, infile)

Passed an infile - as a filename or a list of lines, it tests if a config file is a flatfile or if it has sections. Returns True for a flatfile or False if it appears to have sections. Also returns True if the file doesn't exist.

A section is defined as any line that has only whitespace at the start followed by [section name] and possibly whitespace and a comment afterwards. Section name can be in quotes if required (inside the square brackets). It currently doesn't check that the section names are correctly built - just if a line looks like a section name.

If you pass in None as the value to the 'flatfile' option, when you create a configobj, it will attempt to work out for itself if the config file is a flatfile or not. (If you give it a configspec it actually checks the configspec). This method is available if you want it. A more sensible approach is to parse the file and then check the config.flatfile attribute - but this method is available if you want to use it.

reset(self)
For all existing values - this sets comments and values to ''.
verify(self)

This acts like object.reset() - but only for missing values (where the keyword entry is None). If a different value was passed in for 'default' this method will have no effect. The following to examples have the same effect :

config = ConfigObj(infile, configspec=configspec, default='')

config = ConfigObj(infile, configspec=configspec)
config.verify()

Reset and verify are two similar methods. If you use a configspec to parse a config file then any missing keywords will be set to None. (So long as you don't change the 'default' option of course). This can be convenient to tell if there were any missing values - but inconvenient if you need to do anything with them. The verify method goes through every value and sets any that are at None to ''. You could use this method after checking the values for missing ones and deciding if any that are missing are fatal. The reset method does the same thing... for all keywords and comments. Both are called without arguments.

istrue

istrue is a shorthand way of having a 'boolean' type of value. You point it at a keyword, or a section and a keyword, and it tells you if the value there is True or not. The value must be a string. It is True if it is in the following list : ``['yes', 'on', '1', 'true']`. The test is case insensitive. If the value pointed to doesn't exist you will get a KeyError. If the value pointed to isn't a string (e.g. a list) you will get an AttributeError.

istrue = config.istrue(keyword, section=None)

15.1   Dictionary Methods

All dictionary methods are usable on a configobj, it's sections and the __comments__ dictionary. They are all fully documented in the python documentation and include :

has_key, get, setdefault, update, pop, keys, popitem, items, values, iteritems, iterkeys, itervalues

copy
This function returns a caselessDict instance, not a ConfigObj instance ! It might not return a shallow copy !
fromkeys
This also returns a caselessDict instance I think.
clear
This only clears keywords and sections. Leaves other attributes (and probably __comments__ as well !)
__contains__
more commonly used as if 'keyword' in configobj:
__iter__
more commonly used as for keyword in configobj:
__delitem__
more commonly used as del configobj['keyword']
__len__
more commonly used as len(configobj)

Plus any others that I've forgotten. Any methods that return or remove an item, will return or remove a whole section if you use them on a sectionfile configobj.

15.2   caseless Methods

The following extra methods are available because ConfigObj is a subclass of caselessDict :

findkey(self, item)
A caseless way of checking if a key exists or not. It returns None or the correct key. (e.g. if you search for 'KEY' and there is a keyword 'Key' - it returns 'Key', the keyword with the correct casing.
changekey(self, item)

For changing the casing of a key. If a key exists that is a caseless match for 'item', it will be changed to 'item'. This is useful when initially setting up default keys - but later might want to preserve an alternative casing. (e.g. if later read from a config file - and you might want to write back out with the user's casing preserved).

(e.g. config.changekey('ITEM') will change config['item'] to config['ITEM'] )

lowerkeys(self)
Returns a lowercase list of all member keywords.
dict(self)
Returns a dictionary version of self.

See the caseless module for more details.

16   Summary

This section contains a summary of all options, attributes and methods associated with a ConfigObj object.

config = ConfigObj(infile=[], indict = {}, **keywargs)

infile can either be a filename or a config file as a list of lines.

16.1   Options and Exceptions

options can be passed in as keyword arguments and/or as a dictionary of options. Any keyword arguments take precedence over options set in the dictionary.

There is a default dictionary, called pref_dict with all the options in it - defined in the configobj module. It can be got with :

from configobj import pref_dict

# A dictionary containing all the keywords for ConfigObj, and their default values.
# You can modify this and pass it in as a dictionary instead of using individual keywords -
# You only need include keywords which you are changing from their defaults.
# Additional individual keyword arguments take precedence over any dictionary passed in.
pref_dict = {   
            'configspec' : None,         # The keywords or sections/keywords to parse for
                                         # None means parse everything in the file. 
                                         # This also specifies the order to write out the file in.
            
            'recursivelist' : True,      # Can list keywords have nested lists in them ?
            
            'fileerror' : False,         # If set to True, raises IOError if the specified filename 
                                         # doesn't exist
            
            'createempty' : False,       # If set to True, creates an empty file 
                                         # if the specified filename doesn't exist
                                         # (which also checks that the filename is a possible, valid path)
            
            'newline' : False,           # If set to True - it writes a newline with every line, 
                                         # when force_return is on or infile was a list of lines.
            
            'force_return' : False,      # If True the write and writein methods return lists of lines 
                                         # rather than writing to file.
            
            'default' : None,            # The default value to set missing keywords to from the configspec 
                                         # may be helpful to set to ''
            
            'flatfile' : None,           # Is the config file a 'flatfile' (True) 
                                         # or does it have sections ? (False)  
                                         # None means it will work it out for itself. If the file doesn't exist 
                                         # and flatfile is set to None - it will create a flatfile 
                                         # (same as flatfile True)
            
            'exceptions' : None,         # What to do with errors - see the section on exceptions
                            
            'divider' : '    =    ',     # The divider to use when writing out keyword - value pairs 
                                         # (whitespace is optional !)
            
            'configspec_only' : False,   # Expect the configspec to contain all keywords ? 
                                         # (extra/missing ones will raise an error)
            
            'write_full' : True,         # Write out all the keywords/sections in the configobj 
                                         # add ones missing from the configspec ?
                                            
            'stringify'  : True,         # Convert all non-string values to strings before writing 
                                 # (otherwise non-string values will raise a TypeError)

    'encoding'  : None,          # input encoding and output encoding
    
    'backup_encoding' : 'latin1',   # used for string conversion (non unicode values) 
                                    # when doing conversions
    
    'lists' : True,              # do we allow interpret lists in values ? (if set to False they are 
                                 # left as strings - only when reading)
    'interpolation' : True,      # is interpolation of values switched on ?

            }

pref_dict contains all the default values. In fact though, you only need to pass in values that you change.

The 'exceptions' keyword allows you to specify the behaviour for all errors when parsing - or to set different behaviour for different types of error. The three different possible options on encountering an error are :

1)  ignore it,           False
2)  print the error,     None
3)  raise an exception,  True

the configobj module has a dictionary of all the errors. Set the value for an error to True or False to modify the behaviour of ConfigObj when it encounters that error :

from configobj import exceptionlist

# The 'exceptions' keyword' (relating to errors in parsing) :
# You can *either* pass in a single value for the 'exceptions' keyword - False, None or True (None is the default)
# False means ignore errors.
# None means print the error message
# True means raise the exception.
# *or* you can set a different value for each possible error, by modifying the following exceptionlist dictionary - and passing that in instead.
# None is the default for every error - you only need pass in a value for ones you wish to change.
# Even if an error is ignored - that line won't have been processed !
# Note - there are a few errors prior to parsing - like passing in a badly built configspec - that won't be trapped using this method.
# See the __init__ function for the list of exceptions that will be raised for each error, and the corresponding error message.
exceptionlist = {'duplicate' : None,            # the same keyword being defined twice in the file, or a section
                 'badquote' : None,             # a keyword or value with unbalanced quotes
                 'badline' : None,              # a badly formatted line - couldn't work out a proper keyword or value
                 'badlist' : None,              # Badly formed list
                 'badsection' : None,           # badly formed section line - note, this is probably a serious error - if a section marker is invalid then keywords following will be put in the wrong section
                 'badconspec' : None,           # Error in configspec - badly built line
                 'conspecerror' : None,         # Error in configspec - missing or extra keywords (generated when parsing/writing a file)
                 'emptyerror' : None,           # Empty section defined in wrong place in configspec, defined at all in config file
                 }

The following list is a list of the actual exceptions raised when these errors occur (if you have it set to raise exceptions !) The exceptions are created inside the configobj module :

'duplicate' : DuplicateKey, 
'badquote' : BadlyQuoted, 
'badline': FormatError,                    
'badlist' : FormatError, 
'badconspec' : badconspec,
'conspecerror' : conspecerror, 
'emptyerror' : EmptyError,
'badsection' : BadSection

They are all subclasses of : ConfigObjError

ConfigObj is a subclass of dictionaries and caselessDict. This means that any methods associated with dictionaries and caselessDict will work on a configobj. Don't forget that methods like pop, get etc on a sectionfile configobj will remove or return a whole section - not just a single value. In addition to this every section itself is a caselessDict - and you can use methods like has_key and update on these too.

16.2   Public Methods

write(self, configspec=None, encoding=None)

Takes the members of this ConfigObj and writes out as a config file.

If config.filename is set, it overwrites the existing file. The order can be set using a sequence (of keywords) passed in - the configspec acts as an orderlist. Comments are preserved in the created config file.

Any values in config that are of value None (weren't read in from the original file) will be output as ''

If config.newline is set to True, terminates lines with a 'n'.

If no config.filename is set or config.force_return is set, the config file is returned as a list of lines.

A configspec acts as an orderlist. It tells ConfigObj what order to write out values. If you don't explicitly pass one in, but one is set for the configobj (config.configspec) - that will be used. If a configspec is passed in to this method then the old one is still preserved. The configspec can be a list of lines, filename, or StringIO instance.

If write_full is off (default is on) then only values in the configspec will be written - to allow you to write out a subset of a configobj, otherwise extra values and sections not in the configspec are written out at the end. If 'configspec_only' is set, it means you expect the configobj to contain all the values in the configspec - and no extra. Extra values and missing values will then raise errors, depending on your error settings.

If encoding is set then that is used for both decoding the configspec that was passed in (if any) and encoding the output. If encoding is left as None then self.encoding is used. If encoding is False then the system default will be used. If you have an encoding specified and any of the stored keywords/values are strings, ConfigObj uses 'config.backup_encoding' to turn the strings into unicode before encoding for the output.

writein(self, infile=[], encoding=None)

Writes the values back into the file - only overwriting lines that it has keywords for.

Useful if you have only parsed a few keywords from a file and want to only update those values.

infile can be a list of lines, StringIO instance, or a filename. By default it will use self.filename, if there is one set. Even if a new filename is passed in, the old one is preserved.

If write_full is off (default is on) then only values in the infile will be written - no extra values will be added. By default extra values and sections (not in infile) are written out at the end.

Duplicate keywords or sections in the infile will raise errors according to the error settings.

If encoding is set then that is used for both decoding the infile (if any) and encoding the output. If encoding is left as None then self.encoding is used. If encoding is False then the system default will be used. If you have an encoding specified and any of the stored keywords/values are strings, ConfigObj uses self.backup_encoding to turn the strings into unicode before encoding for the output.

configspec_only is not checked with writein.

sortcomments(self)
Keys can get added and removed without valid comments being set. This method makes sure every section/keyword has at least a blank entry in the __comments__ dictionary. Sections have a caselessDict(). Each keyword in a section that doesn't have an entry is set to ''.
isflatfile(self, infile)

Passed an infile - as a filename or a list of lines, it tests if a config file is a flatfile or if it has sections. Returns True for a flatfile or False if it appears to have sections.

Returns True if the file doesn't exist.

A section is defined as any line that has only whitespace at the start followed by [section name] and possibly whitespace and a comment afterwards. It doesn't properly check that the section names are correctly built - just if a line looks like a section name.

It can check a StringIO instance. It can also check a dictionary - a dictionary must either have every entry as a dictionary (section file) or every entry a string or list (flatfile). If the dictionary has a mixture (or other types) a TypeError will be raised. If the dictionary is empty, this returns True.

reset(self)
For all existing values - this sets comments and values to ''.
verify(self)

This acts like object.reset() - but only for missing values (where the keyword entry is None).

If a different value was passed in for 'default' this will have no effect.

configobj = ConfigObj(infile, configspec=configspec, default='')

is equivalent to :

configobj = ConfigObj(infile, configspec=configspec)
configobj.verify()
makeconfigspec(self)

Return a copy of the configobj as a configspec. This will contain every section and every key - and can be used for reading and writing. Especially useful the first time you create a config file - can be used to test later config files for completeness (using configspec_only).

The ordering is random. configspec is returned as a list - you'll have to write it to file yourself.

configobj.newline is observed but the output of this function is not encoded.

It doesn't set the current configspec for the configobj. This can be done with :

configobj.configspec = configobj.makeconfigspec()
istrue(self, keyword, section=None)
istrue is a shorthand way of having a 'boolean' type of value. You point it at a keyword, or a section and a keyword, and it tells you if the value there is True or not. The value must be a string. It is True if it is in the following list : ``['yes', 'on', '1', 'true']`. The test is case insensitive. If the value pointed to doesn't exist you will get a KeyError. If the value pointed to isn't a string (e.g. a list) you will get an AttributeError.
parseconfigspec(self, configspec, encoding=None)

This takes a configspec and if necessary parses it as a config file and returns the stripped configspec. If the configspec is invalid, or just a straight list (with no validation information) it leaves it as it is.

returns (newconfig, stripped_config) where newconfig is a ConfigObj representing the configspec

If encoding is set then that is used for decoding the configspec. If encoding is left as None then self.encoding is used. If encoding is False then the system default will be used (i.e. no decoding takes place).

stripconfigspec(self, configspec)
Given a configspec with validation information it returns a stripped configspec.
validate(self, val)

Given a validator object, walk self.__configspec__ and validate.

If self.__configspec__ is None then we can't validate and returns None

If we validate successfully we return True - Otherwise we return a list of failed entries. For a sectionfile these will be (section, keyword) Tuples.

If the test raises an exception - this is a fail. Any missing keywords (that raise a KeyError) will also be marked as fail. Only members with entries in self.__configspec__ are tested.

See the documentation and examples in validate.py to see how to write your tests.

interpolate(self, value)

Interpolate a given value with entries from the 'defaults' section. This can be used even if interpolation is switched off. If there is no interpolation to be done, or the specified key is missing, the value is returned unchanged. There is a max interpolation depth of 10, after which the value is returned with no more interpolation done.

Code borrowed from ConfigParser

16.3   Attributes

A configobj has various attributes. Some of these relate to the internal state of the object - these are read only. The rest relate to the options passed in when the configobj is created. These can be changed and affect config files that are written out.

16.3.1   Normal Attributes

  • filename ---- The filename that we are reading/writing - or None (or the stored StringIO instance)
  • configspec ---- The configspec that defines how we write out the file - If you set this attribute directly it must be a stripped configspec
  • write_full ---- Write out all values and sections (even if missing from the configspec) ?
  • configspec_only ---- Raise errors if there are extra/missing values from the configspec?
  • newline ---- Add a 'n' to each line if we are outputting as a list (rather than writing to a file)
  • force_return ---- Force configobj to output as a list (rather than writing to a file)
  • stringify ---- Automatically convert non-string values to strings when we write ? (or raise a TypeError if not set)
  • initial_comment ---- Any comment lines at the start of the config file. A list. Written out by the write method.
  • final_comment ---- Any comment lines at the end of the config file. A list. Written out by the write method.
  • encoding ---- Encoding used to decode input files and encode output files
  • backup_encoding ---- Encoding used to decode strings before encoding for output
  • BOM ---- Stored BOM if there was one in an input config file, currently UTF8 only
  • interpolation ---- Switches interpolation from the 'default' section on or off

16.3.2   Read Only Attributes

  • flatfile ---- Is this a configobj for a flatfile or for a configobj with sections ?
  • sectionfile ---- The opposite of config.flatfile
  • recursivelist ---- Are nested lists allowed in values ? (Only relevant when parsing)
  • lists ---- Were strings allowed to contain lists ? (Only relevant when parsing)

17   Distributions

ConfigObj comes in a couple of different packages. In time that may expand to include a proper distutils distribution with self-installing windows package. It's more envisaged that you will want to bundle ConfigObj with your own programs - in which case just including the modules in your distribution is most straightforward.

It is currently available in three forms :

ConfigObj is dependent on the caseless and listquote modules. These modules stand in their own right and may be useful individually. It may however be simpler to only have one file to include in your distributions, in which case you can use fullconfigobj.py

Both configobj and fullconfigobj distributions include this file, as reST source (configobj.txt) and html (configobj.html). They should also have a test subdirectory. At the moment that contains 6 files - 3 test ini files and 3 test configspecs... configobj.zip should have a directory called htmldoc. This is an epydoc generated set of docs for ConfigObj. I haven't yet made the docstrings fully 'epydoc friendly', but it's still helpful. You can see them online at ConfigObj API Docs.

The pythonutils package contains everything that the config.zip distribution does, plus a couple of extra small modules. They are packaged together for convenience. It comes with a distutils setup.py and is available as a windows installer file. If you install the pythonutils package then ConfigObj will be placed in your site-packages folder and be on sys.path. If you want to distribute modules that use ConfigObj, without having to distribute ConfigObj itself, it is simplest to suggest that your users isntall the pythonutils package. See the pythonutils package.

17.1   Installing ConfigObj

In terms of 'installing' ConfigObj, the simplest thing is still to include configobj.py or fullconfigobj.py in the same directory as the script calling it. If you use ConfigObj regularly then it may be worthwhile putting it somewhere in your normal sys.path - e.g. the site-packages subdirectory of your python installation for Windows. Once I've done a setup.py this will be more straightforward of course..... If you use the smaller configobj.py then you will also need caseless.py and listquote.py within 'reach' of the calling script. If you install the pythonutils package, then ConfigObj will automatically be available to you.

ConfigObj will attempt to import and use the psyco module. If available this will speed everything up. To disable this, set the PSYCOON variable at the start of configobj.py to 0. Because fullconfigobj is built automagically from the three modules (using includer.py) it may have this chunk of code three times !! (This won't do any harm. includer can be useful for all sorts of things by the way).

18   Caseless and Listquote

This document doesn't attempt to be documentation for the caseless and listquote modules, but they are an integral part of the functioning of ConfigObj. Both modules contain pretty full documentation in the source code and are well worth a look if you think you can use them.

18.1   caseless

This provides two new classes and a sort function.

  • caselessDict - a dictionary with case insensitive keys.
  • caselessList - a list like object with all the list methods, various of which are case insensitive.
  • cSort - a function to sort lists in a caseless way.

caseless can be got from the Downloading section or at http://www.voidspace.org.uk/python/modules.html#caseless

18.2   listquote

Has functions for quoting and unquoting strings and also for turning a text representation of a list back into a list. (And also for simple reading and writing of CSV files)

listquote can be found at http://www.voidspace.org.uk/python/modules.shtml#listquote

19   TODO

These are in no particular order by the way. If you have any more suggestions, or ideas as to which should be priorities, then please let me know. Some of these have question marks at the end. This means the idea is a suggestion, but may not actually be desirable - or worth the effort.

See also the TODO/ISSUES sections in caseless.py and listquote.py. If any of these issues particularly matter to you then let me know..... (or if you have any other request/suggestions).

20   ISSUES

Also in no particular order.

21   CHANGELOG

2005/03/01        Version 3.3.0
Requires listquote 1.2.0 - which is improved/optimised
Requires caseless 2.2.0 which has support for unicode
Adding support for validation using the configspec
    To be done with  an external validator. (Validator class created with help of Mark Andrews)
    This means added methods/attributes :
        parseconfigspec method
        stripconfigspec method
        validate method
        __configspec__ attribute
        BOM attribute
Experimental unicode internally. 'encoding' and 'backup_encoding' keywords added
'lists' keyword added - can turn off list handling (lists are left as strings)
A ConfigObj can be created by passing in a dictionary
Added a __repr__ method for the ConfigObj
configspec can now be a filename (or StringIO instance...) - including for the write method
Now raises a TypeError rather than a KeyError if you pass in invalid options
writein can now return a config file as a list of lines if no filename is set
duplicate keys/sections in writein now raise 'duplicate' errors, rather than 'conspecerror'
String interpolation from the 'default' section - using '%(keyword)s' format - similar to ConfigParser
Attribute access as well as dictionary syntax 
Coerce sections created as dictionaries to caselessDict (bug fix)
Escaped '&mjf-lf;' and '&mjf-quot;' in unquoted values are converted (bug fix)
Bug fixed in configspec with section files (bug fix)
Bug fix in reporting of duplicate sections with configspec. (bug fix)
Fixed bugs in sectionfiles with 'configspec_only' (errors in the empty last section would be missed) (bug fix)
Bug fix in __buildconfigspec (bug fix)
Improved support for '/*... */' in the writein method (bug fix)
Fixed typo in verify and reset methods (bug fix)
configspec is no longer destroyed for flatfiles (bug fix)
Missing keys and Extra keys errors the wrong way round in write method (bug fix)
Plus other minor bugfixes, simplifications and optimisations

2005/02/15        Version 3.2.5
Changes so that ConfigObj can work with StringIO instances, by Wayne Wiitanen
    (for a project that receives a configuration file over a socket as a string.
    It is used as the source text for a StringIO object)
Lines can be extended across more than one line, with the '\' character
    (must be final character on line - it escapes the newline)
Empty values can be written 'value=' (like the ini file - but read only currently)
Errors whilst parsing now report the line they occurred in
Duplicate keys and sections are now reported as errors (bug fix)
isflatfile can now handle '[' inside '\*.. *\' comments (bug fix)
Fixed bug in handling of final line of '\*.. *\' comments
If the first and last non empty lines of a config file are comments they will be preserved as config.initial_comment and self.final_comment
   These are written out when the write method is called (but not the writein method)
   New list attributes self.initial_comment and self.final_comment
self.sectionfile is always set to the opposite of self.flatfile
    
2005/01/07        Version 3.2.4
Use absolute paths for stored filename. Avoids problems when cwd is changed.

2004/12/03        Version 3.2.3
Fixed bug in creating sectionfiles from scratch. (__comments__ KeyError).
Tuple entries are written out as lists rather than being converted to strings.
When an exception is raised, it's no longer printed first.
Added the istrue method.
Changed the license to BSD-License.

09-09-04        Version 3.2.2
Defined basestring for versions of Python prior to 2.3. (Thanks to Imre Andras Robert for reporting this).

30-08-04        Version 3.2.1
Fixed a bug causing the dictionary of options to be lost... oops

16-08-04        Version 3.2.0
Removed the charmap 'function' that eliminated unicode errors.    Unicode problems will now raise an exception rather than just stamping out unicode characters from latin1.
If this causes you problems let me know (with examples if possible) and I'll work on the unicode issues.
The test for list type entries is not an 'isinstance' test but a 'hasattr' test (append is the attribute tested for).    This isn't ubiquitous though.
Added the 'stringify' keyword - including changes to the listquote module for this (which is also now a bit faster).
fullconfigobj.py is now built using includer.py
Uses a newer version of caseless.
Spelling in docs corrected….

20-06-04        Version 3.1.0
Now uses the listquote module instead of listparse. (Which now does all the linehandling - not just lists).
This allows lists without the '[..]' and also allows lists using '(..)' - by default lists are now written out without the enclosing '[..]'
Fixed bug in __repr__ - oops !

30-05-04        Version 3.0.2
Added support for 'C-style' comments - whole sections commented out using '/*' and '*/' - see DOCS.
This allows embedding other data in a config file.

27-05-04        Version 3.0.1
Slight change to the parameters you pass in when you create a new configobj. Now uses infile=None, indict=None and creates the [] and {} inside __init__ - will make no difference to anyone !
__setitem__ calls caselessDict.__setitem__ and so is simpler and less dependent on the details of the caselessDict implementation 
Also added the clear method in caseless and __repr__ here. Does a new version of a dependent module warrant a new version number here ?

24-05-04        Version 3.0.0
Several incompatible changes - another major overhaul and change.    Lot's of improvements though.
Added support for standard config files with sections. 
    This has an entirely new interface - each section is a dictionary of values.
Changed the update method to be called writein - update clashes with a dict method.
Made various attributes keyword arguments, added several.
configspecs and orderlists have changed a great deal.
Removed support for adding dictionaries - use update instead.
Now subclasses a new class called caselessDict. 
    This should add various dictionary methods that could have caused errors before.
It also preserves the original casing of keywords when writing them back out.
Comments are also saved using a caselessDict.
Using a non-string key will now raise a TypeError rather than converting the key.
Added an exceptions keyword for *much* better handling of errors.
Made creatempty=False the default.
Now checks indict *and* any keyword args. Keyword args take precedence over indict.
' ', ':', '=', ',' and '\t' are now all valid dividers where the keyword is unquoted.
ConfigObj now does no type checking against configspec when you set items.
delete and add methods removed (they were unnecessary).
Docs rewritten - to include all this gumph and more..... Actually ConfigObj is *really* easy to use.
Support for stout was removed - use the new version of StandOut instead - gives a greater degree of control - or the new exception handling stuff.
A few new methods added.
Charmap is now incorporated into ConfigObj


30-04-04        Version 2.1.2
No longer crashes with non-string keys. Turns all keys into strings first.

29-04-04        Version 2.1.1
Changed to use the slightly updated version of listparse.
I've switched 'escaping' of elements off. This avoids some confusion and allows you to use the '\' character in config files.
'\n' in cofigobj values are now escaped as '&mjf-lf;' when written out.

07-04-04        Version 2.1.0
Made stout and recursivelist into keyword arguments.
Added a couple of extra keyword arguments to do with specifying filenames that don't exist.

15-03-04       Version 2.0.0 beta
Re-written it to subclass dict. My first forays into inheritance and operator overloading.
The config object now behaves like a dictionary.
I've completely broken the interface - but I don't think anyone was really using it anyway.
This new version is much more 'classy' ;-)
It will also read straight from/to a filename and completely parse a config file without you *having* to supply a config spec.
Uses listparse - so can handle nested list items as values.
No longer has getval and setval methods - use normal dictionary methods, or add and delete.


13-03-04       Version 1.0.7
Made the default value for infile an empty list - I seem to using ConfigObj to create new configobj (empty ones) more often.
Added a new parameter to the write and update methods (optional) - newline - to decide if you want to terminate every line in your returned config file with a newline.
This resets the behaviour changed in 1.0.6 - bad I know - but I realised I had different defaults for the write and update methods....
Fixed an obscure bug causing empty lists to be wrongly written out sometimes. In the process vastly simplified the write and update methods - making debugging and changing much simpler.

29-02-04       Version 1.0.6
Added a default standard output object - to save you passing one in when you don't really need one.
The write method now terminates lines with a '\n'

29-01-04       Version 1.0.5 
Version 1.0.5 has a couple of bugfixes as well as a couple of useful additions over previous versions.
Since 1.0.0 the buildconfig function has been moved into this distribution -
and the methods reset, verify, getval and setval have been added.
A couple of bugs have been fixed.

ConfigObj originated in a set of functions for reading config files in the atlantibots_ project.
(http://www.voidspace.org.uk/atlantibots) These were written by Rob McNeur... 
I'm not sure if any trace of them remains in the current code - but that's where it all started.

22   License

ConfigObj, and related files, are licensed under the BSD license. This is a very unrestrictive license - but it comes with the usual disclaimer. This is free software - test it, break it, just don't blame me if it eats your data ! (If it does though, let me know and I'll (try to) fix that it so it doesn't happen to anyone else :-)

Copyright (c) 2004 & 2005, Michael Foord
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:


    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * Neither the name of Michael Foord nor the name of Voidspace 
      may be used to endorse or promote products derived from this
      software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

You should also be able to find a copy of this license at : BSD License

If you use this program, please help Sponsor Voidspace, to help defray the costs of hosting Voidspace. Even $1 or $2 is helpful !

[1]This is sometimes known as 'data persistence'.
[2]It doesn't yet preserve other aspects of your formatting - like indentation and what divider you used. Doing this is a target for a ConfigObj upgrade. Possibly version 4 when nested sections will be implemented.
[3]In an actual fact if you pass in an empty cStringIO instance you probably will be able to write to it. Another limitation is that cStringIO objects can't work with unicode strings that can't be represented as ASCII. See the cStringIO docs for full details, of course.
[4]See the default option in the options section.
[5]A normal Validator instance has it's own 'range' and 'frange' tests that are a bit more sophisticated than this - but this is just an example.
[6]If you have fullconfigobj.py, which has the examples stripped out, you will probably want to get validate.py to have a look at these.
[7]So giving ConfigObj an invalid configspec is a very bad idea.
[8]Or in the original file when using the writein method.
[9]BOM = Byte Order Mark

Certified Open Source