"""Implementation classes that are used as application configuration containersparsed from files."""__author__='Paul Landes'fromtypingimportDict,Set,Unionimportloggingimportreimportcollectionsfromzensols.persistimportpersistedfrom.importConfigurable,ConfigurableErrorlogger=logging.getLogger(__name__)
[docs]classStringConfig(Configurable):"""A simple string based configuration. This takes a single comma delimited key/value pair string in the format: ``<section>.<name>=<value>[,<section>.<name>=<value>,...]`` A dot (``.``) is used to separate the section from the option instead of a colon (``:``), as used in more sophisticaed interpolation in the :class:`configparser.ExtendedInterpolation`. The dot is used for this reason to make other section interpolation easier. """KEY_VAL_REGEX=re.compile(r'^(?:([^.]+?)\.)?([^=]+?)=(.+)$')
[docs]def__init__(self,config_str:str,option_sep_regex:Union[re.Pattern,str]=r'\s*,\s*',default_section:str=None):"""Initialize with a string given as described in the class docs. :param config_str: the configuration :param option_sep_regex: the regular expression used to delimit the each key/value pair :param default_section: used as the default section when non given on the get methds such as :meth:`get_option` """super().__init__(default_section)self.config_str=config_strifisinstance(option_sep_regex,str):self.option_sep_regex=re.compile(option_sep_regex)else:self.option_sep_regex=option_sep_regex
@persisted('_parsed_config')def_get_parsed_config(self)->Dict[str,str]:"""Parse the configuration string given in the initializer (see class docs). """conf=collections.defaultdict(lambda:{})forkvinre.split(self.option_sep_regex,self.config_str):m=self.KEY_VAL_REGEX.match(kv)ifmisNone:raiseConfigurableError(f"unexpected format: '{kv}' in '{self.config_str}'")sec,name,value=m.groups()sec=self.default_sectionifsecisNoneelseseciflogger.isEnabledFor(logging.DEBUG):logger.debug(f'section={sec}, name={name}, value={value}')conf[sec][name]=valuereturnconf@property@persisted('_sections')defsections(self)->Set[str]:returnset(self._get_parsed_config().keys())