diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml new file mode 100644 index 0000000..2caa6ff --- /dev/null +++ b/.github/workflows/python-test.yml @@ -0,0 +1,56 @@ +name: Python package + +on: [push] + +jobs: + build-on-latest: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest coverage pytest-cov six mock + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install -e . + - name: Test with pytest + run: | + python src/tests/configobj_doctests.py + python -m configobj.validate + py.test -c setup.cfg --color=yes --cov=configobj --cov-report=term --cov-report=html --cov-report=xml + + + build-on-legacy: + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + python-version: [ "2.7", "3.5", "3.6" ] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest coverage pytest-cov six mock + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install -e . + - name: Test with pytest + run: | + python src/tests/configobj_doctests.py + python -m configobj.validate + py.test -c setup.cfg --color=yes --cov=configobj --cov-report=term --cov-report=html --cov-report=xml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fd6828c..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: python -python: 2.7 -env: - - TOX_ENV=py34 - - TOX_ENV=py33 - - TOX_ENV=py32 - - TOX_ENV=py27 - - TOX_ENV=py26 -install: - - pip install tox - - pip install python-coveralls -script: - - tox -e $TOX_ENV -after_success: - coveralls diff --git a/CHANGES.rst b/CHANGES.rst new file mode 100644 index 0000000..86e4fb1 --- /dev/null +++ b/CHANGES.rst @@ -0,0 +1,28 @@ +Changelog +--------- + +Release 5.0.7 +""""""""""""" + +* update testing to validate against python version 2.7 and 3.5-3.11 +* update broken links / non-existent services and references + +Older Releases +"""""""""""""" + +* Release 5.0.6 improves error messages in certain edge cases +* Release 5.0.5 corrects a unicode-bug that still existed in writing files +* Release 5.0.4 corrects a unicode-bug that still existed in reading files after + fixing lists of string in 5.0.3 +* Release 5.0.3 corrects errors related to the incorrectly handling unicode + encoding and writing out files +* Release 5.0.2 adds a specific error message when trying to install on + Python versions older than 2.5 +* Release 5.0.1 fixes a regression with unicode conversion not happening + in certain cases PY2 +* Release 5.0.0 updates the supported Python versions to 2.6, 2.7, 3.2, 3.3 + and is otherwise unchanged +* Release 4.7.2 fixes several bugs in 4.7.1 +* Release 4.7.1 fixes a bug with the deprecated options keyword in 4.7.0. +* Release 4.7.0 improves performance adds features for validation and + fixes some bugs. \ No newline at end of file diff --git a/LICENSE b/LICENSE index a989b12..dddf422 100644 --- a/LICENSE +++ b/LICENSE @@ -1,9 +1,10 @@ Copyright (c): -2003-2010, Michael Foord -2014, Eli Courtwright, Rob Dennis +2003-2010, Michael Foord, Nicola Larosa +2014-2023, Eli Courtwright, Rob Dennis All rights reserved. E-mails : -fuzzyman AT voidspace DOT org DOT uk +michael AT python DOT org +nico AT tekNico DOT net eli AT courtwright DOT org rdennis AT gmail DOT com @@ -12,7 +13,7 @@ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - +2014 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. diff --git a/README.md b/README.md index 186a309..e55cf52 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,40 @@ -configobj [![Build Status](https://travis-ci.org/DiffSK/configobj.svg?branch=master)](https://travis-ci.org/DiffSK/configobj)[![Downloads](https://pypip.in/d/configobj/badge.png)](https://crate.io/packages/configobj)[![PyPI version](https://badge.fury.io/py/configobj.png)](http://badge.fury.io/py/configobj)[![Coverage Status](https://coveralls.io/repos/DiffSK/configobj/badge.png?branch=master)](https://coveralls.io/r/DiffSK/configobj?branch=master) -========= +# configobj +[![Coverage Status](https://img.shields.io/coveralls/DiffSK/configobj.svg)](https://coveralls.io/r/DiffSK/configobj?branch=master) +[![PyPI version](http://img.shields.io/pypi/v/configobj.svg)](https://pypi.python.org/pypi/configobj) +[![License](https://img.shields.io/badge/license-BSD_3--clause-red.svg)](https://github.com/DiffSK/configobj/blob/master/LICENSE) + Python 3+ compatible port of the [configobj](https://pypi.python.org/pypi/configobj/) library. -Documentation -========= -Found at [readthedocs](http://configobj.readthedocs.org/) +The Github CI/CD Pipeline runs tests on python versions: +- 2.7 +- 3.5 +- 3.6 +- 3.7 +- 3.8 +- 3.9 +- 3.10 +- 3.11 -Status -========= -This project is now maintained by [Eli Courtwright](https://github.com/EliAndrewC) and [Rob Dennis](https://github.com/robdennis) with the blessing of original creator [Michael Foord](http://www.voidspace.org.uk/). -For long time ConfigObj users, the biggest change is in the officially supported python versions: -- 2.6 -- 2.7 -- 3.2 -- 3.3 +## Documentation + +You can find a full manual on how to use ConfigObj at [readthedocs](http://configobj.readthedocs.io/). + +## Status + +This is a mature project that is not actively maintained at this time. -(notably adding python 3 support; previously this was 2.3 - 2.6) -Other versions may work, but this is what travis and tox uses to run the tests on commit. +## Past Contributors: -Roadmap -========= -- Fixing any issues introduced as a result of the added python 3 support -- Moving tests away from doctests in favor of pytest (reasonable now that versions older than 2.6 are dropped) -- Considering new features that work in a backwards-compatible way (feel free to open an issue with your suggestion) +- [Michael Foord](https://agileabstractions.com/) + - original creator of ``configobj`` and ``validate`` and maintainer through version 4 +- [Rob Dennis](https://github.com/robdennis) + - released version 5 (first python 3-compatible release) in 2014, bringing the project to github + - released the last maintenance release (until new maintainership is established) in 2023 +- [Eli Courtwright](https://github.com/EliAndrewC) + - released version 5 (first python 3-compatible release) in 2014 +- [Nicola Larosa](https://pypi.org/user/tekNico/) + - Contributions to the pre-version 5 codebase +- [Jürgen Hermann](https://github.com/jhermann) + - day-to-day maintenance of the repo diff --git a/_version.py b/_version.py deleted file mode 100644 index 6d01371..0000000 --- a/_version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = '5.0.6' \ No newline at end of file diff --git a/docs/configobj.html b/docs/configobj.html deleted file mode 100644 index 1cb1abe..0000000 --- a/docs/configobj.html +++ /dev/null @@ -1,2671 +0,0 @@ - - - - - - -Reading and Writing Config Files - - - - - - - -
-

Reading and Writing Config Files

-

ConfigObj 4 Introduction and Reference

- --- - - - - - - - - - - - - - - - - - -
Authors:Michael Foord -
Nicola Larosa
Version:ConfigObj 4.7.2
Date:2010/02/27
Homepage:ConfigObj Homepage
PyPI Entry:ConfigObj on PyPI
Development:Google Code Homepage
License:BSD License
Support:Mailing List
-
-

ConfigObj Manual

- -
-
-

Note

-

The best introduction to working with ConfigObj, including the powerful configuration validation system, -is the article:

- -
-
-

1   Introduction

-

ConfigObj is a simple but powerful config file reader and writer: an ini -file round tripper. Its main feature is that it is very easy to use, with a -straightforward programmer's interface and a simple syntax for config files. -It has lots of other features though :

- -

For support and bug reports please use the ConfigObj Mailing List or the issue tracker on the -Google Code Homepage.

-
-
-

2   Downloading

-

The current version is 4.7.2, dated 27th February 2010. ConfigObj 4 is -stable and mature. We still expect to pick up a few bugs along the way though [1].

-

You can get ConfigObj in the following ways :

- -
-

2.1   Installing

-

ConfigObj has a source distribution on PyPI. If you unzip -the archive you can install it with:

-
-setup.py install
-
-

Alternatively, you can install with easy install or pip:

-
-easy_install configobj
-
-
-
-

2.2   Documentation

-

configobj.zip also contains this document.

- -
-
-

2.3   Development Version

-

It is sometimes possible to get the latest development version of ConfigObj -from the Subversion Repository maintained on the Google Code Homepage.

-
-
-
-

3   ConfigObj in the Real World

-

ConfigObj is widely used. Projects using it include:

- -
-
-

4   Getting Started

-

The outstanding feature of using ConfigObj is simplicity. Most functions can be -performed with single line commands.

-
-

4.1   Reading a Config File

-

The normal way to read a config file, is to give ConfigObj the filename :

-
from configobj import ConfigObj
-config = ConfigObj(filename)
-
-

You can also pass the config file in as a list of lines, or a StringIO -instance, so it doesn't matter where your config data comes from.

-

You can then access members of your config file as a dictionary. Subsections -will also be dictionaries.

-
from configobj import ConfigObj
-config = ConfigObj(filename)
-#
-value1 = config['keyword1']
-value2 = config['keyword2']
-#
-section1 = config['section1']
-value3 = section1['keyword3']
-value4 = section1['keyword4']
-#
-# you could also write
-value3 = config['section1']['keyword3']
-value4 = config['section1']['keyword4']
-
-
-
-

4.2   Writing a Config File

-

Creating a new config file is just as easy as reading one. You can specify a -filename when you create the ConfigObj, or do it later [2].

-

If you don't set a filename, then the write method will return a list of -lines instead of writing to file. See the write method for more details.

-

Here we show creating an empty ConfigObj, setting a filename and some values, -and then writing to file :

-
from configobj import ConfigObj
-config = ConfigObj()
-config.filename = filename
-#
-config['keyword1'] = value1
-config['keyword2'] = value2
-#
-config['section1'] = {}
-config['section1']['keyword3'] = value3
-config['section1']['keyword4'] = value4
-#
-section2 = {
-    'keyword5': value5,
-    'keyword6': value6,
-    'sub-section': {
-        'keyword7': value7
-        }
-}
-config['section2'] = section2
-#
-config['section3'] = {}
-config['section3']['keyword 8'] = [value8, value9, value10]
-config['section3']['keyword 9'] = [value11, value12, value13]
-#
-config.write()
-
-
-

Caution!

-

Keywords and section names can only be strings [3]. Attempting to set -anything else will raise a ValueError.

-

See String Interpolation and List Values for an important note on -using lists in combination with String Interpolation.

-
-
-
-

4.3   Config Files

-

The config files that ConfigObj will read and write are based on the 'INI' -format. This means it will read and write files created for ConfigParser -[4].

-

Keywords and values are separated by an '=', and section markers are -between square brackets. Keywords, values, and section names can be surrounded -by single or double quotes. Indentation is not significant, but can be -preserved.

-

Subsections are indicated by repeating the square brackets in the section -marker. You nest levels by using more brackets.

-

You can have list values by separating items with a comma, and values spanning -multiple lines by using triple quotes (single or double).

-

For full details on all these see the config file format. Here's an example -to illustrate:

-
-# This is the 'initial_comment'
-# Which may be several lines
-keyword1 = value1
-'keyword 2' = 'value 2'
-
-[ "section 1" ]
-# This comment goes with keyword 3
-keyword 3 = value 3
-'keyword 4' = value4, value 5, 'value 6'
-
-    [[ sub-section ]]    # an inline comment
-    # sub-section is inside "section 1"
-    'keyword 5' = 'value 7'
-    'keyword 6' = '''A multiline value,
-that spans more than one line :-)
-The line breaks are included in the value.'''
-
-        [[[ sub-sub-section ]]]
-        # sub-sub-section is *in* 'sub-section'
-        # which is in 'section 1'
-        'keyword 7' = 'value 8'
-
-[section 2]    # an inline comment
-keyword8 = "value 9"
-keyword9 = value10     # an inline comment
-# The 'final_comment'
-# Which also may be several lines
-
-
-
-
-

5   ConfigObj specifications

-
config = ConfigObj(infile=None, options=None, configspec=None, encoding=None,
-                   interpolation=True, raise_errors=False, list_values=True,
-                   create_empty=False, file_error=False, stringify=True,
-                   indent_type=None, default_encoding=None, unrepr=False,
-                   write_empty_values=False, _inspec=False)
-
-

Many of the keyword arguments are available as attributes after the config file has been -parsed.

-
-

Note

-

New in ConfigObj 4.7.0: Instantiating ConfigObj with -an options dictionary is now deprecated. To modify code that used to -do this simply unpack the dictionary in the constructor call:

-
config = ConfigObj(filename, **options)
-
-
-

ConfigObj takes the following arguments (with the default values shown) :

- -
-

5.1   Methods

-

The ConfigObj is a subclass of an object called Section, which is itself a -subclass of dict, the builtin dictionary type. This means it also has -all the normal dictionary methods.

-

In addition, the following Section Methods may be useful :

-
    -
  • 'restore_default'
  • -
  • 'restore_defaults'
  • -
  • 'walk'
  • -
  • 'merge'
  • -
  • 'dict'
  • -
  • 'as_bool'
  • -
  • 'as_float'
  • -
  • 'as_int'
  • -
  • 'as_list'
  • -
-

Read about Sections for details of all the methods.

-
-

Hint

-

The merge method of sections is a recursive update.

-

You can use this to merge sections, or even whole ConfigObjs, into each -other.

-

You would typically use this to create a default ConfigObj and then merge -in user settings. This way users only need to specify values that are -different from the default. You can use configspecs and validation to -achieve the same thing of course.

-
-

The public methods available on ConfigObj are :

-
    -
  • 'write'
  • -
  • 'validate'
  • -
  • 'reset'
  • -
  • 'reload'
  • -
-
-

5.1.1   write

-
write(file_object=None)
-
-

This method writes the current ConfigObj and takes a single, optional argument -[9].

-

If you pass in a file like object to the write method, the config file will -be written to this. (The only method of this object that is used is its -write method, so a StringIO instance, or any other file like object -will work.)

-

Otherwise, the behaviour of this method depends on the filename attribute -of the ConfigObj.

-
-
filename
-
ConfigObj will write the configuration to the file specified.
-
None
-
write returns a list of lines. (Not '\n' terminated)
-
-

First the 'initial_comment' is written, then the config file, followed by the -'final_comment'. Comment lines and inline comments are written with each -key/value.

-
-
-

5.1.2   validate

-
validate(validator, preserve_errors=False, copy=False)
-
-
# filename is the config file
-# filename2 is the configspec
-# (which could also be hardcoded into your program)
-config = ConfigObj(filename, configspec=filename2)
-#
-from validate import Validator
-val = Validator()
-test = config.validate(val)
-if test == True:
-    print 'Succeeded.'
-
-

The validate method uses the validate module to do the -validation.

-

This method validates the ConfigObj against the configspec. By doing type -conversion as well it can abstract away the config file altogether and present -the config data to your application (in the types it expects it to be).

-

If the configspec attribute of the ConfigObj is None, it raises a -ValueError.

-

If the stringify attribute is set, this process will convert values to the -type defined in the configspec.

-

The validate method uses checks specified in the configspec and defined in the -Validator object. It is very easy to extend.

-

The configspec looks like the config file, but instead of the value, you -specify the check (and any default value). See the validation section for -details.

-
-

Hint

-

The system of configspecs can seem confusing at first, but is actually -quite simple and powerful. The best guide to them is this article on -ConfigObj:

- -
-

The copy parameter fills in missing values from the configspec (default -values), without marking the values as defaults. It also causes comments to -be copied from the configspec into the config file. This allows you to use a -configspec to create default config files. (Normally default values aren't -written out by the write method.)

-

As of ConfigObj 4.3.0 you can also pass in a ConfigObj instance as your -configspec. This is especially useful if you need to specify the encoding of -your configspec file. When you read your configspec file, you must specify -list_values=False. If you need to support hashes inside the configspec -values then you must also pass in _inspec=True. This is because configspec -files actually use a different syntax to config files and inline comment support -must be switched off to correctly read configspec files with hashes in the values.

-
from configobj import ConfigObj
-configspec = ConfigObj(configspecfilename, encoding='UTF8',
-                       list_values=False, _inspec=True)
-config = ConfigObj(filename, configspec=configspec)
-
-
-

5.1.2.1   Return Value

-

By default, the validate method either returns True (everything passed) -or a dictionary of True / False representing pass/fail. The dictionary -follows the structure of the ConfigObj.

-

If a whole section passes then it is replaced with the value True. If a -whole section fails, then it is replaced with the value False.

-

If a value is missing, and there is no default in the check, then the check -automatically fails.

-

The validate method takes an optional keyword argument preserve_errors. -If you set this to True, instead of getting False for failed checks you -get the actual error object from the validate module. This usually contains -useful information about why the check failed.

-

See the flatten_errors function for how to turn your results dictionary into -a useful list of error messages.

-

Even if preserve_errors is True, missing keys or sections will still be -represented by a False in the results dictionary.

-
-
-

5.1.2.2   Mentioning Default Values

-

In the check in your configspec, you can specify a default to be used - by -using the default keyword. E.g.

-
-key1 = integer(0, 30, default=15)
-key2 = integer(default=15)
-key3 = boolean(default=True)
-key4 = option('Hello', 'Goodbye', 'Not Today', default='Not Today')
-
-

If the configspec check supplies a default and the value is missing in the -config, then the default will be set in your ConfigObj. (It is still passed to -the Validator so that type conversion can be done: this means the default -value must still pass the check.)

-

ConfigObj keeps a record of which values come from defaults, using the -defaults attribute of sections. Any key in this list isn't written out by -the write method. If a key is set from outside (even to the same value) -then it is removed from the defaults list.

- -

There is additionally a special case default value of None. If you set the -default value to None and the value is missing, the value will always be -set to None. As the other checks don't return None (unless you -implement your own that do), you can tell that this value came from a default -value (and was missing from the config file). It allows an easy way of -implementing optional values. Simply check (and ignore) members that are set -to None.

-
-

Note

-

If stringify is False then default=None returns '' instead of -None. This is because setting a value to a non-string raises an error -if stringify is unset.

-
-

The default value can be a list. See List Values for the way to do this.

-

Writing invalid default values is a guaranteed way of confusing your users. -Default values must pass the check.

-
-
-

5.1.2.3   Mentioning Repeated Sections and Values

-

In the configspec it is possible to cause every sub-section in a section to -be validated using the same configspec. You do this with a section in the -configspec called __many__. Every sub-section in that section has the -__many__ configspec applied to it (without you having to explicitly name -them in advance).

-

Your __many__ section can have nested subsections, which can also include -__many__ type sections.

-

You can also specify that all values should be validated using the same configspec, -by having a member with the name __many__. If you want to use repeated values -along with repeated sections then you can call one of them ___many___ (triple -underscores).

-

Sections with repeated sections or values can also have specifically named sub-sections -or values. The __many__ configspec will only be used to validate entries that don't -have an explicit configspec.

-

See Repeated Sections for examples.

-
-
-

5.1.2.4   Mentioning SimpleVal

-

If you just want to check if all members are present, then you can use the -SimpleVal object that comes with ConfigObj. It only fails members if they -are missing.

-

Write a configspec that has all the members you want to check for, but set -every section to ''.

-
val = SimpleVal()
-test = config.validate(val)
-if test is True:
-    print 'Succeeded.'
-
-
-
-

5.1.2.5   Mentioning copy Mode

-

As discussed in Mentioning Default Values, you can use a configspec to -supply default values. These are marked in the ConfigObj instance as defaults, -and not written out by the write mode. This means that your users only -need to supply values that are different from the defaults.

-

This can be inconvenient if you do want to write out the default values, -for example to write out a default config file.

-

If you set copy=True when you call validate, then no values are marked as -defaults. In addition, all comments from the configspec are copied into -your ConfigObj instance. You can then call write to create your config -file.

-

There is a limitation with this. In order to allow String Interpolation to work -within configspecs, DEFAULT sections are not processed by -validation; even in copy mode.

-
-
-
-

5.1.3   reload

-

If a ConfigObj instance was loaded from the filesystem, then this method will reload it. It -will also reuse any configspec you supplied at instantiation (including reloading it from -the filesystem if you passed it in as a filename).

-

If the ConfigObj does not have a filename attribute pointing to a file, then a ReloadError -will be raised.

-
-
-

5.1.4   reset

-

This method takes no arguments and doesn't return anything. It restores a ConfigObj -instance to a freshly created state.

-
-
-
-

5.2   Attributes

-

A ConfigObj has the following attributes :

-
    -
  • indent_type
  • -
  • interpolation
  • -
  • stringify
  • -
  • BOM
  • -
  • initial_comment
  • -
  • final_comment
  • -
  • list_values
  • -
  • encoding
  • -
  • default_encoding
  • -
  • unrepr
  • -
  • write_empty_values
  • -
  • newlines
  • -
-
-

Note

-

This doesn't include comments, inline_comments, defaults, or -configspec. These are actually attributes of Sections.

-
-

It also has the following attributes as a result of parsing. They correspond to -options when the ConfigObj was created, but changing them has no effect.

-
    -
  • raise_errors
  • -
  • create_empty
  • -
  • file_error
  • -
-
-

5.2.1   interpolation

-

ConfigObj can perform string interpolation in a similar way to -ConfigParser. See the String Interpolation section for full details.

-

If interpolation is set to False, then interpolation is not done when -you fetch values.

-
-
-

5.2.2   stringify

-

If this attribute is set (True) then the validate method changes the -values in the ConfigObj. These are turned back into strings when write is -called.

-

If stringify is unset (False) then attempting to set a value to a non -string (or a list of strings) will raise a TypeError.

-
-
-

5.2.3   BOM

-

If the initial config file started with the UTF8 Unicode signature (known -slightly incorrectly as the BOM - Byte Order Mark), or the UTF16 BOM, then -this attribute is set to True. Otherwise it is False.

-

If it is set to True when write is called then, if encoding is set -to None or to utf_8 (and variants) a UTF BOM will be written.

-

For UTF16 encodings, a BOM is always written.

-
-
-

5.2.4   initial_comment

-

This is a list of lines. If the ConfigObj is created from an existing file, it -will contain any lines of comments before the start of the members.

-

If you create a new ConfigObj, this will be an empty list.

-

The write method puts these lines before it starts writing out the members.

-
-
-

5.2.5   final_comment

-

This is a list of lines. If the ConfigObj is created from an existing file, it -will contain any lines of comments after the last member.

-

If you create a new ConfigObj, this will be an empty list.

-

The write method puts these lines after it finishes writing out the -members.

-
-
-

5.2.6   list_values

-

This attribute is True or False. If set to False then values are -not parsed for list values. In addition single line values are not unquoted.

-

This allows you to do your own parsing of values. It exists primarily to -support the reading of the configspec - but has other use cases.

-

For example you could use the LineParser from the -listquote module -to read values for nested lists.

-

Single line values aren't quoted when writing - but multiline values are -handled as normal.

-
-

Caution!

-

Because values aren't quoted, leading or trailing whitespace can be lost. This behaviour was changed in version 4.0.1. Prior to this, single line values might have been quoted; even with list_values=False. This means that files written by earlier versions of ConfigObj could now be incompatible and need the quotes removing by hand.

-
-
-
-

5.2.7   encoding

-

This is the encoding used to encode the output, when you call write. It -must be a valid encoding recognised by Python.

-

If this value is None then no encoding is done when write is called.

-
-
-

5.2.8   default_encoding

-

If encoding is set, any byte-strings in your ConfigObj instance (keys or -members) will first be decoded to Unicode using the encoding specified by the -default_encoding attribute. This ensures that the output is in the encoding -specified.

-

If this value is None then sys.defaultencoding is used instead.

-
-
-

5.2.9   unrepr

-

Another boolean value. If this is set, then repr(value) is used to write -values. This writes values in a slightly different way to the normal ConfigObj -file syntax.

-

This preserves basic Python data-types when read back in. See unrepr mode -for more details.

-
-
-

5.2.10   write_empty_values

-

Also boolean. If set, values that are an empty string ('') are written as -empty values. See Empty Values for more details.

-
-
-

5.2.11   newlines

-

When a config file is read, ConfigObj records the type of newline separators in the -file and uses this separator when writing. It defaults to None, and ConfigObj -uses the system default (os.linesep) if write is called without newlines having -been set.

-
-
-
-
-

6   The Config File Format

-

You saw an example config file in the Config Files section. Here is a fuller -specification of the config files used and created by ConfigObj.

-

The basic pattern for keywords is:

-
-# comment line
-# comment line
-keyword = value # inline comment
-
-

Both keyword and value can optionally be surrounded in quotes. The equals sign -is the only valid divider.

-

Values can have comments on the lines above them, and an inline comment after -them. This, of course, is optional. See the comments section for details.

-

If a keyword or value starts or ends with whitespace, or contains a quote mark -or comma, then it should be surrounded by quotes. Quotes are not necessary if -whitespace is surrounded by non-whitespace.

-

Values can also be lists. Lists are comma separated. You indicate a single -member list by a trailing comma. An empty list is shown by a single comma:

-
-keyword1 = value1, value2, value3
-keyword2 = value1, # a single member list
-keyword3 = , # an empty list
-
-

Values that contain line breaks (multi-line values) can be surrounded by triple -quotes. These can also be used if a value contains both types of quotes. List -members cannot be surrounded by triple quotes:

-
-keyword1 = ''' A multi line value
-on several
-lines'''     # with a comment
-keyword2 = '''I won't be "afraid".'''
-#
-keyword3 = """ A multi line value
-on several
-lines"""     # with a comment
-keyword4 = """I won't be "afraid"."""
-
-
-

Warning

-

There is no way of safely quoting values that contain both types of triple -quotes.

-
-

A line that starts with a '#', possibly preceded by whitespace, is a comment.

-

New sections are indicated by a section marker line. That is the section name -in square brackets. Whitespace around the section name is ignored. The name can -be quoted with single or double quotes. The marker can have comments before it -and an inline comment after it:

-
-# The First Section
-[ section name 1 ] # first section
-keyword1 = value1
-
-# The Second Section
-[ "section name 2" ] # second section
-keyword2 = value2
-
-

Any subsections (sections that are inside the current section) are -designated by repeating the square brackets before and after the section name. -The number of square brackets represents the nesting level of the sub-section. -Square brackets may be separated by whitespace; such whitespace, however, will -not be present in the output config written by the write method.

-

Indentation is not significant, but can be preserved. See the description of -the indent_type option, in the ConfigObj specifications chapter, for the -details.

-

A NestingError will be raised if the number of the opening and the closing -brackets in a section marker is not the same, or if a sub-section's nesting -level is greater than the nesting level of it parent plus one.

-

In the outer section, single values can only appear before any sub-section. -Otherwise they will belong to the sub-section immediately before them:

-
-# initial comment
-keyword1 = value1
-keyword2 = value2
-
-[section 1]
-keyword1 = value1
-keyword2 = value2
-
-    [[sub-section]]
-    # this is in section 1
-    keyword1 = value1
-    keyword2 = value2
-
-        [[[nested section]]]
-        # this is in sub section
-        keyword1 = value1
-        keyword2 = value2
-
-    [[sub-section2]]
-    # this is in section 1 again
-    keyword1 = value1
-    keyword2 = value2
-
-[[sub-section3]]
-# this is also in section 1, indentation is misleading here
-keyword1 = value1
-keyword2 = value2
-
-# final comment
-
-

When parsed, the above config file produces the following data structure:

-
ConfigObj({
-    'keyword1': 'value1',
-    'keyword2': 'value2',
-    'section 1': {
-        'keyword1': 'value1',
-        'keyword2': 'value2',
-        'sub-section': {
-            'keyword1': 'value1',
-            'keyword2': 'value2',
-            'nested section': {
-                'keyword1': 'value1',
-                'keyword2': 'value2',
-            },
-        },
-        'sub-section2': {
-            'keyword1': 'value1',
-            'keyword2': 'value2',
-        },
-        'sub-section3': {
-            'keyword1': 'value1',
-            'keyword2': 'value2',
-        },
-    },
-})
-
-

Sections are ordered: note how the structure of the resulting ConfigObj is in -the same order as the original file.

-
-

Note

-

In ConfigObj 4.3.0 empty values became valid syntax. They are read as the -empty string. There is also an option/attribute (write_empty_values) to -allow the writing of these.

-

This is mainly to support 'legacy' config files, written from other -applications. This is documented under Empty Values.

-

unrepr mode introduces another syntax variation, used for storing -basic Python datatypes in config files.

-
-
-
-

7   Sections

-

Every section in a ConfigObj has certain properties. The ConfigObj itself also -has these properties, because it too is a section (sometimes called the root -section).

-

Section is a subclass of the standard new-class dictionary, therefore it -has all the methods of a normal dictionary. This means you can update -and clear sections.

-
-

Note

-

You create a new section by assigning a member to be a dictionary.

-

The new Section is created from the dictionary, but isn't the same -thing as the dictionary. (So references to the dictionary you use to create -the section aren't references to the new section).

-

Note the following.

-
config = ConfigObj()
-vals = {'key1': 'value 1',
-        'key2': 'value 2'
-       }
-config['vals'] = vals
-config['vals'] == vals
-True
-config['vals'] is vals
-False
-
-

If you now change vals, the changes won't be reflected in config['vals'].

-
-

A section is ordered, following its scalars and sections -attributes documented below. This means that the following dictionary -attributes return their results in order.

- -
-

7.1   Section Attributes

-
    -
  • main

    -
    -

    A reference to the main ConfigObj.

    -
    -
  • -
  • parent

    -
    -

    A reference to the 'parent' section, the section that this section is a -member of.

    -

    On the ConfigObj this attribute is a reference to itself. You can use this -to walk up the sections, stopping when section.parent is section.

    -
    -
  • -
  • depth

    -
    -

    The nesting level of the current section.

    -

    If you create a new ConfigObj and add sections, 1 will be added to the -depth level between sections.

    -
    -
  • -
  • defaults

    -
    -

    This attribute is a list of scalars that came from default values. Values -that came from defaults aren't written out by the write method. -Setting any of these values in the section removes them from the defaults -list.

    -
    -
  • -
  • default_values

    -
    -

    This attribute is a dictionary mapping keys to the default values for the -keys. By default it is an empty dictionary and is populated when you -validate the ConfigObj.

    -
    -
  • -
  • scalars, sections

    -
    -

    These attributes are normal lists, representing the order that members, -single values and subsections appear in the section. The order will either -be the order of the original config file, or the order that you added -members.

    -

    The order of members in this lists is the order that write creates in -the config file. The scalars list is output before the sections -list.

    -

    Adding or removing members also alters these lists. You can manipulate the -lists directly to alter the order of members.

    -
    -

    Warning

    -

    If you alter the scalars, sections, or defaults attributes -so that they no longer reflect the contents of the section, you will -break your ConfigObj.

    -
    -

    See also the rename method.

    -
    -
  • -
  • comments

    -
    -

    This is a dictionary of comments associated with each member. Each entry is -a list of lines. These lines are written out before the member.

    -
    -
  • -
  • inline_comments

    -
    -

    This is another dictionary of comments associated with each member. Each -entry is a string that is put inline with the member.

    -
    -
  • -
  • configspec

    -
    -

    The configspec attribute is a dictionary mapping scalars to checks. A -check defines the expected type and possibly the allowed values for a -member.

    -

    The configspec has the same format as a config file, but instead of values -it has a specification for the value (which may include a default value). -The validate method uses it to check the config file makes sense. If a -configspec is passed in when the ConfigObj is created, then it is parsed -and broken up to become the configspec attribute of each section.

    -

    If you didn't pass in a configspec, this attribute will be None on the -root section (the main ConfigObj).

    -

    You can set the configspec attribute directly on a section.

    -

    See the validation section for full details of how to write configspecs.

    -
    -
  • -
  • extra_values

    -
    -

    By default an empty list. After validation this is populated with any members -of the section that don't appear in the configspec (i.e. they are additional -values). Rather than accessing this directly it may be more convenient to get -all the extra values in a config file using the get_extra_values function.

    -

    New in ConfigObj 4.7.0.

    -
    -
  • -
-
-
-

7.2   Section Methods

-
    -
  • dict

    -
    -

    This method takes no arguments. It returns a deep copy of the section as a -dictionary. All subsections will also be dictionaries, and list values will -be copies, rather than references to the original [10].

    -
    -
  • -
  • rename

    -
    -

    rename(oldkey, newkey)

    -

    This method renames a key, without affecting its position in the sequence.

    -
    -
  • -
  • merge

    -
    -

    merge(indict)

    -

    This method is a recursive update method. It allows you to merge two -config files together.

    -

    You would typically use this to create a default ConfigObj and then merge -in user settings. This way users only need to specify values that are -different from the default.

    -

    For example :

    -
    # def_cfg contains your default config settings
    -# user_cfg contains the user settings
    -cfg = ConfigObj(def_cfg)
    -usr = ConfigObj(user_cfg)
    -#
    -cfg.merge(usr)
    -
    -"""
    -cfg now contains a combination of the default settings and the user
    -settings.
    -
    -The user settings will have overwritten any of the default ones.
    -"""
    -
    -
    -
  • -
  • walk

    -
    -

    This method can be used to transform values and names. See walking a -section for examples and explanation.

    -
    -
  • -
  • as_bool

    -
    -

    as_bool(key)

    -

    Returns True if the key contains a string that represents True, or -is the True object.

    -

    Returns False if the key contains a string that represents False, -or is the False object.

    -

    Raises a ValueError if the key contains anything else.

    -

    Strings that represent True are (not case sensitive):

    -
    -true, yes, on, 1
    -
    -

    Strings that represent False are:

    -
    -false, no, off, 0
    -
    -
    -
  • -
  • as_int

    -
    -

    as_int(key)

    -

    This returns the value contained in the specified key as an integer.

    -

    It raises a ValueError if the conversion can't be done.

    -
    -
  • -
  • as_float

    -
    -

    as_float(key)

    -

    This returns the value contained in the specified key as a float.

    -

    It raises a ValueError if the conversion can't be done.

    -
    -
  • -
  • as_list

    -
    -

    as_list(key)

    -

    This returns the value contained in the specified key as a list.

    -

    If it isn't a list it will be wrapped as a list so that you can -guarantee the returned value will be a list.

    -
    -
  • -
  • restore_default

    -
    -

    restore_default(key)

    -

    Restore (and return) the default value for the specified key.

    -

    This method will only work for a ConfigObj that was created -with a configspec and has been validated.

    -

    If there is no default value for this key, KeyError is raised.

    -
    -
  • -
  • restore_defaults

    -
    -

    restore_defaults()

    -

    Recursively restore default values to all members -that have them.

    -

    This method will only work for a ConfigObj that was created -with a configspec and has been validated.

    -

    It doesn't delete or modify entries without default values.

    -
    -
  • -
-
-
-

7.3   Walking a Section

-
-

Note

-

The walk method allows you to call a function on every member/name.

-
-
walk(function, raise_errors=True,
-     call_on_sections=False, **keywargs)
-
-

walk is a method of the Section object. This means it is also a method -of ConfigObj.

-

It walks through every member and calls a function on the keyword and value. It -walks recursively through subsections.

-

It returns a dictionary of all the computed values.

-

If the function raises an exception, the default is to propagate the error, and -stop. If raise_errors=False then it sets the return value for that keyword -to False instead, and continues. This is similar to the way validation -works.

-

Your function receives the arguments (section, key). The current value is -then section[key] [11]. Any unrecognised keyword arguments you pass to -walk, are passed on to the function.

-

Normally walk just recurses into subsections. If you are transforming (or -checking) names as well as values, then you want to be able to change the names -of sections. In this case set call_on_sections to True. Now, on -encountering a sub-section, first the function is called for the whole -sub-section, and then it recurses into it's members. This means your function -must be able to handle receiving dictionaries as well as strings and lists.

-

If you are using the return value from walk and call_on_sections, -note that walk discards the return value when it calls your function.

-
-

Caution!

-

You can use walk to transform the names of members of a section -but you mustn't add or delete members.

-
-
-
-

7.4   Examples

-

You can use this for transforming all values in your ConfigObj. For example -you might like the nested lists from ConfigObj 3. This was provided by the -listquote module. You could switch off the parsing for list values -(list_values=False) and use listquote to parse every value.

-

Another thing you might want to do is use the Python escape codes in your -values. You might be used to using \n for line feed and \t for tab. -Obviously we'd need to decode strings that come from the config file (using the -escape codes). Before writing out we'll need to put the escape codes back in -encode.

-

As an example we'll write a function to use with walk, that encodes or decodes -values using the string-escape codec.

-

The function has to take each value and set the new value. As a bonus we'll -create one function that will do decode or encode depending on a keyword -argument.

-

We don't want to work with section names, we're only transforming values, so -we can leave call_on_sections as False. This means the two datatypes we -have to handle are strings and lists, we can ignore everything else. (We'll -treat tuples as lists as well).

-

We're not using the return values, so it doesn't need to return anything, just -change the values if appropriate.

-
def string_escape(section, key, encode=False):
-    """
-    A function to encode or decode using the 'string-escape' codec.
-    To be passed to the walk method of a ConfigObj.
-    By default it decodes.
-    To encode, pass in the keyword argument ``encode=True``.
-    """
-    val = section[key]
-    # is it a type we can work with
-    # NOTE: for platforms where Python > 2.2
-    # you can use basestring instead of (str, unicode)
-    if not isinstance(val, (str, unicode, list, tuple)):
-        # no !
-        return
-    elif isinstance(val, (str, unicode)):
-        # it's a string !
-        if not encode:
-            section[key] = val.decode('string-escape')
-        else:
-            section[key] = val.encode('string-escape')
-    else:
-        # it must be a list or tuple!
-        # we'll be lazy and create a new list
-        newval = []
-        # we'll check every member of the list
-        for entry in val:
-            if isinstance(entry, (str, unicode)):
-                if not encode:
-                    newval.append(entry.decode('string-escape'))
-                else:
-                   newval.append(entry.encode('string-escape'))
-            else:
-                newval.append(entry)
-        # done !
-        section[key] =  newval
-
-# assume we have a ConfigObj called ``config``
-#
-# To decode
-config.walk(string_escape)
-#
-# To encode.
-# Because ``walk`` doesn't recognise the ``encode`` argument
-# it passes it to our function.
-config.walk(string_escape, encode=True)
-
-

Here's a simple example of using walk to transform names and values. One -usecase of this would be to create a standard config file with placeholders -for section and keynames. You can then use walk to create new config files -and change values and member names :

-
# We use 'XXXX' as a placeholder
-config = '''
-XXXXkey1 = XXXXvalue1
-XXXXkey2 = XXXXvalue2
-XXXXkey3 = XXXXvalue3
-[XXXXsection1]
-XXXXkey1 = XXXXvalue1
-XXXXkey2 = XXXXvalue2
-XXXXkey3 = XXXXvalue3
-[XXXXsection2]
-XXXXkey1 = XXXXvalue1
-XXXXkey2 = XXXXvalue2
-XXXXkey3 = XXXXvalue3
-    [[XXXXsection1]]
-    XXXXkey1 = XXXXvalue1
-    XXXXkey2 = XXXXvalue2
-    XXXXkey3 = XXXXvalue3
-'''.splitlines()
-cfg = ConfigObj(config)
-#
-def transform(section, key):
-    val = section[key]
-    newkey = key.replace('XXXX', 'CLIENT1')
-    section.rename(key, newkey)
-    if isinstance(val, (tuple, list, dict)):
-        pass
-    else:
-        val = val.replace('XXXX', 'CLIENT1')
-        section[newkey] = val
-#
-cfg.walk(transform, call_on_sections=True)
-print cfg
-ConfigObj({'CLIENT1key1': 'CLIENT1value1', 'CLIENT1key2': 'CLIENT1value2',
-'CLIENT1key3': 'CLIENT1value3',
-'CLIENT1section1': {'CLIENT1key1': 'CLIENT1value1',
-    'CLIENT1key2': 'CLIENT1value2', 'CLIENT1key3': 'CLIENT1value3'},
-'CLIENT1section2': {'CLIENT1key1': 'CLIENT1value1',
-    'CLIENT1key2': 'CLIENT1value2', 'CLIENT1key3': 'CLIENT1value3',
-    'CLIENT1section1': {'CLIENT1key1': 'CLIENT1value1',
-        'CLIENT1key2': 'CLIENT1value2', 'CLIENT1key3': 'CLIENT1value3'}}})
-
-
-
-
-

8   Exceptions

-

There are several places where ConfigObj may raise exceptions (other than -because of bugs).

-
    -
  1. -
    If a configspec filename you pass in doesn't exist, or a config file
    -

    filename doesn't exist and file_error=True, an IOError will be -raised.

    -
    -
    -
  2. -
  3. -
    If you try to set a non-string key, or a non string value when
    -

    stringify=False, a TypeError will be raised.

    -
    -
    -
  4. -
  5. A badly built config file will cause parsing errors.

    -
  6. -
  7. A parsing error can also occur when reading a configspec.

    -
  8. -
  9. -
    In string interpolation you can specify a value that doesn't exist, or
    -

    create circular references (recursion).

    -
    -
    -
  10. -
-

Number 5 (which is actually two different types of exceptions) is documented -in String Interpolation.

-

This section is about errors raised during parsing.

-

The base error class is ConfigObjError. This is a subclass of -SyntaxError, so you can trap for SyntaxError without needing to -directly import any of the ConfigObj exceptions.

-

The following other exceptions are defined (all deriving from -ConfigObjError) :

- -

When parsing a configspec, ConfigObj will stop on the first error it -encounters. It will raise a ConfigspecError. This will have an error -attribute, which is the actual error that was raised.

-

Behaviour when parsing a config file depends on the option raise_errors. -If ConfigObj encounters an error while parsing a config file:

-
-

If raise_errors=True then ConfigObj will raise the appropriate error -and parsing will stop.

-

If raise_errors=False (the default) then parsing will continue to the -end and all errors will be collected.

-
-

If raise_errors is False and multiple errors are found a ConfigObjError -is raised. The error raised has a config attribute, which is the parts of -the ConfigObj that parsed successfully. It also has an attribute errors, -which is a list of all the errors raised. Each entry in the list is an -instance of the appropriate error type. Each one has the following attributes -(useful for delivering a sensible error message to your user) :

- -

If only one error is found, then that error is re-raised. The error still has -the config and errors attributes. This means that your error handling -code can be the same whether one error is raised in parsing , or several.

-

It also means that in the most common case (a single error) a useful error -message will be raised.

-
-

Note

-

One wrongly written line could break the basic structure of your config -file. This could cause every line after it to flag an error, so having a -list of all the lines that caused errors may not be as useful as it sounds.

-
-
-
-

9   Validation

-
-

Hint

-

The system of configspecs can seem confusing at first, but is actually -quite simple and powerful. The best reference is my article on ConfigObj:

- -
-

Validation is done through a combination of the configspec and a Validator -object. For this you need validate.py [12]. See downloading if you don't -have a copy.

-

Validation can perform two different operations :

-
    -
  1. -
    Check that a value meets a specification. For example, check that a value
    -

    is an integer between one and six, or is a choice from a specific set of -options.

    -
    -
    -
  2. -
  3. -
    It can convert the value into the type required. For example, if one of
    -

    your values is a port number, validation will turn it into an integer for -you.

    -
    -
    -
  4. -
-

So validation can act as a transparent layer between the datatypes of your -application configuration (boolean, integers, floats, etc) and the text format -of your config file.

-
-

9.1   configspec

-

The validate method checks members against an entry in the configspec. Your -configspec therefore resembles your config file, with a check for every member.

-

In order to perform validation you need a Validator object. This has -several useful built-in check functions. You can also create your own custom -functions and register them with your Validator object.

-

Each check is the name of one of these functions, including any parameters and -keyword arguments. The configspecs look like function calls, and they map to -function calls.

-

The basic datatypes that an un-extended Validator can test for are :

-
    -
  • boolean values (True and False)
  • -
  • integers (including minimum and maximum values)
  • -
  • floats (including min and max)
  • -
  • strings (including min and max length)
  • -
  • IP addresses (v4 only)
  • -
-

It can also handle lists of these types and restrict a value to being one from -a set of options.

-

An example configspec is going to look something like:

-
-port = integer(0, 100)
-user = string(max=25)
-mode = option('quiet', 'loud', 'silent')
-
-

You can specify default values, and also have the same configspec applied to -several sections. This is called repeated sections.

-

For full details on writing configspecs, please refer to the validate.py -documentation.

-
-

Important

-

Your configspec is read by ConfigObj in the same way as a config file.

-

That means you can do interpolation within your configspec.

-

In order to allow this, checks in the 'DEFAULT' section (of the root level -of your configspec) are not used.

-

If you want to use a configspec without interpolation being done in it -you can create your configspec manually and switch off interpolation:

-
from configobj import ConfigObj
-
-configspec = ConfigObj(spec_filename, interpolation=False, list_values=False,
-                       _inspec=True)
-conf = ConfigObj(config_filename, configspec=configspec)
-
-
-

If you need to specify the encoding of your configspec, then you can pass in a -ConfigObj instance as your configspec. When you read your configspec file, you -must specify list_values=False. If you need to support hashes in -configspec values then you must also pass in _inspec=True.

-
from configobj import ConfigObj
-configspec = ConfigObj(configspecfilename, encoding='UTF8',
-                       list_values=False, _inspec=True)
-config = ConfigObj(filename, configspec=configspec)
-
-
-
-

9.2   Type Conversion

-

By default, validation does type conversion. This means that if you specify -integer as the check, then calling validate will actually change the value -to an integer (so long as the check succeeds).

-

It also means that when you call the write method, the value will be converted -back into a string using the str function.

-

To switch this off, and leave values as strings after validation, you need to -set the stringify attribute to False. If this is the case, attempting to -set a value to a non-string will raise an error.

-
-
-

9.3   Default Values

-

You can set a default value in your check. If the value is missing from the -config file then this value will be used instead. This means that your user -only has to supply values that differ from the defaults.

-

If you don't supply a default then for a value to be missing is an error, -and this will show in the return value from validate.

-

Additionally you can set the default to be None. This means the value will -be set to None (the object) whichever check is used. (It will be set to -'' rather than None if stringify is False). You can use this -to easily implement optional values in your config files.

-
-port = integer(0, 100, default=80)
-user = string(max=25, default=0)
-mode = option('quiet', 'loud', 'silent', default='loud')
-nick = string(default=None)
-
-
-

Note

-

Because the default goes through type conversion, it also has to pass the -check.

-

Note that default=None is case sensitive.

-
-
-

9.3.1   List Values

-

It's possible that you will want to specify a list as a default value. To avoid -confusing syntax with commas and quotes you use a list constructor to specify -that keyword arguments are lists. This includes the default value. This -makes checks look something like:

-
-checkname(default=list('val1', 'val2', 'val3'))
-
-

This works with all keyword arguments, but is most useful for default values.

-
-
-
-

9.4   Repeated Sections

-

Repeated sections are a way of specifying a configspec for a section that -should be applied to all unspecified subsections in the same section.

-

The easiest way of explaining this is to give an example. Suppose you have a -config file that describes a dog. That dog has various attributes, but it can -also have many fleas. You don't know in advance how many fleas there will be, -or what they will be called, but you want each flea validated against the same -configspec.

-

We can define a section called fleas. We want every flea in that section -(every sub-section) to have the same configspec applied to it. We do this by -defining a single section called __many__.

-
-[dog]
-name = string(default=Rover)
-age = float(0, 99, default=0)
-
-    [[fleas]]
-
-        [[[__many__]]]
-        bloodsucker = boolean(default=True)
-        children = integer(default=10000)
-        size = option(small, tiny, micro, default=tiny)
-
-

Every flea on our dog will now be validated using the __many__ configspec.

-

__many__ sections can have sub-sections, including their own __many__ -sub-sections. Defaults work in the normal way in repeated sections.

-
-
-

9.5   Repeated Values

-

As well as using __many__ to validate unspecified sections you can use it to validate values. For -example, to specify that all values in a section should be integers:

-
-[section]
-    __many__ = integer
-
-

If you want to use repeated values alongside repeated sections you can call one __many__ and the -other ___many___ (with three underscores).

-
-
-

9.6   Copy Mode

-

Because you can specify default values in your configspec, you can use -ConfigObj to write out default config files for your application.

-

However, normally values supplied from a default in a configspec are not -written out by the write method.

-

To do this, you need to specify copy=True when you call validate. As well -as not marking values as default, all the comments in the configspec file -will be copied into your ConfigObj instance.

-
from configobj import ConfigObj
-from validate import Validator
-vdt = Validator()
-config = ConfigObj(configspec='default.ini')
-config.filename = 'new_default.ini'
-config.validate(vdt, copy=True)
-config.write()
-
-

If you need to support hashes in the configspec values then you must create -it with _inspec=True. This has the side effect of switching off the parsing -of inline comments, meaning that they won't be copied into the new config file. -(ConfigObj syntax is slightly different from configspec syntax and the parser -can't support both inline comments and hashes in configspec values.)

-
-
-

9.7   Validation and Interpolation

-

String interpolation and validation don't play well together. When validation -changes type it sets the value. If the value uses interpolation, then the -interpolation reference would normally be overwritten. Calling write would -then use the absolute value and the interpolation reference would be lost.

-

As a compromise - if the value is unchanged by validation then it is not reset. -This means strings that pass through validation unmodified will not be -overwritten. If validation changes type - the value has to be overwritten, and -any interpolation references are lost.

-
-
-

9.8   Extra Values

-

After validation the extra_values member of every section that is listed in -the configspec will be populated with the names of members that are in the -config file but not in the configspec.

-

If you are reporting configuration errors to your user this information can be -useful, for example some missing entries may be due to misspelt entries that -appear as extra values.

-

See the get_extra_values function

-

New in ConfigObj 4.7.0.

-
-
-

9.9   SimpleVal

-

You may not need a full validation process, but still want to check if all the -expected values are present.

-

Provided as part of the ConfigObj module is the SimpleVal object. This has -a dummy test method that always passes.

-

The only reason a test will fail is if the value is missing. The return value -from validate will either be True, meaning all present, or a dictionary -with False for all missing values/sections.

-

To use it, you still need to pass in a valid configspec when you create the -ConfigObj, but just set all the values to ''. Then create an instance of -SimpleVal and pass it to the validate method.

-

As a trivial example if you had the following config file:

-
-# config file for an application
-port = 80
-protocol = http
-domain = voidspace
-top_level_domain = org.uk
-
-

You would write the following configspec:

-
-port = ''
-protocol = ''
-domain = ''
-top_level_domain = ''
-
-
config = Configobj(filename, configspec=configspec)
-val = SimpleVal()
-test = config.validate(val)
-if test == True:
-    print 'All values present.'
-elif test == False:
-    print 'No values present!'
-else:
-    for entry in test:
-        if test[entry] == False:
-            print '"%s" missing.' % entry
-
-
-
-
-

10   Empty values

-

Many config files from other applications allow empty values. As of version -4.3.0, ConfigObj will read these as an empty string.

-

A new option/attribute has been added (write_empty_values) to allow -ConfigObj to write empty strings as empty values.

-
from configobj import ConfigObj
-cfg = '''
-    key =
-    key2 = # a comment
-'''.splitlines()
-config = ConfigObj(cfg)
-print config
-ConfigObj({'key': '', 'key2': ''})
-
-config.write_empty_values = True
-for line in config.write():
-    print line
-
-key =
-key2 =     # a comment
-
-
-
-

11   unrepr mode

-

The unrepr option allows you to store and retrieve the basic Python -data-types using config files. It has to use a slightly different syntax to -normal ConfigObj files. Unsurprisingly it uses Python syntax.

-

This means that lists are different (they are surrounded by square brackets), -and strings must be quoted.

-

The types that unrepr can work with are :

-
-
-
strings, lists tuples
-
None, True, False
-
dictionaries, integers, floats
-
longs and complex numbers
-
-
-

You can't store classes, types or instances.

-

unrepr uses repr(object) to write out values, so it currently doesn't -check that you are writing valid objects. If you attempt to read an unsupported -value, ConfigObj will raise a configobj.UnknownType exception.

-

Values that are triple quoted cased. The triple quotes are removed before -converting. This means that you can use triple quotes to write dictionaries -over several lines in your config files. They won't be written like this -though.

-

If you are writing config files by hand, for use with unrepr, you should -be aware of the following differences from normal ConfigObj syntax :

-
-
-
List : ['A List', 'With', 'Strings']
-
Strings : "Must be quoted."
-
Backslash : "The backslash must be escaped \\"
-
-
-

These all follow normal Python syntax.

-

In unrepr mode inline comments are not saved. This is because lines are -parsed using the compiler package -which discards comments.

-
-
-

12   String Interpolation

-
-

Note

-

String interpolation can slow down (slightly) the fetching of values -from your config object. If you aren't using interpolation and it -is performance critical then create your instance with -interpolation=False.

-
-

ConfigObj allows string interpolation similar to the way ConfigParser -or string.Template work. The value of the interpolation attribute -determines which style of interpolation you want to use. Valid values are -"ConfigParser" or "Template" (case-insensitive, so "configparser" and -"template" will also work). For backwards compatibility reasons, the value -True is also a valid value for the interpolation attribute, and -will select ConfigParser-style interpolation. At some undetermined point -in the future, that default may change to Template-style interpolation.

-

For ConfigParser-style interpolation, you specify a value to be -substituted by including %(name)s in the value.

-

For Template-style interpolation, you specify a value to be substituted -by including ${cl}name{cr} in the value. Alternately, if 'name' is a valid -Python identifier (i.e., is composed of nothing but alphanumeric characters, -plus the underscore character), then the braces are optional and the value -can be written as $name.

-

Note that ConfigParser-style interpolation and Template-style -interpolation are mutually exclusive; you cannot have a configuration file -that's a mix of one or the other. Pick one and stick to it. Template-style -interpolation is simpler to read and write by hand, and is recommended if -you don't have a particular reason to use ConfigParser-style.

-

Interpolation checks first the current section to see if name is the key -to a value. ('name' is case sensitive).

-

If it doesn't find it, next it checks the 'DEFAULT' sub-section of the current -section.

-

If it still doesn't find it, it moves on to check the parent section and the -parent section's 'DEFAULT' subsection, and so on all the way up to the main -section.

-

If the value specified isn't found in any of these locations, then a -MissingInterpolationOption error is raised (a subclass of -ConfigObjError).

-

If it is found then the returned value is also checked for substitutions. This -allows you to make up compound values (for example directory paths) that use -more than one default value. It also means it's possible to create circular -references. If there are any circular references which would cause an infinite -interpolation loop, an InterpolationLoopError is raised.

-

Both of these errors are subclasses of InterpolationError, which is a -subclass of ConfigObjError.

-

String interpolation and validation don't play well together. This is because -validation overwrites values - and so may erase the interpolation references. -See Validation and Interpolation. (This can only happen if validation -has to change the value).

-

New in ConfigObj 4.7.0: String interpolation is now done in members of list -values.

-
-

12.1   String Interpolation and List Values

-

Since version 4.7 string interpolation is done on string members of list values. -If interpolation changes any members of the list then what you get back is a -copy of the list rather than the original list.

-

This makes fetching list values slightly slower when interpolation is on, it -also means that if you mutate the list changes won't be reflected in the -original list:

-
>>> c = ConfigObj()
->>> c['foo'] = 'boo'
->>> c['bar'] = ['%(foo)s']
->>> c['bar']
-['boo']
->>> c['bar'].append('fish')
->>> c['bar']
-['boo']
-
-

Instead of mutating the list you must create a new list and reassign it.

-
-
-
-

13   Comments

-

Any line that starts with a '#', possibly preceded by whitespace, is a comment.

-

If a config file starts with comments then these are preserved as the -initial_comment.

-

If a config file ends with comments then these are preserved as the -final_comment.

-

Every key or section marker may have lines of comments immediately above it. -These are saved as the comments attribute of the section. Each member is a -list of lines.

-

You can also have a comment inline with a value. These are saved as the -inline_comments attribute of the section, with one entry per member of the -section.

-

Subsections (section markers in the config file) can also have comments.

-

See Section Attributes for more on these attributes.

-

These comments are all written back out by the write method.

-
-
-

14   flatten_errors

-
flatten_errors(cfg, res)
-
-

Validation is a powerful way of checking that the values supplied by the user -make sense.

-

The validate method returns a results dictionary that represents pass or fail -for each value. This doesn't give you any information about why the check -failed.

-

flatten_errors is an example function that turns a results dictionary into -a flat list, that only contains values that failed.

-

cfg is the ConfigObj instance being checked, res is the results -dictionary returned by validate.

-

It returns a list of keys that failed. Each member of the list is a tuple:

-
-([list of sections...], key, result)
-
-

If validate was called with preserve_errors=False (the default) -then result will always be False.

-

list of sections is a flattened list of sections that the key was found -in.

-

If the section was missing then key will be None.

-

If the value (or section) was missing then result will be False.

-

If validate was called with preserve_errors=True and a value -was present, but failed the check, then result will be the exception -object returned. You can use this as a string that describes the failure.

-

For example :

-
-The value "3" is of the wrong type.
-
-

14.1   Example Usage

-

The output from flatten_errors is a list of tuples.

-

Here is an example of how you could present this information to the user.

-
vtor = validate.Validator()
-# ini is your config file - cs is the configspec
-cfg = ConfigObj(ini, configspec=cs)
-res = cfg.validate(vtor, preserve_errors=True)
-for entry in flatten_errors(cfg, res):
-    # each entry is a tuple
-    section_list, key, error = entry
-    if key is not None:
-       section_list.append(key)
-    else:
-        section_list.append('[missing section]')
-    section_string = ', '.join(section_list)
-    if error == False:
-        error = 'Missing value or section.'
-    print section_string, ' = ', error
-
-
-
-
-

15   get_extra_values

-
get_extra_values(conf)
-
-

New in ConfigObj 4.7.0.

-

Find all the values and sections not in the configspec from a validated -ConfigObj.

-

get_extra_values returns a list of tuples where each tuple represents -either an extra section, or an extra value.

-

The tuples contain two values, a tuple representing the section the value -is in and the name of the extra values. For extra values in the top level -section the first member will be an empty tuple. For values in the 'foo' -section the first member will be ('foo',). For members in the 'bar' -subsection of the 'foo' section the first member will be ('foo', 'bar').

-

Extra sections will only have one entry. Values and subsections inside -an extra section aren't listed separately.

-

NOTE: If you call get_extra_values on a ConfigObj instance that hasn't -been validated it will return an empty list.

-
-

15.1   Example Usage

-

The output from get_extra_values is a list of tuples.

-

Here is an example of how you could present this information to the user.

-
vtor = validate.Validator()
-# ini is your config file - cs is the configspec
-cfg = ConfigObj(ini, configspec=cs)
-cfg.validate(vtor, preserve_errors=True)
-
-for sections, name in get_extra_values(cfg):
-
-    # this code gets the extra values themselves
-    the_section = cfg
-    for section in sections:
-        the_section = cfg[section]
-
-    # the_value may be a section or a value
-    the_value = the_section[name]
-
-    section_or_value = 'value
-    if isinstance(the_value, dict):
-        # Sections are subclasses of dict
-        section_or_value = 'section'
-
-    section_string = ', '.join(sections) or "top level"
-    print 'Extra entry in section: %s. Entry %r is a %s' % (section_string, name, section_or_value)
-
-
-
-
-

16   CREDITS

-

ConfigObj 4 is written by (and copyright) Michael Foord and -Nicola Larosa.

-

Particularly thanks to Nicola Larosa for help on the config file spec, the -validation system and the doctests.

-

validate.py was originally written by Michael Foord and Mark Andrews.

-

Thanks to many others for input, patches and bugfixes.

-
-
-

17   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 us if it eats your data ! -Of course if it does, let us know and we'll fix the problem so it doesn't -happen to anyone else:

-
-Copyright (c) 2004 - 2010, Michael Foord & Nicola Larosa
-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 Nicola Larosa
-      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

-
-
-

18   TODO

-

Better support for configuration from multiple files, including tracking -where the original file came from and writing changes to the correct -file.

-

Make newline a keyword argument (as well as an attribute) ?

-

UTF16 encoded files, when returned as a list of lines, will have the -BOM at the start of every line. Should this be removed from all but the -first line ?

-

Option to set warning type for unicode decode ? (Defaults to strict).

-

A method to optionally remove uniform indentation from multiline values. -(do as an example of using walk - along with string-escape)

-

Should the results dictionary from validate be an ordered dictionary if -odict is available ?

-

Implement some of the sequence methods (which include slicing) from the -newer odict ?

-

Preserve line numbers of values (and possibly the original text of each value).

-
-
-

19   ISSUES

-
-

Note

-

Please file any bug reports to Michael Foord or the ConfigObj -Mailing List.

-
-

There is currently no way to specify the encoding of a configspec file.

-

As a consequence of the changes to configspec handling in version 4.6.0, when -you create a ConfigObj instance and provide a configspec, the configspec -attribute is only set on the ConfigObj instance - it isn't set on the sections until you validate. You also can't set the configspec attribute to be a dictionary. This wasn't documented but did work previously.

-

In order to fix the problem with hashes in configspecs I had to turn off the parsing of inline comments in configspecs. This will only affect you if you are using copy=True when validating and expecting inline comments to be copied from the configspec into the ConfigObj instance (all other comments will be copied as usual).

-

If you create the configspec by passing in a ConfigObj instance (usual way is to pass in a filename or list of lines) then you should pass in _inspec=True to the constructor to allow hashes in values. This is the magic that switches off inline comment parsing.

-

When using copy mode for validation, it won't copy DEFAULT -sections. This is so that you can use interpolation in configspec -files. This is probably true even if interpolation is off in the -configspec.

-

You can't have a keyword with the same name as a section (in the same -section). They are both dictionary keys - so they would overlap.

-

ConfigObj doesn't quote and unquote values if list_values=False. -This means that leading or trailing whitespace in values will be lost when -writing. (Unless you manually quote).

-

Interpolation checks first the current section, then the 'DEFAULT' subsection -of the current section, before moving on to the current section's parent and -so on up the tree.

-

Does it matter that we don't support the ':' divider, which is supported -by ConfigParser ?

-

String interpolation and validation don't play well together. When -validation changes type it sets the value. This will correctly fetch the -value using interpolation - but then overwrite the interpolation reference. -If the value is unchanged by validation (it's a string) - but other types -will be.

-
-
-

20   CHANGELOG

-

This is an abbreviated changelog showing the major releases up to version 4. -From version 4 it lists all releases and changes.

-
-

20.1   2010/02/27 - Version 4.7.2

-
    -
  • BUGFIX: Restore Python 2.3 compatibility
  • -
  • BUGFIX: Members that were lists were being returned as copies due to interpolation -introduced in 4.7. Lists are now only copies if interpolation changes a list -member.
  • -
  • BUGFIX: pop now does interpolation in list values as well.
  • -
  • BUGFIX: where interpolation matches a section name rather than a value it is -ignored instead of raising an exception on fetching the item.
  • -
  • BUGFIX: values that use interpolation to reference members that don't exist can -now be repr'd.
  • -
  • BUGFIX: Fix to avoid writing '\r\r\n' on Windows when given a file opened in -text write mode ('w').
  • -
-

See String Interpolation and List Values for information about the problem with lists and interpolation.

-
-
-

20.2   2010/02/06 - Version 4.7.1

-
    -
  • Fix bug in options deprecation warning added in 4.7.0
  • -
-
-
-

20.3   2010/01/09 - Version 4.7.0

-
    -
  • Minimum supported version of Python is now 2.3
  • -
  • ~25% performance improvement thanks to Christian Heimes
  • -
  • String interpolation now works in list value members
  • -
  • After validation any additional entries not in the configspec are listed in -the extra_values section member
  • -
  • Addition of the get_extra_values function for finding all extra values -in a validated ConfigObj instance
  • -
  • Deprecated the use of the options dictionary in the ConfigObj constructor -and added explicit keyword arguments instead. Use **options if you want -to initialise a ConfigObj instance from a dictionary
  • -
  • Constructing a ConfigObj from an existing ConfigObj instance now preserves -the order of values and sections from the original instance in the new one
  • -
  • BUGFIX: Checks that failed validation would not populate default_values and -restore_default_value() wouldn't work for those entries
  • -
  • BUGFIX: clear() now clears 'defaults'
  • -
  • BUGFIX: empty values in list values were accidentally valid syntax. They now -raise a ParseError. e.g. "value = 1, , 2"
  • -
  • BUGFIX: Change to the result of a call to validate when preserve_errors -is True. Previously sections where all values failed validation would -return False for the section rather than preserving the errors. False will -now only be returned for a section if it is missing
  • -
  • Distribution includes version 1.0.1 of validate.py
  • -
  • Removed __revision__ and __docformat__
  • -
-
-
-

20.4   2009/04/13 - Version 4.6.0

-
    -
  • Pickling of ConfigObj instances now supported (thanks to Christian Heimes)
  • -
  • Hashes in confgspecs are now allowed (see note below)
  • -
  • Replaced use of hasattr (which can swallow exceptions) with getattr
  • -
  • __many__ in configspecs can refer to scalars (ordinary values) as well as sections
  • -
  • You can use ___many___ (three underscores!) where you want to use __many__ as well
  • -
  • You can now have normal sections inside configspec sections that use __many__
  • -
  • You can now create an empty ConfigObj with a configspec, programmatically set values and then validate
  • -
  • A section that was supplied as a value (or vice-versa) in the actual config file would cause an exception during validation (the config file is still broken of course, but it is now handled gracefully)
  • -
  • Added as_list method
  • -
  • Removed the deprecated istrue, encode and decode methods
  • -
  • Running test_configobj.py now also runs the doctests in the configobj module
  • -
-

As a consequence of the changes to configspec handling, when you create a ConfigObj instance and provide -a configspec, the configspec attribute is only set on the ConfigObj instance - it isn't set on the -sections until you validate. You also can't set the configspec attribute to be a dictionary. This wasn't -documented but did work previously.

-

In order to fix the problem with hashes in configspecs I had to turn off the parsing of inline comments -in configspecs. This will only affect you if you are using copy=True when validating and expecting -inline comments to be copied from the configspec into the ConfigObj instance (all other comments will be -copied as usual).

-

If you create the configspec by passing in a ConfigObj instance (usual way is to pass in a filename or -list of lines) then you should pass in _inspec=True to the constructor to allow hashes in values. -This is the magic that switches off inline comment parsing.

-
-
-

20.5   2008/06/27 - Version 4.5.3

-

BUGFIX: fixed a problem with copy=True when validating with configspecs that use -__many__ sections.

-
-
-

20.6   2008/02/05 - Version 4.5.2

-

Distribution updated to include version 0.3.2 of validate. This means that -None as a default value in configspecs works.

-
-
-

20.7   2008/02/05 - Version 4.5.1

-

Distribution updated to include version 0.3.1 of validate. This means that -Unicode configspecs now work.

-
-
-

20.8   2008/02/05 - Version 4.5.0

-

ConfigObj will now guarantee that files will be written terminated with a -newline.

-

ConfigObj will no longer attempt to import the validate module, until/unless -you call ConfigObj.validate with preserve_errors=True. This makes it -faster to import.

-

New methods restore_default and restore_defaults. restore_default -resets an entry to its default value (and returns that value). restore_defaults -resets all entries to their default value. It doesn't modify entries without a -default value. You must have validated a ConfigObj (which populates the -default_values dictionary) before calling these methods.

-

BUGFIX: Proper quoting of keys, values and list values that contain hashes -(when writing). When list_values=False, values containing hashes are -triple quoted.

-

Added the reload method. This reloads a ConfigObj from file. If the filename -attribute is not set then a ReloadError (a new exception inheriting from -IOError) is raised.

-

BUGFIX: Files are read in with 'rb' mode, so that native/non-native line endings work!

-

Minor efficiency improvement in unrepr mode.

-

Added missing docstrings for some overidden dictionary methods.

-

Added the reset method. This restores a ConfigObj to a freshly created state.

-

Removed old CHANGELOG file.

-
-
-

20.9   2007/02/04 - Version 4.4.0

-

Official release of 4.4.0

-
-
-

20.10   2006/12/17 - Version 4.3.3-alpha4

-

By Nicola Larosa

-

Allowed arbitrary indentation in the indent_type parameter, removed the -NUM_INDENT_SPACES and MAX_INTERPOL_DEPTH (a leftover) constants, -added indentation tests (including another docutils workaround, sigh), updated -the documentation.

-

By Michael Foord

-

Made the import of compiler conditional so that ConfigObj can be used -with IronPython.

-
-
-

20.11   2006/12/17 - Version 4.3.3-alpha3

-

By Nicola Larosa

-

Added a missing self. in the _handle_comment method and a related test, -per Sourceforge bug #1523975.

-
-
-

20.12   2006/12/09 - Version 4.3.3-alpha2

-

By Nicola Larosa

-

Changed interpolation search strategy, based on this patch by Robin Munn: -http://sourceforge.net/mailarchive/message.php?msg_id=17125993

-
-
-

20.13   2006/12/09 - Version 4.3.3-alpha1

-

By Nicola Larosa

-

Added Template-style interpolation, with tests, based on this patch by -Robin Munn: http://sourceforge.net/mailarchive/message.php?msg_id=17125991 -(awful archives, bad Sourceforge, bad).

-
-
-

20.14   2006/06/04 - Version 4.3.2

-

Changed error handling, if parsing finds a single error then that error will -be re-raised. That error will still have an errors and a config -attribute.

-

Fixed bug where '\n' terminated files could be truncated.

-

Bugfix in unrepr mode, it couldn't handle '#' in values. (Thanks to -Philippe Normand for the report.)

-

As a consequence of this fix, ConfigObj doesn't now keep inline comments in -unrepr mode. This is because the parser in the compiler package -doesn't keep comments.

-

Error messages are now more useful. They tell you the number of parsing errors -and the line number of the first error. (In the case of multiple errors.)

-

Line numbers in exceptions now start at 1, not 0.

-

Errors in unrepr mode are now handled the same way as in the normal mode. -The errors stored will be an UnreprError.

-
-
-

20.15   2006/04/29 - Version 4.3.1

-

Added validate.py back into configobj.zip. (Thanks to Stewart -Midwinter)

-

Updated to validate.py 0.2.2.

-

Preserve tuples when calling the dict method. (Thanks to Gustavo Niemeyer.)

-

Changed __repr__ to return a string that contains ConfigObj({ ... }).

-

Change so that an options dictionary isn't modified by passing it to ConfigObj. -(Thanks to Artarious.)

-

Added ability to handle negative integers in unrepr. (Thanks to Kevin -Dangoor.)

-
-
-

20.16   2006/03/24 - Version 4.3.0

-

Moved the tests and the CHANGELOG (etc) into a separate file. This has reduced -the size of configobj.py by about 40%.

-

Added the unrepr mode to reading and writing config files. Thanks to Kevin -Dangoor for this suggestion.

-

Empty values are now valid syntax. They are read as an empty string ''. -(key =, or key = # comment.)

-

validate now honours the order of the configspec.

-

Added the copy mode to validate. Thanks to Louis Cordier for this -suggestion.

-

Fixed bug where files written on windows could be given '\r\r\n' line -terminators.

-

Fixed bug where last occurring comment line could be interpreted as the -final comment if the last line isn't terminated.

-

Fixed bug where nested list values would be flattened when write is -called. Now sub-lists have a string representation written instead.

-

Deprecated encode and decode methods instead.

-

You can now pass in a ConfigObj instance as a configspec (remember to read -the configspec file using list_values=False).

-

Sorted footnotes in the docs.

-
-
-

20.17   2006/02/16 - Version 4.2.0

-

Removed BOM_UTF8 from __all__.

-

The BOM attribute has become a boolean. (Defaults to False.) It is -only True for the UTF16/UTF8 encodings.

-

File like objects no longer need a seek attribute.

-

Full unicode support added. New options/attributes encoding, -default_encoding.

-

ConfigObj no longer keeps a reference to file like objects. Instead the -write method takes a file like object as an optional argument. (Which -will be used in preference of the filename attribute if that exists as -well.)

-

utf16 files decoded to unicode.

-

If BOM is True, but no encoding specified, then the utf8 BOM is -written out at the start of the file. (It will normally only be True if -the utf8 BOM was found when the file was read.)

-

Thanks to Aaron Bentley for help and testing on the unicode issues.

-

File paths are not converted to absolute paths, relative paths will -remain relative as the filename attribute.

-

Fixed bug where final_comment wasn't returned if write is returning -a list of lines.

-

Deprecated istrue, replaced it with as_bool.

-

Added as_int and as_float.

-
-
-

20.18   2005/12/14 - Version 4.1.0

-

Added merge, a recursive update.

-

Added preserve_errors to validate and the flatten_errors -example function.

-

Thanks to Matthew Brett for suggestions and helping me iron out bugs.

-

Fixed bug where a config file is all comment, the comment will now be -initial_comment rather than final_comment.

-

Validation no longer done on the 'DEFAULT' section (only in the root level). -This allows interpolation in configspecs.

-

Also use the new list syntax in validate 0.2.1. (For configspecs).

-
-
-

20.19   2005/12/02 - Version 4.0.2

-

Fixed bug in create_empty. Thanks to Paul Jimenez for the report.

-
-
-

20.20   2005/11/05 - Version 4.0.1

-

Fixed bug in Section.walk when transforming names as well as values.

-

Added the istrue method. (Fetches the boolean equivalent of a string -value).

-

Fixed list_values=False - they are now only quoted/unquoted if they -are multiline values.

-

List values are written as item, item rather than item,item.

-
-
-

20.21   2005/10/17 - Version 4.0.0

-

ConfigObj 4.0.0 Final

-

Fixed bug in setdefault. When creating a new section with setdefault the -reference returned would be to the dictionary passed in not to the new -section. Bug fixed and behaviour documented.

-

Obscure typo/bug fixed in write. Wouldn't have affected anyone though.

-
-
-

20.22   2005/09/09 - Version 4.0.0 beta 5

-

Removed PositionError.

-

Allowed quotes around keys as documented.

-

Fixed bug with commas in comments. (matched as a list value)

-
-
-

20.23   2005/09/07 - Version 4.0.0 beta 4

-

Fixed bug in __delitem__. Deleting an item no longer deletes the -inline_comments attribute.

-

Fixed bug in initialising ConfigObj from a ConfigObj.

-

Changed the mailing list address.

-
-
-

20.24   2005/08/28 - Version 4.0.0 beta 3

-

Interpolation is switched off before writing out files.

-

Fixed bug in handling StringIO instances. (Thanks to report from -Gustavo Niemeyer.)

-

Moved the doctests from the __init__ method to a separate function. -(For the sake of IDE calltips).

-
-
-

20.25   2005/08/25 - Version 4.0.0 beta 2

-

Amendments to validate.py.

-

First public release.

-
-
-

20.26   2005/08/21 - Version 4.0.0 beta 1

-

Reads nested subsections to any depth.

-

Multiline values.

-

Simplified options and methods.

-

New list syntax.

-

Faster, smaller, and better parser.

-

Validation greatly improved. Includes:

-
-
    -
  • type conversion
  • -
  • default values
  • -
  • repeated sections
  • -
-
-

Improved error handling.

-

Plus lots of other improvements.

-
-
-

20.27   2004/05/24 - Version 3.0.0

-

Several incompatible changes: another major overhaul and change. (Lots 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 stdout was removed.

-

A few new methods added.

-

Charmap is now incorporated into ConfigObj.

-
-
-

20.28   2004/03/14 - 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.

-
-
-

20.29   2004/01/29 - 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.

-
-
-

20.30   Origins

-

ConfigObj originated in a set of functions for reading config files in the -atlantibots project. The original -functions were written by Rob McNeur.

-
-
-
-
-

21   Footnotes

- - - - - -
[1]And if you discover any bugs, let us know. We'll fix them quickly.
- - - - - -
[2]If you specify a filename that doesn't exist, ConfigObj will assume you -are creating a new one. See the create_empty and file_error options.
- - - - - -
[3]They can be byte strings (ordinary strings) or Unicode.
- - - - - -
[4]Except we don't support the RFC822 style line continuations, nor ':' as -a divider.
- - - - - -
[5]This is a change in ConfigObj 4.2.0. Note that ConfigObj doesn't call -the seek method of any file like object you pass in. You may want to call -file_object.seek(0) yourself, first.
- - - - - -
[6]

A side effect of this is that it enables you to copy a ConfigObj :

-
# only copies members
-# not attributes/comments
-config2 = ConfigObj(config1)
-
-

Since ConfigObj 4.7.0 the order of members and sections will be -preserved when copying a ConfigObj instance.

-
- - - - - -
[7]Other than lists of strings.
- - - - - -
[8]The exception is if it detects a UTF16 encoded file which it -must decode before parsing.
- - - - - -
[9]The method signature shows that this method takes -two arguments. The second is the section to be written. This is because the -write method is called recursively.
- - - - - -
[10]The dict method doesn't actually use the deepcopy mechanism. This means -if you add nested lists (etc) to your ConfigObj, then the dictionary -returned by dict may contain some references. For all normal ConfigObjs -it will return a deepcopy.
- - - - - -
[11]Passing (section, key) rather than (value, key) allows you to -change the value by setting section[key] = newval. It also gives you -access to the rename method of the section.
- - - - - -
[12]Minimum required version of validate.py 0.2.0 .
-
-
- - diff --git a/docs/configobj.rst b/docs/configobj.rst index c4bbc18..66005d3 100644 --- a/docs/configobj.rst +++ b/docs/configobj.rst @@ -8,8 +8,8 @@ ---------------------------------------- :Authors: Michael Foord, Nicola Larosa, Rob Dennis, Eli Courtwright -:Version: ConfigObj 5.0.6 -:Date: 2014/08/25 +:Version: ConfigObj 5.0.7 +:Date: 2023/01/17 :PyPI Entry: `ConfigObj on PyPI `_ :Homepage: `Github Page`_ :License: `BSD License`_ @@ -32,7 +32,7 @@ The best introduction to working with ConfigObj, including the powerful configuration validation system, is the article: - * `An Introduction to ConfigObj `_ + * `An Introduction to ConfigObj `_ Introduction @@ -64,7 +64,7 @@ For support and bug reports please use the ConfigObj `Github Page`_. Downloading =========== -The current version is **5.0.6**, dated 25th August 2014. ConfigObj 5 is +The current version is **5.0.7**, dated January 2023. ConfigObj 5 is stable and mature. We still expect to pick up a few bugs along the way though, particularly with respect to Python 3 compatibility [#]_. We recommend downloading and installing using pip: @@ -2271,7 +2271,7 @@ free software: test it, break it, just don't blame us if it eats your data ! Of course if it does, let us know and we'll fix the problem so it doesn't happen to anyone else:: - Copyright (C) 2005-2014: + Copyright (C) 2003-2023: (name) : (email) Michael Foord: fuzzyman AT voidspace DOT org DOT uk Nicola Larosa: nico AT tekNico DOT net @@ -2383,6 +2383,12 @@ CHANGELOG This is an abbreviated changelog showing the major releases up to version 4. From version 4 it lists all releases and changes. +2023/01/17 - Version 5.0.7 +-------------------------- + +* Update documentation to remove some dead links +* Update unit tests to go against updated versions of Python + 2014/08/25 - Version 5.0.6 -------------------------- * BUGFIX: Did not correctly handle %-chars in invalid lines diff --git a/docs/validate.html b/docs/validate.html deleted file mode 100644 index f514475..0000000 --- a/docs/validate.html +++ /dev/null @@ -1,639 +0,0 @@ - - - - - - -Validation Schema with validate.py - - - - - -
-

Validation Schema with validate.py

-

Using the Validator class

- --- - - - - - - - - - - - - - - - - - -
Authors:Michael Foord -
Nicola Larosa -
Mark Andrews
Version:Validate 1.0.1
Date:2010/01/09
Homepage:Validate Homepage
Repository:Google code homepage
PyPI Entry:Validate on Python Packaging Index
License:BSD License
Support:Mailing List
- -
-

1   Introduction

-

Validation is used to check that supplied values conform to a specification.

-

The value can be supplied as a string, e.g. from a config file. In this case -the check will also convert the value to the required type. This allows you -to add validation as a transparent layer to access data stored as strings. The -validation checks that the data is correct and converts it to the expected -type.

-

Checks are also strings, and are easy to write. One generic system can be used -to validate information from different sources via a single consistent -mechanism.

-

Checks look like function calls, and map to function calls. They can include -parameters and keyword arguments. These arguments are passed to the relevant -function by the Validator instance, along with the value being checked.

-

The syntax for checks also allows for specifying a default value. This default -value can be None, no matter what the type of the check. This can be used -to indicate that a value was missing, and so holds no useful value.

-

Functions either return a new value, or raise an exception. See Validator -Exceptions for the low down on the exception classes that validate.py -defines.

-

Some standard functions are provided, for basic data types; these come built -into every validator. Additional checks are easy to write: they can be provided -when the Validator is instantiated, or added afterwards.

-

Validate was primarily written to support ConfigObj, but is designed to be -applicable to many other situations.

-

For support and bug reports please use the ConfigObj Mailing List.

-
-
-

2   Downloading

-

The current version is 1.0.1, dated 9th January 2010.

-

You can get obtain validate in the following ways :

-
-

2.1   Files

-
    -
  • validate.py from Voidspace

    -
  • -
  • configobj.zip from Voidspace - See the homepage of ConfigObj for the latest -version and download links.

    -
    -

    This contains validate.py and this document. (As well as ConfigObj and -the ConfigObj documentation).

    -
    -
  • -
  • The latest development version can be obtained from the Subversion Repository.

    -
  • -
-
-
-

2.2   Documentation

-

configobj.zip contains this document.

- -
-
-
-

3   The standard functions

-

The standard functions come built-in to every Validator instance. They work -with the following basic data types :

-
    -
  • integer
  • -
  • float
  • -
  • boolean
  • -
  • string
  • -
  • ip_addr
  • -
-

plus lists of these datatypes.

-

Adding additional checks is done through coding simple functions.

-

The full set of standard checks are :

- --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'integer':

matches integer values (including negative). Takes optional 'min' -and 'max' arguments:

-
-integer()
-integer(3, 9)    # any value from 3 to 9
-integer(min=0) # any positive value
-integer(max=9)
-
-
'float':

matches float values -Has the same parameters as the integer check.

-
'boolean':
-
matches boolean values: True or False.
-

Acceptable string values for True are:

-
-true, on, yes, 1
-
-
-
-

Acceptable string values for False are:

-
-false, off, no, 0
-
-

Any other value raises an error.

-
'string':

matches any string. Takes optional keyword args 'min' and 'max' to -specify min and max length of string.

-
'ip_addr':

matches an Internet Protocol address, v.4, represented by a -dotted-quad string, i.e. '1.2.3.4'.

-
'list':

matches any list. Takes optional keyword args 'min', and 'max' to -specify min and max sizes of the list. The list checks always -return a list.

-
force_list:

matches any list, but if a single value is passed in will -coerce it into a list containing that value. Useful for -configobj if the user forgot the trailing comma to turn -a single value into a list.

-
'tuple':

matches any list. This check returns a tuple rather than a list.

-
'int_list':

Matches a list of integers. Takes the same arguments as list.

-
'float_list':

Matches a list of floats. Takes the same arguments as list.

-
'bool_list':

Matches a list of boolean values. Takes the same arguments as -list.

-
'string_list':

Matches a list of strings. Takes the same arguments as list.

-
'ip_addr_list':

Matches a list of IP addresses. Takes the same arguments as -list.

-
'mixed_list':

Matches a list with different types in specific positions. -List size must match the number of arguments.

-

Each position can be one of:

-
-int, str, boolean, float, ip_addr
-
-

So to specify a list with two strings followed by two integers, -you write the check as:

-
-mixed_list(str, str, int, int)
-
-
'pass':

matches everything: it never fails and the value is unchanged. It is -also the default if no check is specified.

-
'option':

matches any from a list of options. -You specify this test with:

-
-option('option 1', 'option 2', 'option 3')
-
-
-

The following code will work without you having to specifically add the -functions yourself.

-
from validate import Validator
-#
-vtor = Validator()
-newval1 = vtor.check('integer', value1)
-newval2 = vtor.check('boolean', value2)
-# etc ...
-
-
-

Note

-

Of course, if these checks fail they raise exceptions. So you should wrap -them in try...except blocks. Better still, use ConfigObj for a higher -level interface.

-
-
-
-

4   Using Validator

-

Using Validator is very easy. It has one public attribute and one public -method.

-

Shown below are the different steps in using Validator.

-

The only additional thing you need to know, is about Writing check -functions.

-
-

4.1   Instantiate

-
from validate import Validator
-vtor = Validator()
-
-

or even :

-
from validate import Validator
-#
-fdict = {
-    'check_name1': function1,
-    'check_name2': function2,
-    'check_name3': function3,
-}
-#
-vtor = Validator(fdict)
-
-

The second method adds a set of your functions as soon as your validator is -created. They are stored in the vtor.functions dictionary. The 'key' you -give them in this dictionary is the name you use in your checks (not the -original function name).

-

Dictionary keys/functions you pass in can override the built-in ones if you -want.

-
-
-

4.2   Adding functions

-

The code shown above, for adding functions on instantiation, has exactly the -same effect as the following code :

-
from validate import Validator
-#
-vtor = Validator()
-vtor.functions['check_name1'] = function1
-vtor.functions['check_name2'] = function2
-vtor.functions['check_name3'] = function3
-
-

vtor.functions is just a dictionary that maps names to functions, so we -could also have called vtor.functions.update(fdict).

-
-
-

4.3   Writing the check

-

As we've heard, the checks map to the names in the functions dictionary. -You've got a full list of The standard functions and the arguments they -take.

-

If you're using Validator from ConfigObj, then your checks will look like:

-
-keyword = int_list(max=6)
-
-

but the check part will be identical .

-
-
-

4.4   The check method

-

If you're not using Validator from ConfigObj, then you'll need to call the -check method yourself.

-

If the check fails then it will raise an exception, so you'll want to trap -that. Here's the basic example :

-
from validate import Validator, ValidateError
-#
-vtor = Validator()
-check = "integer(0, 9)"
-value = 3
-try:
-    newvalue = vtor.check(check, value)
-except ValidateError:
-    print 'Check Failed.'
-else:
-    print 'Check passed.'
-
-
-

Caution!

-

Although the value can be a string, if it represents a list it should -already have been turned into a list of strings.

-
-
-

4.4.1   Default Values

-

Some values may not be available, and you may want to be able to specify a -default as part of the check.

-

You do this by passing the keyword missing=True to the check method, as -well as a default=value in the check. (Constructing these checks is done -automatically by ConfigObj: you only need to know about the default=value -part) :

-
check1 = 'integer(default=50)'
-check2 = 'option("val 1", "val 2", "val 3", default="val 1")'
-
-assert vtor.check(check1, '', missing=True) == 50
-assert vtor.check(check2, '', missing=True) == "val 1"
-
-

If you pass in missing=True to the check method, then the actual value is -ignored. If no default is specified in the check, a ValidateMissingValue -exception is raised. If a default is specified then that is passed to the -check instead.

-

If the check has default=None (case sensitive) then vtor.check will -always return None (the object). This makes it easy to tell your program -that this check contains no useful value when missing, i.e. the value is -optional, and may be omitted without harm.

-
-

Note

-

As of version 0.3.0, if you specify default='None' (note the quote marks -around None) then it will be interpreted as the string 'None'.

-
-
-
-

4.4.2   List Values

-

It's possible that you would like your default value to be a list. It's even -possible that you will write your own check functions - and would like to pass -them keyword arguments as lists from within the check.

-

To avoid confusing syntax with commas and quotes you use a list constructor to -specify that keyword arguments are lists. This includes the default value. -This makes checks look something like:

-
-checkname(default=list('val1', 'val2', 'val3'))
-
-
-
-
-

4.5   get_default_value

-

Validator instances have a get_default_value method. It takes a check string -(the same string you would pass to the check method) and returns the default value, -converted to the right type. If the check doesn't define a default value then this method -raises a KeyError.

-

If the check has been seen before then it will have been parsed and cached already, -so this method is not expensive to call (however the conversion is done each time).

-
-
-
-

5   Validator Exceptions

-
-

Note

-

If you only use Validator through ConfigObj, it traps these Exceptions for -you. You will still need to know about them for writing your own check -functions.

-
-

vtor.check indicates that the check has failed by raising an exception. -The appropriate error should be raised in the check function.

-

The base error class is ValidateError. All errors (except for VdtParamError) -raised are sub-classes of this.

-

If an unrecognised check is specified then VdtUnknownCheckError is -raised.

-

There are also VdtTypeError and VdtValueError.

-

If incorrect parameters are passed to a check function then it will (or should) -raise VdtParamError. As this indicates programmer error, rather than an error -in the value, it is a subclass of SyntaxError instead of ValidateError.

-
-

Note

-

This means it won't be caught by ConfigObj - but propagated instead.

-
-

If the value supplied is the wrong type, then the check should raise -VdtTypeError. e.g. the check requires the value to be an integer (or -representation of an integer) and something else was supplied.

-

If the value supplied is the right type, but an unacceptable value, then the -check should raise VdtValueError. e.g. the check requires the value to -be an integer (or representation of an integer) less than ten and a higher -value was supplied.

-

Both VdtTypeError and VdtValueError are initialised with the -incorrect value. In other words you raise them like this :

-
raise VdtTypeError(value)
-#
-raise VdtValueError(value)
-
-

VdtValueError has the following subclasses, which should be raised if -they are more appropriate.

-
    -
  • VdtValueTooSmallError
  • -
  • VdtValueTooBigError
  • -
  • VdtValueTooShortError
  • -
  • VdtValueTooLongError
  • -
-
-
-

6   Writing check functions

-

Writing check functions is easy.

-

The check function will receive the value as its first argument, followed by -any other parameters and keyword arguments.

-

If the check fails, it should raise a VdtTypeError or a -VdtValueError (or an appropriate subclass).

-

All parameters and keyword arguments are always passed as strings. (Parsed -from the check string).

-

The value might be a string (or list of strings) and need -converting to the right type - alternatively it might already be a list of -integers. Our function needs to be able to handle either.

-

If the check passes then it should return the value (possibly converted to the -right type).

-

And that's it !

-
-

6.1   Example

-

Here is an example function that requires a list of integers. Each integer -must be between 0 and 99.

-

It takes a single argument specifying the length of the list. (Which allows us -to use the same check in more than one place). If the length can't be converted -to an integer then we need to raise VdtParamError.

-

Next we check that the value is a list. Anything else should raise a -VdtTypeError. The list should also have 'length' entries. If the list -has more or less entries then we will need to raise a -VdtValueTooShortError or a VdtValueTooLongError.

-

Then we need to check every entry in the list. Each entry should be an integer -between 0 and 99, or a string representation of an integer between 0 and 99. -Any other type is a VdtTypeError, any other value is a -VdtValueError (either too big, or too small).

-
def special_list(value, length):
-    """
-    Check that the supplied value is a list of integers,
-    with 'length' entries, and each entry between 0 and 99.
-    """
-    # length is supplied as a string
-    # we need to convert it to an integer
-    try:
-        length = int(length)
-    except ValueError:
-        raise VdtParamError('length', length)
-    #
-    # Check the supplied value is a list
-    if not isinstance(value, list):
-        raise VdtTypeError(value)
-    #
-    # check the length of the list is correct
-    if len(value) > length:
-        raise VdtValueTooLongError(value)
-    elif len(value) < length:
-        raise VdtValueTooShortError(value)
-    #
-    # Next, check every member in the list
-    # converting strings as necessary
-    out = []
-    for entry in value:
-        if not isinstance(entry, (str, unicode, int)):
-            # a value in the list
-            # is neither an integer nor a string
-            raise VdtTypeError(value)
-        elif isinstance(entry, (str, unicode)):
-            if not entry.isdigit():
-                raise VdtTypeError(value)
-            else:
-                entry = int(entry)
-        if entry < 0:
-            raise VdtValueTooSmallError(value)
-        elif entry > 99:
-            raise VdtValueTooBigError(value)
-        out.append(entry)
-    #
-    # if we got this far, all is well
-    # return the new list
-    return out
-
-

If you are only using validate from ConfigObj then the error type (TooBig, -TooSmall, etc) is lost - so you may only want to raise VdtValueError.

-
-

Caution!

-

If your function raises an exception that isn't a subclass of -ValidateError, then ConfigObj won't trap it. This means validation will -fail.

-

This is why our function starts by checking the type of the value. If we -are passed the wrong type (e.g. an integer rather than a list) we get a -VdtTypeError rather than bombing out when we try to iterate over -the value.

-
-

If you are using validate in another circumstance you may want to create your -own subclasses of ValidateError which convey more specific information.

-
-
-
-

7   Known Issues

-

The following parses and then blows up. The resulting error message -is confusing:

-
-checkname(default=list(1, 2, 3, 4)
-

This is because it parses as: checkname(default="list(1", 2, 3, 4). -That isn't actually unreasonable, but the error message won't help you -work out what has happened.

-
-
-

8   TODO

-
    -
  • A regex check function ?
  • -
  • A timestamp check function ? (Using the parse function from DateUtil perhaps).
  • -
-
-
-

9   ISSUES

-
-

Note

-

Please file any bug reports to Michael Foord or the ConfigObj -Mailing List.

-
-

If we could pull tuples out of arguments, it would be easier -to specify arguments for 'mixed_lists'.

-
-
-

10   CHANGELOG

-
-

10.1   2009/10/25 - Version 1.0.1

-
    -
  • BUGFIX: Fixed compatibility with Python 2.3.
  • -
-
-
-

10.2   2009/04/13 - Version 1.0.0

-
    -
  • BUGFIX: can now handle multiline strings.
  • -
  • Addition of 'force_list' validation option.
  • -
-

As the API is stable and there are no known bugs or outstanding feature requests I am marking this 1.0.

-
-
-

10.3   2008/02/24 - Version 0.3.2

-

BUGFIX: Handling of None as default value fixed.

-
-
-

10.4   2008/02/05 - Version 0.3.1

-

BUGFIX: Unicode checks no longer broken.

-
-
-

10.5   2008/02/05 - Version 0.3.0

-

Improved performance with a parse cache.

-

New get_default_value method. Given a check it returns the default -value (converted to the correct type) or raises a KeyError if the -check doesn't specify a default.

-

Added 'tuple' check and corresponding 'is_tuple' function (which always returns a tuple).

-

BUGFIX: A quoted 'None' as a default value is no longer treated as None, -but as the string 'None'.

-

BUGFIX: We weren't unquoting keyword arguments of length two, so an -empty string didn't work as a default.

-

BUGFIX: Strings no longer pass the 'is_list' check. Additionally, the -list checks always return lists.

-

A couple of documentation bug fixes.

-

Removed CHANGELOG from module.

-
- -
-

10.7   2006/12/17 Version 0.2.3-alpha1

-

By Nicola Larosa

-

Fixed validate doc to talk of boolean instead of bool; changed the -is_bool function to is_boolean (Sourceforge bug #1531525).

-
-
-

10.8   2006/04/29 Version 0.2.2

-

Addressed bug where a string would pass the is_list test. (Thanks to -Konrad Wojas.)

-
-
-

10.9   2005/12/16 Version 0.2.1

-

Fixed bug so we can handle keyword argument values with commas.

-

We now use a list constructor for passing list values to keyword arguments -(including default):

-
-default=list("val", "val", "val")
-
-

Added the _test test.

-

Moved a function call outside a try...except block.

-
-
-

10.10   2005/08/18 Version 0.2.0

-

Updated by Michael Foord and Nicola Larosa

-

Does type conversion as well.

-
-
-

10.11   2005/02/01 Version 0.1.0

-

Initial version developed by Michael Foord -and Mark Andrews.

-
-
-
- - diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..fed528d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..fccba36 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,28 @@ +# +# Configuration for setuptools +# + +[egg_info] +tag_build = .dev0 +tag_date = false + + +[sdist] +formats = zip, gztar + + +[bdist_wheel] +# If you set this to 1, make sure you have a proper Travis CI build matrix, +# and that your Trove classifiers state you support Python 2 and 3 +universal = 1 + + +[tool:pytest] +norecursedirs = .* *.egg *.egg-info bin dist include lib local share static docs +python_files = src/tests/test_*.py +#addopts = + + +[flake8] +#ignore = E226,… +max-line-length = 132 diff --git a/setup.py b/setup.py index c6d57a6..fcdecc0 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,10 @@ +#!/usr/bin/env python # setup.py -# Install script for ConfigObj +# -*- coding: utf-8 -*- +# pylint: disable=invalid-name + +"""Install script for ConfigObj""" + # Copyright (C) 2005-2014: # (name) : (email) # Michael Foord: fuzzyman AT voidspace DOT org DOT uk @@ -10,31 +15,48 @@ # This software is licensed under the terms of the BSD license. # http://opensource.org/licenses/BSD-3-Clause +import io import os +import re import sys -from distutils.core import setup -# a simple import wouldn't work if we moved towards a package with __init__ -from _version import __version__ +from contextlib import closing + +from setuptools import setup if sys.version_info < (2, 6): - print('for python versions < 2.6 use configobj ' + print('for Python versions < 2.6 use configobj ' 'version 4.7.2') sys.exit(1) +elif sys.version_info < (2, 7): + print('for Python version 2.6 use configobj ' + 'version 5.0.6') + sys.exit(1) __here__ = os.path.abspath(os.path.dirname(__file__)) -VERSION = __version__ NAME = 'configobj' -MODULES = 'configobj', 'validate', '_version' - +MODULES = [] +PACKAGES = ['configobj'] DESCRIPTION = 'Config file reading, writing and validation.' - URL = 'https://github.com/DiffSK/configobj' +REQUIRES = """ + six +""" + +VERSION = '' +with closing(open(os.path.join(__here__, 'src', PACKAGES[0], '_version.py'), 'r')) as handle: + for line in handle.readlines(): + if line.startswith('__version__'): + VERSION = re.split('''['"]''', line)[1] +assert re.match(r"[0-9](\.[0-9]+)", VERSION), "No semantic version found in 'configobj._version'" + LONG_DESCRIPTION = """**ConfigObj** is a simple but powerful config file reader and writer: an *ini file round tripper*. Its main feature is that it is very easy to use, with a straightforward programmer's interface and a simple syntax for config files. -It has lots of other features though : + +List of Features +---------------- * Nested sections (subsections), to any level * List values @@ -51,35 +73,31 @@ * The order of keys/sections is preserved * Powerful ``unrepr`` mode for storing/retrieving Python data-types -| Release 5.0.6 improves error messages in certain edge cases -| Release 5.0.5 corrects a unicode-bug that still existed in writing files -| Release 5.0.4 corrects a unicode-bug that still existed in reading files after -| fixing lists of string in 5.0.3 -| Release 5.0.3 corrects errors related to the incorrectly handling unicode -| encoding and writing out files -| Release 5.0.2 adds a specific error message when trying to install on -| Python versions older than 2.5 -| Release 5.0.1 fixes a regression with unicode conversion not happening -| in certain cases PY2 -| Release 5.0.0 updates the supported Python versions to 2.6, 2.7, 3.2, 3.3 -| and is otherwise unchanged -| Release 4.7.2 fixes several bugs in 4.7.1 -| Release 4.7.1 fixes a bug with the deprecated options keyword in -| 4.7.0. -| Release 4.7.0 improves performance adds features for validation and -| fixes some bugs.""" +""" + +try: + with io.open('CHANGES.rst', encoding='utf-8') as handle: + LONG_DESCRIPTION += handle.read() +except EnvironmentError as exc: + # Build / install anyway + print("WARNING: Cannot open/read CHANGES.rst due to {}".format(exc)) CLASSIFIERS = [ + # Details at http://pypi.python.org/pypi?:action=list_classifiers 'Development Status :: 6 - Mature', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Programming Language :: Python', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', 'Operating System :: OS Independent', 'Topic :: Software Development :: Libraries', 'Topic :: Software Development :: Libraries :: Python Modules', @@ -91,16 +109,23 @@ KEYWORDS = "config, ini, dictionary, application, admin, sysadmin, configuration, validation".split(', ') - -setup(name=NAME, - version=VERSION, - install_requires=['six'], - description=DESCRIPTION, - long_description=LONG_DESCRIPTION, - author=AUTHOR, - author_email=AUTHOR_EMAIL, - url=URL, - py_modules=MODULES, - classifiers=CLASSIFIERS, - keywords=KEYWORDS - ) +project = dict( + name=NAME, + version=VERSION, + description=DESCRIPTION, + long_description=LONG_DESCRIPTION, + author=AUTHOR, + author_email=AUTHOR_EMAIL, + url=URL, + py_modules=MODULES, + package_dir={'': 'src'}, + packages=PACKAGES, + install_requires=[i.strip() for i in REQUIRES.splitlines() if i.strip()], + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', + classifiers=CLASSIFIERS, + keywords=KEYWORDS, + license='BSD (2 clause)', +) + +if __name__ == '__main__': + setup(**project) \ No newline at end of file diff --git a/configobj.py b/src/configobj/__init__.py similarity index 99% rename from configobj.py rename to src/configobj/__init__.py index ba886e8..0d752bc 100644 --- a/configobj.py +++ b/src/configobj/__init__.py @@ -20,7 +20,7 @@ from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE import six -from _version import __version__ +from ._version import __version__ # imported lazily to avoid startup performance hit if it isn't used compiler = None @@ -2170,7 +2170,7 @@ def validate(self, validator, preserve_errors=False, copy=False, if preserve_errors: # We do this once to remove a top level dependency on the validate module # Which makes importing configobj faster - from validate import VdtMissingValue + from configobj.validate import VdtMissingValue self._vdtMissingValue = VdtMissingValue section = self diff --git a/src/configobj/_version.py b/src/configobj/_version.py new file mode 100644 index 0000000..3379d0a --- /dev/null +++ b/src/configobj/_version.py @@ -0,0 +1 @@ +__version__ = '5.0.7' \ No newline at end of file diff --git a/validate.py b/src/configobj/validate.py similarity index 100% rename from validate.py rename to src/configobj/validate.py diff --git a/tests/__init__.py b/src/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to src/tests/__init__.py diff --git a/tests/conf.ini b/src/tests/conf.ini similarity index 100% rename from tests/conf.ini rename to src/tests/conf.ini diff --git a/tests/conf.spec b/src/tests/conf.spec similarity index 100% rename from tests/conf.spec rename to src/tests/conf.spec diff --git a/test_configobj.py b/src/tests/configobj_doctests.py similarity index 99% rename from test_configobj.py rename to src/tests/configobj_doctests.py index 2133a7d..ab9e04d 100644 --- a/test_configobj.py +++ b/src/tests/configobj_doctests.py @@ -33,7 +33,7 @@ from codecs import BOM_UTF8 from configobj import * -from validate import Validator, VdtValueTooSmallError +from configobj.validate import Validator, VdtValueTooSmallError def _test_validate(): @@ -45,7 +45,7 @@ def _test_validate(): >>> c = ConfigObj(a, configspec=b) >>> c ConfigObj({'foo': 'fish'}) - >>> from validate import Validator + >>> from configobj.validate import Validator >>> v = Validator() >>> c.validate(v) 0 @@ -691,7 +691,7 @@ def _unexpected_validation_errors(): report the failure to validate # section specified, got scalar - >>> from validate import ValidateError + >>> from configobj.validate import ValidateError >>> s = ['[cow]', 'something = boolean'] >>> c = ['cow = true'] >>> ini = ConfigObj(c, configspec=s) diff --git a/tests/conftest.py b/src/tests/conftest.py similarity index 80% rename from tests/conftest.py rename to src/tests/conftest.py index e11ad40..33b1bc9 100644 --- a/tests/conftest.py +++ b/src/tests/conftest.py @@ -2,7 +2,7 @@ import pytest from configobj import ConfigObj -from validate import Validator +from configobj.validate import Validator @pytest.fixture def empty_cfg(): diff --git a/tests/test_configobj.py b/src/tests/test_configobj.py similarity index 99% rename from tests/test_configobj.py rename to src/tests/test_configobj.py index 473992b..b9004fd 100644 --- a/tests/test_configobj.py +++ b/src/tests/test_configobj.py @@ -12,7 +12,7 @@ import configobj as co from configobj import ConfigObj, flatten_errors, ReloadError, DuplicateError, MissingInterpolationOption, InterpolationLoopError, ConfigObjError -from validate import Validator, VdtValueTooSmallError +from configobj.validate import Validator, VdtValueTooSmallError def cfg_lines(config_string_representation): diff --git a/tests/test_validate.py b/src/tests/test_validate.py similarity index 98% rename from tests/test_validate.py rename to src/tests/test_validate.py index bffb0dc..07c1de7 100644 --- a/tests/test_validate.py +++ b/src/tests/test_validate.py @@ -2,7 +2,7 @@ from configobj import ConfigObj import pytest -from validate import Validator, VdtValueTooSmallError +from configobj.validate import Validator, VdtValueTooSmallError class TestBasic(object): diff --git a/tests/test_validate_errors.py b/src/tests/test_validate_errors.py similarity index 98% rename from tests/test_validate_errors.py rename to src/tests/test_validate_errors.py index 644dfb3..399daa8 100644 --- a/tests/test_validate_errors.py +++ b/src/tests/test_validate_errors.py @@ -3,7 +3,7 @@ import pytest from configobj import ConfigObj, get_extra_values, ParseError, NestingError -from validate import Validator +from configobj.validate import Validator @pytest.fixture() def thisdir(): diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 1d71631..0000000 --- a/tox.ini +++ /dev/null @@ -1,12 +0,0 @@ -# content of: tox.ini, put in same dir as setup.py -[tox] -envlist = py26,py27,py32,py33 -[testenv] -deps=pytest - pytest-cov -setenv = - PYTHONWARNINGS = always -commands=python test_configobj.py - python validate.py - coverage run --source=configobj.py,validate.py -m py.test tests - coverage report