From 0aeeaf289ec31da902a9a5e614c1686baf880a29 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Tue, 27 Sep 2016 21:34:42 +0800 Subject: Implement the basic ConfigManger() This is very basic at the moment, and needs many improvements. Thanks: https://github.com/pazz/alot TODO: Add config specifications with default values --- fg21sim/configs/__init__.py | 6 ++++ fg21sim/configs/manager.py | 74 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 fg21sim/configs/__init__.py create mode 100644 fg21sim/configs/manager.py diff --git a/fg21sim/configs/__init__.py b/fg21sim/configs/__init__.py new file mode 100644 index 0000000..b1fe70f --- /dev/null +++ b/fg21sim/configs/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) 2016 Weitian LI +# MIT license + +from .manager import ConfigManager + +configs = ConfigManager() diff --git a/fg21sim/configs/manager.py b/fg21sim/configs/manager.py new file mode 100644 index 0000000..933a63d --- /dev/null +++ b/fg21sim/configs/manager.py @@ -0,0 +1,74 @@ +# Copyright (c) 2016 Weitian LI +# MIT license +# +# References: +# [1] https://configobj.readthedocs.io/en/latest/configobj.html +# [2] https://github.com/pazz/alot/blob/master/alot/settings/manager.py + +""" +Configuration manager. +""" + +import os +from glob import glob +from errors import ConfigError + +from configobj import ConfigObj, ConfigObjError, flatten_errors +from validate import Validator + + +CONFIGS_PATH = os.path.dirname(__file__) + + +class ConfigManager: + """Manager the configurations""" + def __init__(self, configs=None): + """ + :param configs: (optional) list of user configs to load + """ + configs_spec = sorted(glob(os.path.join(CONFIGS_PATH, "*.conf.spec"))) + spec = "\n".join([open(f).read() for f in configs_spec]).split("\n") + self._configspec = ConfigObj(spec, interpolation=False, + list_values=False, _inspec=True) + self._validator = Validator() + configs_default = ConfigObj(configspec=self._configspec) + self._config = self.validate(configs_default) + if configs: + for config in configs: + self.read_config(config) + + def read_config(self, config): + newconfig = ConfigObj(config, configspec=self._configspec) + newconfig = self.validate(newconfig) + self._config.merge(newconfig) + + def validate(self, config): + try: + results = config.validate(self._validator, preserve_errors=True) + except ConfigObjError as e: + raise ConfigError(e.message) + if not results: + error_msg = '' + for (section_list, key, res) in flatten_errors(config, results): + if key is not None: + if res is False: + msg = 'key "%s" in section "%s" is missing.' + msg = msg % (key, ', '.join(section_list)) + else: + msg = 'key "%s" in section "%s" failed validation: %s' + msg = msg % (key, ', '.join(section_list), res) + else: + msg = 'section "%s" is missing' % '.'.join(section_list) + error_msg += msg + '\n' + raise ConfigError(error_msg) + return config + + def get(self, key, fallback=None): + if key in self._config: + value = self._config[key] + else: + value = fallback + return value + + def set(self, key, value): + self._config[key] = value -- cgit v1.2.2