The LayeredConfig class

class ferenda.LayeredConfig(defaults=None, inifile=None, commandline=None, cascade=False)

Provides unified access to a nested set of configuration parameters. The source of these parameters a config file (using .ini-file style syntax), command line parameters, and default settings embedded in code. Command line parameters override configuration file parameters, which in turn override default settings in code (hence Layered Config).

Configuration parameters are accessed as regular object attributes, not dict-style key/value pairs. Configuration parameter names should therefore be regular python identifiers (i.e. only consist of alphanumerical chars and ‘_’).

Configuration parameter values can be typed (strings, integers, booleans, dates, lists...). Even though ini-style config files and command line parameters are by themselves non-typed, by specifying default settings in code, parameters from a config file or the commamd line can be typed.

Configuration parameters can be changed in code. Such changes can be written to the configuration file by calling write().

Parameters:
  • defaults (dict) – A dict with configuration keys and values. If any values are dicts, these are turned into nested config objects.
  • inifile (str) – The name of a ini-style configuration file. The file should have a top-level section named __root__, whose keys are turned into top-level configuration parameters. Any other sections in this file are turned into nested config objects.
  • inifile – full path to a .ini-style config file.
  • commandline (list) – The contents of sys.argv, or something similar. Any long-style parameters are turned into configuration values, and parameters with hyphens are turned into nested config objects (i.e. --module-parameter=foo results in self.module.parameter == “foo”.
  • cascade (bool) – If an attempt to get a non-existing parameter on a sub (nested) configuration object should attempt to get the parameter on the parent config object.
  • cascade – If a configuration key is not found, search parent config object.

Example:

>>> defaults = {'parameter': 'foo', 'other': 'default'}
>>> dir = tempfile.mkdtemp()
>>> inifile = dir + os.sep + "test.ini"
>>> with open(inifile, "w") as fp:
...     res = fp.write("[__root__]\nparameter = bar")
>>> argv = ['--parameter=baz']
>>> conf = LayeredConfig(defaults, inifile, argv)
>>> conf.parameter == 'baz'
True
>>> conf.other == 'default'
True
>>> conf.parameter = 'changed'
>>> conf.other = 'also changed'
>>> LayeredConfig.write(conf)
>>> with open(inifile) as fp:
...     res = fp.read()
>>> res == '[__root__]\nparameter = changed\nother = also changed\n\n'
True
>>> os.unlink(inifile)
>>> os.rmdir(dir)
static write(config)

Write changed properties to inifile (if provided at initialization).