I thought I'd make note of wsgikit.config, a configuration loader. I haven't actually started using it in WSGIKit yet, but I've been using for the configuration of this blog. It has a few features that set it apart from some of the others.
It uses .ini syntax, an easy syntax to work with.
Values are not typed. That means you don't have to use "localhost" for a string, or ["admin", "user"] for lists. The application interprets the strings how it chooses, not based on syntax the user has to learn.
It keeps track of files and line positions, so when you coerce that user-provided string to a certain type (e.g., list of strings, boolean, domain name, etc) and there's an error, you can tell the user exactly where the erroneous data came from.
You aren't bound to a section/key structure, unlike normal ini-file parsers (like ConfigParser). When you use dotted names, that indicates that keys go in sub-dictionaries. Section names are just prefixes for the keys inside them. Lastly, parenthesis can be used to avoid the special meaning of . (useful with domain names), and to avoid normalization (non-alphanumeric characters are ignored, including space and underscore). So these are equivalent:
security.admin.users = tim bob jan # equivalent to: [security(admin)] users = tim bob jan
In addition to layering several files (e.g., a user and site config file) you can also merge sections of a config file on top of another config file, including on top of itself. This allows configurations similar to an Apache <Location> tag, where config values are looked up based on contextual information.
Though not supported now, everything is in there to do round-tripping, i.e., where you load a config from disk, change some settings (e.g., through a web interface), then save the config back, trying to preserve what extra information (like comments and ordering) that it can.
Big to-do's:
If you're curious, the lazyloader module is the place to start looking.
Ian wrote:
Better syntax for nested options than config[section][key]I ran into the same issue. In my config format, I found that I never needed a depth greater than 2, so the following works pretty well (as a method of the Application object):
def config(self, branch=None, leaf=None, default={}): """config([branch], [leaf], default={}) -> tree, branch, or leaf. If branch is not specified, the entire config dict is returned. If branch is specified, but leaf is not, the requested branch is returned (or default if it does not exist). If branch and leaf are specified, the leaf value is returned (or default if either the branch or leaf does not exist). In the case where either branch or leaf are not found, the config tree is not modified--you simply get back empty or default values. """ if branch is None: return self._config if leaf is None: return self._config.get(branch, default) return self._config.get(branch, {}).get(leaf, default)I don't think it would be too hard to convert to n-depth.
# Robert Brewer
I was thinking of allowing either a sequence of keys, like config[section, key] or config.get((section, key)), or maybe somehow allow dotted names, like config.get('section.key') (since usually these are constants anyway). But sometimes I do want keys that contain dots, so it's not a complete plan.
Might users find it more consistent if dots were always required between name components - e.g. admin.(stuff) - rather than being omitted when the component is quoted with brackets? Quoted fields in a CSV file are still delimited by commas even though the field boundaries could be inferred from the quotation marks alone.# Hamish Lawson
Dots are allowed in those positions, but I don't like the way they look, so they aren't required.