import os.path
import pynsive
from ConfigParser import ConfigParser
def _find_cfg_classes(module):
def configuration_objects_only(cls):
return issubclass(cls, ConfigurationPart)
return pynsive.list_classes(module, configuration_objects_only)
[docs]def load_config(cfg_module_name, location, defaults=None):
if not os.path.isfile(location):
raise ConfigurationError(
'Unable to locate configuration file: {}'.format(location))
cfg = ConfigParser()
cfg.read(location)
return Configuration(_find_cfg_classes(cfg_module_name), cfg, defaults)
[docs]class ConfigurationError(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
[docs]class Configuration(object):
def __init__(self, cfg_cls_list, cfg, defaults):
self._cfg_objects = dict()
for cfg_cls in cfg_cls_list:
cfg_object = cfg_cls(cfg, defaults)
self._cfg_objects[cfg_object.name()] = cfg_object
def __getattr__(self, name):
return self._cfg_objects.get(name)
[docs]class ConfigurationPart(object):
"""
A configuration part is an OO abstraction for a ConfigParser that allows
for ease of documentation and usage of configuration options. All
subclasses of ConfigurationPart must follow a naming convention. A
configuration part subclass must start with the name of its section. This
must then be followed by the word "Configuration." This convention results
in subclasses with names similar to: CoreConfiguration and
LoggingConfiguration.
A configuration part subclass will have its section set to the lowercase
name of the subclass sans the word such that a subclass with the name,
"LoggingConfiguration" will reference the ConfigParser section "logging"
when looking up options.
"""
def __init__(self, cfg, defaults=None):
self._cfg = cfg
self._name = self.name()
self._defaults = dict() if not defaults else defaults
def __getattr__(self, name):
return self.get(name)
def _get_default(self, option):
namespace = self._defaults.get(self._name)
return namespace.get(option) if namespace else None
[docs] def name(self):
return type(self).__name__.replace('Configuration', '').lower()
[docs] def options(self):
return self._cfg.options(self._name)
[docs] def has_option(self, option):
return self._cfg.has_option(self._name, option)
[docs] def get(self, option):
if self.has_option(option):
return self._cfg.get(self._name, option)
else:
return self._get_default(option)
[docs] def getboolean(self, option):
if self.has_option(option):
return self._cfg.getboolean(self._name, option)
else:
return self._get_default(option)
[docs] def getint(self, option):
if self.has_option(option):
return self._cfg.getint(self._name, option)
else:
return self._get_default(option)