From ba4e85be503b9a35bb6e9ac3393650f3c4289e91 Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Wed, 19 Jan 2022 17:21:05 +0100 Subject: [PATCH] config: add ConfigurableObject object class --- mylib/config.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/mylib/config.py b/mylib/config.py index af99f1b..498efdd 100644 --- a/mylib/config.py +++ b/mylib/config.py @@ -948,3 +948,87 @@ class Config: # pylint: disable=too-many-instance-attributes ("%s.ini" % self.shortname) if self.shortname else "config.ini" ) + + +class ConfigurableObject: + """ + Base class of configurable object + + This class provide a way to configure an object using : + - mylib.config.Config object + - argparse.Namespace object + - kwargs passed to __init__ method + """ + + # Configuration object name (used for default options prefix and config section) + # Note: required if options_prefix or/and config_section parameters not provided + # to __init__ method. + _config_name = None + + # Configuration comment (used for config section) + _config_comment = None + + # Default options value + # Important: all supported options MUST HAVE a default value defined + _defaults = {} + + # Store options passed throuht __init__ method + _kwargs = {} + _options = {} + _options_prefix = None + _config = None + _config_section = None + + def __init__(self, options=None, options_prefix=None, config=None, config_section=None, + **kwargs): + + for key, value in kwargs.items(): + assert key in self._defaults, "Unknown %s option" % key + self._kwargs[key] = value + + if options: + self._options = options + if options_prefix is not None: + self._options_prefix = options_prefix + elif self._config_name: + self._options_prefix = self._config_name + '_' + else: + raise Exception('No configuration name defined for %s' % __name__) + + if config: + self._config = config + if config_section: + self._config_section = config_section + elif self._config_name: + self._config_section = self._config_name + else: + raise Exception('No configuration name defined for %s' % __name__) + + def _get_option(self, option, default=None, required=False): + """ Retreive option value """ + if self._kwargs and option in self._kwargs: + return self._kwargs[option] + + if self._options and hasattr(self._options, self._options_prefix + option): + return getattr(self._options, self._options_prefix + option) + + if self._config and self._config.defined(self._config_section, option): + return self._config.get(self._config_section, option) + + assert not required, "Options %s not defined" % option + + return default if default is not None else self._defaults.get(option) + + def configure(self, comment=None, ** kwargs): + """ Configure options on registered mylib.Config object """ + assert self._config, "mylib.Config object not registered. Must be passed to __init__ as config keyword argument." + + return self._config.add_section( + self._config_section, + comment=comment if comment else self._config_comment, + loaded_callback=self.initialize, **kwargs) + + def initialize(self, loaded_config=None): + """ Configuration initialized hook """ + if loaded_config: + self.config = loaded_config # pylint: disable=attribute-defined-outside-init