Commit dbe9fb83 authored by Julius Metz's avatar Julius Metz

add validate config function

parent 20dad27f
......@@ -34,9 +34,105 @@ DEFAULT_FILTER = 'average'
### validation Config
# required Config values
CONFIG_VARIABLES = ['NEEDED_VALUES_DEFAULTS', 'NEEDED_VALUES', 'PLOTS_CONFIG',
'NAME_SPEZIAL_PARAMETER', 'COMAND_BLACKLIST', 'PLOTLY_COLORS', 'PLOTLY_STATIC_COLORS']
# Merger that exist and posible kwargs/parameter
MERGER = {
'x2oneaddition_int': {
'roundingpoint': {'type':int},
'operator': {'type': str, 'choices': ['+', '-', '*', '/', '%']},
'operator_value': {'type': (int, float)},
},
'x2oneaddition_float': {
'roundingpoint': {'type':int},
'operator': {'type': str, 'choices': ['+', '-', '*', '/', '%']},
'operator_value': {'type': (int, float)},
}
}
# validation infos of config
# key = config variablename to validate
# value = validator dict or type/tuple of types
# hints!!!!
# '__merger__' can be used as type for the merger tuple.
# in fixed_keys and 'changing_keys' the 'validator' need not be given if sub-elements are not to be validated.
#
# validator dict has follow structur:
# 'type' : required, is the possible type/s of the obj that are valid
# 'emptyable': list/dict/tuple can be empty if emptyable is True. Default: False
# 'subvalue_validator': is a validatordict or type/tuple of types to check all elems are valid if type is list/tuple
# 'fixed_keys': only if type is dict. takes a dict:
# key: a known key of the current dict that is checked
# value: dict with following possible keys:
# 'required': if False the key must not in the dict Default: True
# 'validator': is a validatordict or type/tuple of types to validate the value
# 'changing_keys': only if type is dict. takes a dict:
# 'key_type': type of the keys in the dict current dict
# 'validator': is a validatordict or type/tuple of types to validate the values of the dict
#
VALIDATIONS_INFOS = {
'NEEDED_VALUES_DEFAULTS': {
'type': dict,
'fixed_keys': {
'default_base_value': {},
'default_merger': {'validator': '__merger__'},
},
},
'NEEDED_VALUES': {
'type': dict,
'changing_keys': {
'key_type': str,
'validator': {
'type': dict,
'fixed_keys': {
'keys': {'validator': {'type': list, 'subvalue_validator': str}},
'merger': {'validator': '__merger__'},
'base_value': {'required': False}
},
},
},
},
'PLOTS_CONFIG': {
'type': list,
'subvalue_validator': {
'type': dict,
'fixed_keys': {
'name': {'validator': str},
'needed_key': {'validator': str},
'relative-absolute_xaxis': {'required': False, 'validator': bool},
'plotly_settings': {'validator': dict},
},
},
},
'NAME_SPEZIAL_PARAMETER': {
'type': dict,
'emptyable': True,
'changing_keys': {
'key_type': str,
'validator': {
'type': list,
'emptyable':True,
'subvalue_validator': str,
},
},
},
'COMAND_BLACKLIST': {
'type': list,
'emptyable': True,
'subvalue_validator': str,
},
'PLOTLY_COLORS': {
'type': list,
'subvalue_validator': str,
},
'PLOTLY_STATIC_COLORS': {
'type': dict,
'emptyable': True,
'changing_keys': {
'key_type': str,
'validator': str,
},
},
}
### Other
......@@ -67,6 +163,112 @@ FIELDS_PATTERN = re.compile(r'(?:(?:\s*[^\\]|\A)\"(.*?[^\\]|)\"|(?:\s+|\A)(?=[^\
#(?:\"(.*?)\"|(\S+))
def is_merger(to_check):
"""Check is given obj a valid merger. Possible merger are given in MERGER.
Arguments:
to_check {unkown} -- obj to test
Returns:
(bool, str) -- return true if it is a merger false and error if not
"""
try:
name, mergerkwargs = to_check
except ValueError:
return False, "'{0}' has no right merger structur expected: (name[str], kwargs[dict])".format(to_check)
if isinstance(name, str) and isinstance(mergerkwargs, dict):
if name in MERGER:
for kwarg_name, value in mergerkwargs.items():
if kwarg_name in MERGER[name]:
if 'choices' in MERGER[name][kwarg_name]:
if not value in MERGER[name][kwarg_name]['choices']:
return False, '{0} {1} expect one of {2} got: {3}'.format(
name, kwarg_name, MERGER[name][kwarg_name]['choices'], value
)
else:
if not isinstance(value, MERGER[name][kwarg_name]['type']):
return False, '{1} of {0} expect {2} not {3}'.format(
name, kwarg_name, MERGER[name][kwarg_name]['type'], type(value)
)
else:
return False, '{1} is unknown parameter of {0}'.format(name, kwarg_name)
else:
return False, '"{0}" is unknown merger'.format(name)
else:
return False, '"{0}" has no right merger structur expected: (name[str], kwargs[dict])'.format(to_check)
return True, None
def check_valid(to_check, validationinfos):
"""check object is valid from the perspective of validationinfos
Arguments:
to_check {unkown} -- object to check is valid
validationinfos {dict or type or tuple with types} -- infos what is needed that to_check is valid
Returns:
(bool, str) -- return true if it is valid, false and error if not
"""
if isinstance(validationinfos, dict):
if validationinfos['type'] == '__merger__':
return is_merger(to_check)
else:
if isinstance(to_check, validationinfos['type']):
if validationinfos['type'] == dict:
if not validationinfos.get('emptyable', False) and not len(to_check):
return False, '{0} can not be empty!'.format(to_check)
for fixed_name, infos in validationinfos.get('fixed_keys', {}).items():
if fixed_name in to_check:
if 'validator' in infos:
valid, error_msg = check_valid(to_check[fixed_name], infos['validator'])
if not valid:
return valid, '[{0}] => {1}'.format(fixed_name, error_msg)
elif infos.get('required', True):
return False, '{0} missing key: "{1}"'.format(to_check, fixed_name)
if 'changing_keys' in validationinfos:
for key, subvalue in to_check.items():
if not isinstance(key, validationinfos['changing_keys']['key_type']):
return False, '{0} key has wrong type expected {1} got {2}'.format(
key, validationinfos['changing_keys']['key_type'], type(key),
)
if 'validator' in validationinfos['changing_keys']:
valid, error_msg = check_valid(subvalue, validationinfos['changing_keys']['validator'])
if not valid:
return valid, '[{0}] => {1}'.format(key, error_msg)
if validationinfos['type'] == list or validationinfos['type'] == tuple:
if not validationinfos.get('emptyable', False) and not len(to_check):
return False, '{0} can not be empty!'.format(to_check)
if 'subvalue_validator' in validationinfos:
for i, subvalue in enumerate(to_check):
valid, error_msg = check_valid(subvalue, validationinfos['subvalue_validator'])
if not valid:
return valid, '[{0}] => {1}'.format(i, error_msg)
else:
return False, '{0} is wrong type expected {1} got {2}'.format(
to_check, validationinfos['type'], type(to_check)
)
else:
if validationinfos == '__merger__':
return is_merger(to_check)
else:
if not isinstance(to_check, validationinfos):
return False, '{0} is {1} expected: {2}'.format(
to_check, type(to_check), validationinfos,
)
return True, None
def datestr2date(datestr):
"""Converts a "datestring" to a date Object.
......@@ -509,13 +711,17 @@ def main(source, collectl, plotlypath, destination, configpath,
# validate config and make dict from values
config = {}
for config_var_name in CONFIG_VARIABLES:
a = time.time()
for config_var_name, validator_dict in VALIDATIONS_INFOS.items():
try:
config[config_var_name] = getattr(config_module, config_var_name)
except AttributeError:
print('{} missing in config'.format(config_var_name))
exit(1)
valid, errormsg = check_valid(config[config_var_name], validator_dict)
if not valid:
print('In {0}: \n{1}'.format(config_var_name, errormsg))
exit(1)
data_colllect_functions = []
for source_path in source_paths:
......
......@@ -286,6 +286,7 @@ A merger is a function that merge a values from collectl to existing base value.
### Add new Merger
In default it gives only two filter but in value_merger.py it is possible to add more.
If one merger is added in value_merger.py he must be added in the global var MERGER in Collectl2plotly.py.
#### Arguments of a merger function
1. base value is the initial value for merging on it. Normaly has the same type like the return value
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment