1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2025-10-30 19:19:03 +01:00

After pylint

This commit is contained in:
prieto 2017-02-10 11:48:21 +01:00
commit a1afe3b48d
3 changed files with 144 additions and 201 deletions

View file

@ -8,8 +8,9 @@ LodelContext.expose_modules(globals(), {
#
# Display name and Description of a lodel2 object
##@brief Class allows dislpay name and help text for lodel2 objects and fields
class MlNamedObject(object):
def __init__(self, display_name = None, help_text = None, toto=None):
def __init__(self, display_name=None, help_text=None):
self.display_name = None if display_name is None else MlString(display_name)
self.help_text = None if help_text is None else MlString(help_text)

View file

@ -13,23 +13,23 @@ LodelContext.expose_modules(globals(), {
##@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()
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):
@ -38,26 +38,24 @@ class SettingsLoader(object):
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)
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 ]:
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()
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
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']))
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
@ -65,8 +63,8 @@ class SettingsLoader(object):
# @param default_value *
# @param mandatory bool
# @return the option
def getoption(self,section,keyname,validator,default_value=None,mandatory=False):
conf=self.__conf
def getoption(self, section, keyname, validator, default_value=None, mandatory=False):
conf = self.__conf
if section not in conf:
conf[section] = dict()
@ -85,35 +83,31 @@ class SettingsLoader(object):
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'])
expt = SettingsError(msg=msg, key_id=section+'.'+keyname, \
filename=sec[keyname]['file'])
self.__errors_list.append(expt)
return
else:
sec[keyname]=dict()
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))
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)
expt = SettingsError(msg='Mandatory settings not found', \
key_id=section+'.'+keyname)
self.__errors_list.append(expt)
else:
expt = ValidationError(
"For %s.%s : %s" %
(section, keyname,e)
)
expt2 = SettingsError( msg = str(expt),
key_id = section+'.'+keyname,
filename = sec[keyname]['file'])
expt = ValidationError("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
@ -123,38 +117,38 @@ class SettingsLoader(object):
# @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'])
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 = self.__conf
conf[section][keyname] = value
config = configparser.ConfigParser()
config.read(f_conf)
if section not in config:
config[section]={}
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])
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=[]
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:
@ -162,34 +156,33 @@ class SettingsLoader(object):
pass
elif sect_names.startswith(section_prefix + '.'):
sections.append(sect_names)
if sections == [] and default_section:
sections.append(section_prefix + '.' + default_section)
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
# 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))
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

View file

@ -11,7 +11,7 @@ from lodel.context import LodelContext
LodelContext.expose_modules(globals(), {
'lodel.mlnamedobject.mlnamedobject': ['MlNamedObject'],
'lodel.exceptions': ['LodelException', 'LodelExceptions',
'LodelFatalError', 'FieldValidationError']})
'LodelFatalError', 'FieldValidationError']})
## @package lodel.settings.validator Lodel2 settings validators/cast module
#
@ -30,15 +30,15 @@ class ValidationError(Exception):
# casted value.
#@todo implement an IP validator and use it in multisite confspec
class Validator(MlNamedObject):
_validators = dict()
_description = dict()
##@brief Instanciate a validator
#@param name str : validator name
#@param none_is_valid bool : if True None will be validated
#@param **kwargs : more arguement for the validator
def __init__(self, name, none_is_valid = False, display_name = None, help_text = None, **kwargs):
def __init__(self, name, none_is_valid=False, display_name=None, help_text=None, **kwargs):
if name is not None and name not in self._validators:
raise LodelFatalError("No validator named '%s'" % name)
self.__none_is_valid = none_is_valid
@ -58,9 +58,9 @@ class Validator(MlNamedObject):
try:
ret = self._validators[self.__name](value, **self._opt_args)
return ret
except Exception as e:
raise ValidationError(e)
except Exception as exp:
raise ValidationError(exp)
##@brief Register a new validator
# @param name str : validator name
# @param callback callable : the function that will validate a value
@ -74,7 +74,7 @@ class Validator(MlNamedObject):
raise TypeError("Callable expected but got %s" % type(callback))
cls._validators[name] = callback
cls._description[name] = description
##@brief Get the validator list associated with description
@classmethod
def validators_list(cls):
@ -87,22 +87,18 @@ class Validator(MlNamedObject):
# @param separator str : The element separator
# @return A Validator instance
@classmethod
def create_list_validator(cls, validator_name, elt_validator, description = None, separator = ','):
def create_list_validator(cls, validator_name, elt_validator, description=None, separator=','):
def list_validator(value):
res = list()
errors = list()
for elt in value.split(separator):
elt = elt_validator(elt)
if len(elt) > 0:
res.append(elt)
return res
description = "Convert value to an array" if description is None else description
cls.register_validator(
validator_name,
list_validator,
description)
cls.register_validator(validator_name, list_validator, description)
return cls(validator_name)
##@brief Create and register a list validator which reads an array and returns a string
# @param elt_validator callable : The validator that will be used for validate each elt value
# @param validator_name str
@ -110,39 +106,35 @@ class Validator(MlNamedObject):
# @param separator str : The element separator
# @return A Validator instance
@classmethod
def create_write_list_validator(cls, validator_name, elt_validator, description = None, separator = ','):
def create_write_list_validator(cls, validator_name, elt_validator, description=None, separator=','):
def write_list_validator(value):
res = ''
errors = list()
for elt in value:
res += elt_validator(elt) + ','
return res[:len(res)-1]
description = "Convert value to a string" if description is None else description
cls.register_validator(
validator_name,
write_list_validator,
description)
cls.register_validator(validator_name, write_list_validator, description)
return cls(validator_name)
##@brief Create and register a regular expression validator
# @param pattern str : regex pattern
# @param validator_name str : The validator name
# @param description str : Validator description
# @return a Validator instance
@classmethod
def create_re_validator(cls, pattern, validator_name, description = None):
def create_re_validator(cls, pattern, validator_name, description=None):
def re_validator(value):
if not re.match(pattern, value):
raise ValidationError("The value '%s' doesn't match the following pattern '%s'" % pattern)
raise ValidationError(\
"The value '%s' doesn't match the following pattern '%s'" \
% pattern)
return value
#registering the validator
cls.register_validator(
validator_name,
re_validator,
("Match value to '%s'" % pattern) if description is None else description)
cls.register_validator(validator_name, re_validator, \
("Match value to '%s'" % pattern) \
if description is None else description)
return cls(validator_name)
## @return a list of registered validators
@classmethod
def validators_list_str(cls):
@ -183,22 +175,22 @@ def boolean_val(value):
def directory_val(value):
res = Validator('strip')(value)
if not os.path.isdir(res):
raise ValidationError("Folowing path don't exists or is not a directory : '%s'"%res)
raise ValidationError("Following path don't exists or is not a directory : '%s'"%res)
return res
##@brief Validate a loglevel value
def loglevel_val(value):
valids = ['DEBUG', 'INFO', 'WARNING', 'SECURITY', 'ERROR', 'CRITICAL']
if value.upper() not in valids:
raise ValidationError(
"The value '%s' is not a valid loglevel" % value)
raise ValidationError( \
"The value '%s' is not a valid loglevel" % value)
return value.upper()
##@brief Validate a path
def path_val(value):
if value is None or not os.path.exists(value):
raise ValidationError(
"path '%s' doesn't exists" % value)
raise ValidationError( \
"path '%s' doesn't exists" % value)
return value
##@brief Validate None
@ -211,8 +203,8 @@ def none_val(value):
def str_val(value):
try:
return str(value)
except Exception as e:
raise ValidationError("Not able to convert value to string : " + str(e))
except Exception as exp:
raise ValidationError("Can't to convert value to string: " + str(exp))
##@brief Validate using a regex
def regex_val(value, pattern):
@ -229,21 +221,21 @@ def host_val(value):
try:
socket.inet_aton(value)
return value
except (TypeError,OSError):
except (TypeError, OSError):
pass
try:
socket.inet_pton(socket.AF_INET6, value)
return value
except (TypeError,OSError):
except (TypeError, OSError):
pass
try:
socket.getaddrinfo(value, 80)
return value
except (TypeError,socket.gaierror):
except (TypeError, socket.gaierror):
msg = "The value '%s' is not a valid host"
raise ValidationError(msg % value)
def custom_list_validator(value, validator_name, validator_kwargs = None):
def custom_list_validator(value, validator_name, validator_kwargs=None):
validator_kwargs = dict() if validator_kwargs is None else validator_kwargs
validator = Validator(validator_name, **validator_kwargs)
for item in value.split():
@ -254,100 +246,65 @@ def custom_list_validator(value, validator_name, validator_kwargs = None):
# Default validators registration
#
Validator.register_validator(
'custom_list',
custom_list_validator,
Validator.register_validator('custom_list', custom_list_validator, \
'A list validator that takes a "validator_name" as argument')
Validator.register_validator(
'dummy',
lambda value:value,
'Validate anything')
Validator.register_validator('dummy', lambda value: value, 'Validate anything')
Validator.register_validator(
'none',
none_val,
'Validate None')
Validator.register_validator('none', none_val, 'Validate None')
Validator.register_validator(
'string',
str_val,
'Validate string values')
Validator.register_validator('string', str_val, 'Validate string values')
Validator.register_validator(
'strip',
str.strip,
'String trim')
Validator.register_validator('strip', str.strip, 'String trim')
Validator.register_validator(
'int',
int_val,
'Integer value validator')
Validator.register_validator('int', int_val, 'Integer value validator')
Validator.register_validator(
'bool',
boolean_val,
'Boolean value validator')
Validator.register_validator('bool', boolean_val, 'Boolean value validator')
Validator.register_validator(
'errfile',
file_err_output,
Validator.register_validator('errfile', file_err_output,\
'Error output file validator (return stderr if filename is "-")')
Validator.register_validator(
'directory',
directory_val,
Validator.register_validator('directory', directory_val, \
'Directory path validator')
Validator.register_validator(
'loglevel',
loglevel_val,
'Loglevel validator')
Validator.register_validator('loglevel', loglevel_val, 'Loglevel validator')
Validator.register_validator(
'path',
path_val,
'path validator')
Validator.register_validator('path', path_val, 'path validator')
Validator.register_validator(
'host',
host_val,
'host validator')
Validator.register_validator('host', host_val, 'host validator')
Validator.register_validator(
'regex',
regex_val,
Validator.register_validator('regex', regex_val, \
'RegEx name validator (take re as argument)')
Validator.create_list_validator(
'list',
Validator('strip'),
description = "Simple list validator. Validate a list of values separated by ','",
separator = ',')
Validator.create_list_validator('list', Validator('strip'), description=\
"Simple list validator. Validate a list of values separated by ','", \
separator=',')
Validator.create_list_validator(
'directory_list',
Validator('directory'),
description = "Validator for a list of directory path separated with ','",
separator = ',')
Validator.create_list_validator( \
'directory_list', \
Validator('directory'), \
description="Validator for a list of directory path separated with ','", \
separator=',')
Validator.create_write_list_validator(
'write_list',
Validator('directory'),
description = "Validator for an array of values which will be set in a string, separated by ','",
separator = ',')
Validator.create_write_list_validator( \
'write_list', \
Validator('directory'), \
description="Validator for an array of values \
which will be set in a string, separated by ','",
separator=',')
Validator.create_re_validator(
r'^https?://[^\./]+.[^\./]+/?.*$',
'http_url',
Validator.create_re_validator( \
r'^https?://[^\./]+.[^\./]+/?.*$', \
'http_url', \
'Url validator')
##@brief Validator for Editorial model component
#
# Designed to validate a conf that indicate a class.field in an EM
#@todo modified the hardcoded dyncode import (it's a warning)
def emfield_val(value):
LodelContext.expose_modules(globals(), {
'lodel.plugin.hooks': ['LodelHook']})
LodelContext.expose_modules(globals(), \
{'lodel.plugin.hooks': ['LodelHook']})
spl = value.split('.')
if len(spl) != 2:
msg = "Expected a value in the form CLASSNAME.FIELDNAME but got : %s"
@ -357,7 +314,7 @@ def emfield_val(value):
@LodelHook('lodel2_dyncode_bootstraped')
def emfield_conf_check(hookname, caller, payload):
import leapi_dyncode as dyncode # <-- dirty & quick
classnames = { cls.__name__.lower():cls for cls in dyncode.dynclasses}
classnames = { cls.__name__.lower(): cls for cls in dyncode.dynclasses}
if value[0].lower() not in classnames:
msg = "Following dynamic class do not exists in current EM : %s"
raise SettingsValidationError(msg % value[0])
@ -370,14 +327,14 @@ def emfield_val(value):
##@brief Validator for plugin name & optionnaly type
#
#Able to check that the value is a plugin and if it is of a specific type
def plugin_validator(value, ptype = None):
LodelContext.expose_modules(globals(), {
def plugin_validator(value, ptype=None):
LodelContext.expose_modules(globals(), { \
'lodel.plugin.hooks': ['LodelHook']})
value = copy.copy(value)
@LodelHook('lodel2_dyncode_bootstraped')
def plugin_type_checker(hookname, caller, payload):
LodelContext.expose_modules(globals(), {
'lodel.plugin.plugins': ['Plugin'],
LodelContext.expose_modules(globals(), { \
'lodel.plugin.plugins': ['Plugin'], \
'lodel.plugin.exceptions': ['PluginError']})
if value is None:
return
@ -395,14 +352,14 @@ named '%s' that is a '%s' plugin"
return value
Validator.register_validator(
'plugin',
plugin_validator,
Validator.register_validator( \
'plugin', \
plugin_validator, \
'plugin name & type validator')
Validator.register_validator(
'emfield',
emfield_val,
Validator.register_validator( \
'emfield', \
emfield_val, \
'EmField name validator')
#
@ -427,38 +384,30 @@ def confspec_append(orig, section, key, validator, default):
##@brief Global specifications for lodel2 settings
LODEL2_CONF_SPECS = {
'lodel2': {
'debug': ( True,
Validator('bool')),
'sitename': ( 'noname',
Validator('strip')),
'runtest': ( False,
Validator('bool')),
'debug': (True, Validator('bool')),
'sitename': ('noname', Validator('strip')),
'runtest': (False, Validator('bool')),
},
'lodel2.logging.*' : {
'level': ( 'ERROR',
Validator('loglevel')),
'context': ( False,
Validator('bool')),
'filename': ( "-",
Validator('errfile', none_is_valid = False)),
'backupcount': ( 5,
Validator('int', none_is_valid = False)),
'maxbytes': ( 1024*10,
Validator('int', none_is_valid = False)),
'level': ('ERROR', Validator('loglevel')),
'context': (False, Validator('bool')),
'filename': ("-", Validator('errfile', none_is_valid=False)),
'backupcount': (5, Validator('int', none_is_valid=False)),
'maxbytes': (1024*10, Validator('int', none_is_valid=False)),
},
'lodel2.editorialmodel': {
'emfile': ( 'em.pickle', Validator('strip')),
'emtranslator': ( 'picklefile', Validator('strip')),
'dyncode': ( 'leapi_dyncode.py', Validator('strip')),
'groups': ( '', Validator('list')),
'editormode': ( False, Validator('bool')),
'emfile': ('em.pickle', Validator('strip')),
'emtranslator': ('picklefile', Validator('strip')),
'dyncode': ('leapi_dyncode.py', Validator('strip')),
'groups': ('', Validator('list')),
'editormode': (False, Validator('bool')),
},
'lodel2.datasources.*': {
'read_only': (False, Validator('bool')),
'identifier': ( None, Validator('string')),
'identifier': (None, Validator('string')),
},
'lodel2.auth': {
'login_classfield': ('user.login', Validator('emfield')),
'pass_classfield': ('user.password', Validator('emfield')),
},
}
}