1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2025-11-02 04:20:55 +01:00
lodel2_mirror/lodel/settings/settings_loader.py

195 lines
7.6 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#-*- coding: utf-8 -*-
import configparser
import os
import glob
import copy
from lodel.context import LodelContext
LodelContext.expose_modules(globals(), {
'lodel.logger': 'logger',
'lodel.settings.utils': ['SettingsError', 'SettingsErrors'],
'lodel.settings.validator': ['SettingsValidationError']})
##@brief Merges and loads configuration files
class SettingsLoader(object):
## To avoid the DEFAULT section whose values are found in all sections, we
# have to give it an unsual name
DEFAULT_SECTION = 'lodel2_default_passaway_tip'
## @brief Virtual filename when default value is used
DEFAULT_FILENAME = 'default_value'
##@brief Constructor
# @param conf_path str : conf.d path
def __init__(self,conf_path):
self.__conf_path=conf_path
self.__conf_sv=dict()
self.__conf=self.__merge()
# Stores errors
self.__errors_list = []
##@brief Lists and merges files in settings_loader.conf_path
# @return dict()
def __merge(self):
conf = dict()
l_dir = glob.glob(self.__conf_path+'/*.ini')
logger.debug("SettingsLoader found those settings files : %s" % (
', '.join(l_dir)))
for f_ini in l_dir:
config = configparser.ConfigParser(default_section = self.DEFAULT_SECTION ,interpolation=None)
config.read(f_ini)
for section in [ s for s in config if s != self.DEFAULT_SECTION ]:
if section not in conf:
conf[section] = dict()
for param in config[section]:
if param not in conf[section]:
conf[section][param]=dict()
conf[section][param]['value'] = config[section][param]
conf[section][param]['file'] = f_ini
self.__conf_sv[section + ':' + param]=f_ini
else:
raise SettingsError("Error redeclaration of key %s in section %s. Found in %s and %s" % (
section,
param,
f_ini,
conf[section][param]['file']))
return conf
##@brief Returns option if exists default_value else and validates
# @param section str : name of the section
# @param keyname str
# @param validator callable : takes one argument value and raises validation fail
# @param default_value *
# @param mandatory bool
# @return the option
def getoption(self,section,keyname,validator,default_value=None,mandatory=False):
conf=self.__conf
if section not in conf:
conf[section] = dict()
sec = conf[section]
result = None
if keyname in sec:
result = sec[keyname]['value']
if result is not None:
result = result.strip()
if len(result) == 0:
result = None
try:
del self.__conf_sv[section + ':' + keyname]
except KeyError: #allready fetched
pass
if result is None:
if default_value is None and mandatory:
msg = "Default value mandatory for option %s" % keyname
expt = SettingsError( msg = msg,
key_id = section+'.'+keyname,
filename = sec[keyname]['file'])
self.__errors_list.append(expt)
return
else:
sec[keyname]=dict()
sec[keyname]['value'] = default_value
sec[keyname]['file'] = SettingsLoader.DEFAULT_FILENAME
result = default_value
logger.debug("Using default value for configuration key %s:%s" % (
section, keyname))
try:
return validator(result)
except Exception as e:
# Generating nice exceptions
if False and sec[keyname]['file'] == SettingsLoader.DEFAULT_FILENAME:
expt = SettingsError( msg = 'Mandatory settings not found',
key_id = section+'.'+keyname)
self.__errors_list.append(expt)
else:
expt = SettingsValidationError(
"For %s.%s : %s" %
(section, keyname,e)
)
expt2 = SettingsError( msg = str(expt),
key_id = section+'.'+keyname,
filename = sec[keyname]['file'])
self.__errors_list.append(expt2)
return
##@brief Sets option in a config section. Writes in the conf file
# @param section str : name of the section
# @param keyname str
# @param value str
# @param validator callable : takes one argument value and raises validation fail
# @return the option
def setoption(self,section,keyname,value,validator):
f_conf=copy.copy(self.__conf[section][keyname]['file'])
if f_conf == SettingsLoader.DEFAULT_FILENAME:
f_conf = self.__conf_path + '/generated.ini'
conf=self.__conf
conf[section][keyname] = value
config = configparser.ConfigParser()
config.read(f_conf)
if section not in config:
config[section]={}
config[section][keyname] = validator(value)
with open(f_conf, 'w') as configfile:
config.write(configfile)
##@brief Saves new partial configuration. Writes in the conf files corresponding
# @param sections dict
# @param validators dict of callable : takes one argument value and raises validation fail
def saveconf(self, sections, validators):
for sec in sections:
for kname in sections[sec]:
self.setoption(sec,kname,sections[sec][kname],validators[sec][kname])
##@brief Returns the section to be configured
# @param section_prefix str
# @param default_section str
# @return the section as dict()
def getsection(self,section_prefix,default_section=None):
conf=copy.copy(self.__conf)
sections=[]
if section_prefix in conf:
sections.append(section_prefix)
for sect_names in conf:
if sect_names in sections:
pass
elif sect_names.startswith(section_prefix + '.'):
sections.append(sect_names)
if sections == [] and default_section:
sections.append(section_prefix + '.' + default_section)
elif sections == []:
raise NameError("Not existing settings section : %s" % section_prefix)
return sections
##@brief Returns invalid settings
#
# This method returns all the settings that was not fecthed by
# getsection() method. For the Settings object it allows to know
# the list of invalids settings keys
# @return a dict with SECTION_NAME+":"+KEY_NAME as key and the filename
# where the settings was found as value
def getremains(self):
return self.__conf_sv
##@brief Raise a SettingsErrors exception if some confs remains
#@note typically used at the end of Settings bootstrap
def raise_errors(self):
remains = self.getremains()
err_l = self.__errors_list
for key_id, filename in remains.items():
err_l.append(SettingsError( msg = "Invalid configuration key",
key_id = key_id,
filename = filename))
if len(err_l) > 0:
raise SettingsErrors(err_l)
else:
return