Configure is a thin wrapper around PyYAML which extends already readable and powerful YAML with inheritance, composition and (so called) “object-graph configuration” features.
Configure uses YAML as a configuration format so you can refer to YAML specification for details on how you can compose your configuration. The basics are the following – you your config as a mapping, which allows nesting and also can contain sequences:
# my.conf database: postgresql://localhost/dbname timeout: !timedelta 10m messages: - msg: Hello, world! author: Andrey Popp - msg: Wow! author: John Doe EOF
Inline comments are started with # (sharp). To read configuration:
from configure import Configuration config = Configuration.from_file('./my.conf').configure() assert config.database == 'postgresql://localhost/dbname' assert config['database'] == 'postgresql://localhost/dbname' assert config.timeout == datetime.timedelta(seconds=600)
As you can see timeout value automatically parsed and converted to class:datetime.timedelta object by annotating configuration value with !timedelta tag. There’s also !re builtin tag which passes value to re.compile() function so you can have compiled regular expression right after reading a config.
You should always call Configuration.configure() method before using Configuration.
Objects of class Configuration implement collections.MutableMapping interface, but as you already saw, you can also access values by attribute.
You can compose configuration from different sources by using !include tag, the configuration you included will be placed inplace of the element you tagged with !include:
# common.conf db: postgresql://localhost/dbname # app.conf common: !include:common.conf
Note that filename resolves relative to dirname of configuration which contain !include tag, so in example above app.conf and common.conf should be placed in the same directory. After loading app.conf configuration:
config = Configuration.from_file('app.conf').configure() assert config.common.db == 'postgresql://localhost/dbname'
You can use !include tag at any level of the document.
Configuration can be also composed using inheritance mechanism using !extends tag. It can be useful for providing some sensible defaults for configuration file:
# base.conf, contains default values db: postgresql://localhost/dbname # app.conf --- !extends:base.conf timeout: !timedelta 10m
Filename resolution performs the same like with !include tag, so base.conf and app.conf should be placed in the same directory again. When you load app.conf:
config = Configuration.from_file('app.conf').configure() assert config.db == 'postgresql://localhost/dbname'
you will see that config.db was inherited from base.conf. Inheritance mechanism can also be applied at any level not necessary at the entire configuration file.
There is also another useful feature configure library provides – so called object-graph configuration. Suppose you have somewhere in your code function which accepts some configuration values and performs some task to configure your system based on these values:
# myapp.py def configure_db(uri, echo=False): ...
You can ask configure to call this function for you automatically with some values from configuration:
# my.conf db: !factory:myapp.configure_db uri: !ref:dburi echo: false dburi: postgresql://localhost/dbname
You see there are !ref and !factory tags – first one just references some other value from configuration which allows you to stay DRY, while !factory tag call specified function using arguments provided in mapping.
This does work only with positional and keyword arguments and doesn’t work with “magic” *args and **kwargs at the moment.
When using inheritance with !extends it is possible to !ref to refer to values defined not in the current config but in the parent configs as well.
Another useful tag is the !obj tag which just imports some python object for you:
will import myapp.resource.Resource object and assign it resource_cls key.
You should never instantiate this object but use from_file, from_string or from_dict classmethods instead. Implements collections.MutableMapping protocol.
This method performs all actions pending to this Configuration object. You can also override configuration at this moment by providing mapping object as struct argument.
Construct Configuration from dict d.
|Parameters:||d – mapping object to use for config|
Construct Configuration object by reading and parsing file filename.
Construct Configuration from string.
Produce new configuration by merging config object into this one
Configure logging in a sane way
Imports an object based on a string. This is useful if you want to use import paths as endpoints or something similar. An import path can be specified either in dotted notation (xml.sax.saxutils.escape) or with a colon as object delimiter (xml.sax.saxutils:escape).
If silent is True the return value will be None if the import fails.
For better debugging we recommend the new import_module() function to be used instead.