Source code for netdef.Shared.SharedConfig

import logging
import os
import pathlib
import sys
from collections import OrderedDict
from configparser import (
    ConfigParser,
    ExtendedInterpolation,
    InterpolationMissingOptionError,
)

log = logging.getLogger(__name__)


[docs]class Config: """ A *wrapper* class for the configparser module in standard python library. :param str identifier: a unique identifier for this app. :param str install_path: Full filepath to application package location :param str proj_path: Full filepath to project location :param str default_config_string: initial config text for configparser """ def __init__( self, identifier, install_path, proj_path, default_config_string, read_from_files=True, ): self.IDENTIFIER = identifier if not install_path: install_path = os.path.dirname(__file__) # install_path = os.path.expanduser(install_path) if not proj_path: proj_path = os.getcwd() config_path = pathlib.Path(proj_path).joinpath("config") _config = ConfigParser(interpolation=ExtendedInterpolation()) # This trick allows the option key to remain case-sensitive _config.optionxform = str self._config = _config _config.add_section("install") _config.set("install", "path", install_path) _config.add_section("proj") _config.set("proj", "path", proj_path) _config.read_string(default_config_string) # if getfilesystemencoding returns ascii then we will not be able to read config files with exotic characters. # we must therefore choose something else; getdefaultencoding () self.conf_encoding = sys.getfilesystemencoding() if self.conf_encoding == "ascii": self.conf_encoding = sys.getdefaultencoding() # self.read("{install_path}/data".format(install_path=install_path)) if read_from_files: self.read_default(config_path) self.verify(proj_path, config_path) if read_from_files and "config" in self._config: for ident, path in self.get_dict("config").items(): self._config.read(path, encoding=self.conf_encoding) # this file should not be editable from "Config Files" in webadmin. # Used to lock specific configurations. must therefore be read last. if read_from_files: self._config.read( "{config_path}/default.lock".format(config_path=config_path), encoding=self.conf_encoding, ) # liste over konfiger som ikke skal være synlig i webadmin # settes med set_hidden_value-funksjonen self._hidden = {}
[docs] def read_default(self, config_path): log.info("Read config from %s", config_path) self._config.read( "{config_path}/default.conf".format(config_path=config_path), encoding=self.conf_encoding, ) self._config.read( "{config_path}/default.{os_name}.conf".format( config_path=config_path, os_name=os.name ), encoding=self.conf_encoding, )
def __call__(self, section, key, defaultvalue=None, add_if_not_exists=True): return self.config(section, key, defaultvalue)
[docs] def config(self, section, key, defaultvalue=None, add_if_not_exists=True): try: if defaultvalue is None: return self._config[section][key] else: # typecast basert på defaultvalue return type(defaultvalue)(self._config[section][key]) except (KeyError, InterpolationMissingOptionError): if add_if_not_exists: self.set_config(section, key, str(defaultvalue)) return defaultvalue
[docs] def set_config(self, section, key, value): self.add_section(section) self._config.set(section, key, value)
[docs] def add_section(self, section): if not self._config.has_section(section): self._config.add_section(section)
[docs] def set_hidden_value(self, section, key): if not section in self._hidden: self._hidden[section] = [] if not key in self._hidden[section]: self._hidden[section].append(key)
[docs] def is_hidden_value(self, section, key): if not section in self._hidden: return False return key in self._hidden[section]
[docs] def get_dict(self, section): return OrderedDict(self._config[section])
[docs] def get_full_list(self): def walker(): for section, keyval in self._config.items(): try: for key, val in keyval.items(): if self.is_hidden_value(section, key): yield section, key, "****" else: yield section, key, val except InterpolationMissingOptionError as error: yield section, "ERROR", repr(error) return walker()
[docs] def verify(self, proj_path, config_path): proj_path = pathlib.Path(proj_path) if not proj_path.is_dir(): raise ValueError( "Error parsing config-files. proj-path {} not found".format(proj_path) ) config_path = pathlib.Path(config_path) if not config_path.is_dir(): raise ValueError( "Error parsing config-files. config-path {} not found".format( config_path ) ) default_conf = config_path.joinpath("default.conf") if not default_conf.is_file(): raise ValueError( "Error parsing config-files. configfile {} not found".format( default_conf ) ) _ident = self.config("general", "identifier", "") if _ident != self.IDENTIFIER: raise ValueError( "Error parsing config-files. [general]identifier {} not found {}".format( self.IDENTIFIER, _ident ) ) if self.config("general", "version", 0.0) != 1: raise ValueError( "Error parsing config-files. [general]version {} not found".format(1) ) return True