Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stateengine #961

Merged
merged 29 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
22cb4a7
stateengine plugin: improve condition check of actions (much faster)
onkelandy Sep 1, 2024
2431e44
stateengine plugin: fix previousstate_conditions set valuation
onkelandy Sep 1, 2024
b36c73e
stateengine plugin: introduce next_conditionset to check conditionset…
onkelandy Sep 1, 2024
65ca7ef
stateengine plugin: update docu for next conditionset
onkelandy Sep 1, 2024
42b90c8
stateengine plugin: minor logging and docu improvements
onkelandy Sep 1, 2024
f67c86d
stateengine plugin: introduce caching of eval results to improve perf…
onkelandy Sep 1, 2024
dbf079e
stateengine plugin: add nextconditionset to web interface
onkelandy Sep 3, 2024
8d94e2a
stateenginge plugin: add nextcondition to source evaluation method
onkelandy Sep 3, 2024
09293d2
stateengine plugin: minor improvements
onkelandy Sep 3, 2024
0764ba8
stateengine plugin: add action_type to action(s) for better webif han…
onkelandy Sep 3, 2024
705e748
stateengine plugin: minor code improvement
onkelandy Sep 3, 2024
d361a3e
stateengine plugin: fix previousonditionset variable
onkelandy Sep 10, 2024
a3aceb2
stateengine plugin: import fix when checking regexes for conditions
onkelandy Sep 11, 2024
a45bbb5
stateengine plugin: minor code adjustments
onkelandy Sep 11, 2024
194d08e
stateengine plugin: improve web interface
onkelandy Sep 11, 2024
611745d
stateengine plugin: major code updates, introduce eval cache feature,…
onkelandy Sep 11, 2024
dfc14fb
stateengine plugin: introduce actions_pass, first step
onkelandy Sep 11, 2024
a4576e8
stateengine plugin: run pass actions
onkelandy Sep 11, 2024
3537c36
stateengine plugin: important fix when logging wrongly defined item f…
onkelandy Sep 11, 2024
df90163
stateengine plugin: fix on_pass actions and implement function to sus…
onkelandy Sep 11, 2024
2a0b5cc
stateengine plugin: improve on_pass actions
onkelandy Sep 18, 2024
f1e6223
stateengine plugin: fix variable logging/handling
onkelandy Sep 18, 2024
928ae60
stateengine plugin: improve web interface - include pass actions, opt…
onkelandy Sep 18, 2024
27abe95
stateengine plugin: introduce delta attribute for single actions, int…
onkelandy Sep 18, 2024
4a03688
stateengine plugin: update docu
onkelandy Sep 19, 2024
e24844f
stateengine plugin: simplify log entry when having issues with value …
onkelandy Sep 19, 2024
b07e9e7
stateengine plugin: highly improve and simplify issue finder and logg…
onkelandy Sep 19, 2024
7d65df6
stateengine plugin: improve struct and add se_minagedelta to plugin.yaml
onkelandy Sep 19, 2024
4996381
stateengine plugin: bump version to 2.2.0
onkelandy Sep 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,098 changes: 489 additions & 609 deletions stateengine/StateEngineAction.py

Large diffs are not rendered by default.

122 changes: 96 additions & 26 deletions stateengine/StateEngineActions.py

Large diffs are not rendered by default.

168 changes: 100 additions & 68 deletions stateengine/StateEngineCondition.py

Large diffs are not rendered by default.

12 changes: 5 additions & 7 deletions stateengine/StateEngineConditionSet.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def __init__(self, abitem, name, conditionid):
self.__evals_items = {}
self.__unused_attributes = {}
self.__used_attributes = {}
self.__state = None

def __repr__(self):
return "SeConditionSet {}".format(self.__conditions)
Expand Down Expand Up @@ -150,6 +151,7 @@ def update(self, item, grandparent_item):
# Check the condition set, optimize and complete it
# state: state (item) to read from
def complete(self, state, use):
self.__state = state
conditions_to_remove = []
# try to complete conditions

Expand All @@ -174,25 +176,21 @@ def write_to_logger(self):
for name in self.__conditions:
self._log_info("Condition '{0}':", name)
self._log_increase_indent()
self.__conditions[name].write_to_logger()
_webif = self.__conditions[name].write_to_logger()
_key = [self.__state.id, 'conditionsets', self.name]
self._abitem.update_webif(_key, _webif, True)
self._log_decrease_indent()

def __currentconditionset_set(self, conditionsetid, name):
self._abitem.set_variable('current.conditionset_id', conditionsetid)
self._abitem.set_variable('current.conditionset_name', name)

def __previousconditionset_set(self, conditionsetid, name):
self._abitem.set_variable('previous.conditionset_id', conditionsetid)
self._abitem.set_variable('previous.conditionset_name', name)

# Check all conditions in the condition set. Return
# returns: True = all conditions in set are matching, False = at least one condition is not matching
def all_conditions_matching(self, state):
try:
self._log_info("Check condition set '{0}'", self.__name)
self._log_increase_indent()
self.__previousconditionset_set(self._abitem.get_variable('current.conditionset_id'),
self._abitem.get_variable('current.conditionset_name'))
self.__currentconditionset_set(self.__id.property.path, self.__name)

for name in self.__conditions:
Expand Down
6 changes: 3 additions & 3 deletions stateengine/StateEngineConditionSets.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ def write_to_logger(self):
def one_conditionset_matching(self, state):
if self.count() == 0:
self._log_debug("No condition sets defined -> matching")
return True
return True, ''
for name in self.__condition_sets:
if self.__condition_sets[name].all_conditions_matching(state):
return True
return True, name

return False
return False, ''
12 changes: 6 additions & 6 deletions stateengine/StateEngineFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ def check_include_exclude(entry_type):
# If current value is in list -> Return "Trigger"
for e in conf_entry:
e = re.compile(e, re.IGNORECASE)
result = e.match(original)
elog.info("Checking regex result {}", result)
if result is not None:
r = e.match(original)
elog.info("Checking regex result {}", r)
if r is not None:
elog.info("{0}: matching.", e)
elog.decrease_indent()
returnvalue = retval_trigger if entry_type == "include" else retval_no_trigger
elog.info("Writing value {0}", returnvalue)
return returnvalue
retval = retval_trigger if entry_type == "include" else retval_no_trigger
elog.info("Writing value {0}", retval)
return retval
elog.info("{0}: not matching", e)
elog.decrease_indent()
return None
Expand Down
314 changes: 239 additions & 75 deletions stateengine/StateEngineItem.py

Large diffs are not rendered by default.

232 changes: 126 additions & 106 deletions stateengine/StateEngineState.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion stateengine/StateEngineStructs.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@


def create(_abitem, struct):
_find_result = next((item for item in __allstructs if item["name"] == struct), False)
_find_result = next((item for item in __allstructs if item["name"] == struct), {})
if not _find_result:
created_struct = StateEngineStruct.SeStructMain(_abitem, struct, global_struct)
__allstructs.append({'name': struct, 'struct': created_struct})
Expand Down
79 changes: 67 additions & 12 deletions stateengine/StateEngineValue.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ def set_from_attr(self, item, attribute_name, default_value=None, reset=True, at
self._log_develop("Setting value {0}, attribute name {1}, reset {2}, type {3}",
value, attribute_name, reset, attr_type)
_returnvalue, _returntype, _issue, _origvalue = self.set(value, attribute_name, reset)
self._log_develop("Set from attribute returnvalue {}, returntype {}, issue {}, original {}", _returnvalue, _returntype, _issue, _origvalue)
self._log_develop("Set from attribute returnvalue {}, returntype {}, issue {}, original {}",
_returnvalue, _returntype, _issue, _origvalue)
return _returnvalue, _returntype, _using_default, _issue, _origvalue

def _set_additional(self, _additional_sources):
Expand Down Expand Up @@ -446,10 +447,14 @@ def get(self, default=None, originalorder=True):
else:
return returnvalues

def get_for_webif(self):
returnvalues = self.get()
def get_for_webif(self, value=None):
if value is None:
returnvalues = self.get()
else:
returnvalues = value
returnvalues = self.__varname if returnvalues == '' else returnvalues
return str(returnvalues)
returnvalues = str(returnvalues)
return returnvalues

def get_type(self):
if len(self.__listorder) <= 1:
Expand Down Expand Up @@ -479,13 +484,15 @@ def write_to_logger(self):
self._log_debug("{0}: {1} ({2})", self.__name, i, type(i))
else:
self._log_debug("{0}: {1} ({2})", self.__name, self.__value, type(self.__value))
return self.__value
if self.__regex is not None:
if isinstance(self.__regex, list):
for i in self.__regex:
if i is not None:
self._log_debug("{0} from regex: {1}", self.__name, i)
else:
self._log_debug("{0} from regex: {1}", self.__name, self.__regex)
return f"regex:{self.__regex}"
if self.__struct is not None:
if isinstance(self.__struct, list):
for i in self.__struct:
Expand All @@ -494,29 +501,42 @@ def write_to_logger(self):

else:
self._log_debug("{0} from struct: {1}", self.__name, self.__struct.property.path)
return self.__struct
if self.__item is not None:
_original_listorder = self.__listorder.copy()
items = []
if isinstance(self.__item, list):
for i, item in enumerate(self.__item):
if item is not None:
self._log_debug("{0} from item: {1}", self.__name, item.property.path)
self._log_debug("Currently item results in {}", self.__get_from_item()[i])
current = self.__get_from_item()[i]
items.append(current)
self._log_debug("Currently item results in {}", current)
else:
self._log_debug("{0} from item: {1}", self.__name, self.__item.property.path)
self._log_debug("Currently item results in {}", self.__get_from_item())
items = self.__get_from_item()
self._log_debug("Currently item results in {}", items)
self.__listorder = _original_listorder
return items
if self.__eval is not None:
self._log_debug("{0} from eval: {1}", self.__name, self.__eval)
_original_listorder = self.__listorder.copy()
self._log_debug("Currently eval results in {}. ", self.__get_eval())
eval_result = self.__get_eval()
self._log_debug("Currently eval results in {}. ", eval_result)
self.__listorder = _original_listorder
return eval_result
if self.__varname is not None:
if isinstance(self.__varname, list):
for i in self.__varname:
if i is not None:
self._log_debug("{0} from variable: {1}", self.__name, i)
else:
self._log_debug("{0} from variable: {1}", self.__name, self.__varname)
_original_listorder = self.__listorder.copy()
var_result = self.__get_from_variable()
self.__listorder = _original_listorder
return var_result
return None

# Get Text (similar to logger text)
# prefix: Prefix for text
Expand Down Expand Up @@ -614,7 +634,7 @@ def __do_cast(self, value, item_id=None):
_newvalue = element if element == 'novalue' else self.__cast_func(element)
except Exception as ex:
_newvalue = None
_issue = "Problem casting element '{0}' to {1}: {2}.".format(element, self.__cast_func, ex)
_issue = "Problem casting element '{0}': {1}.".format(element, ex)
self._log_warning(_issue)
valuelist.append(_newvalue)
if element in self.__listorder:
Expand Down Expand Up @@ -644,7 +664,7 @@ def __do_cast(self, value, item_id=None):
_issue = "You most likely forgot to prefix your expression with 'eval:'"
raise ValueError(_issue)
else:
_issue = "Not possible to cast '{}' because {}".format(value, ex)
_issue = "{}".format(ex)
raise ValueError(_issue)
if value in self.__listorder:
self.__listorder[self.__listorder.index(value)] = _newvalue
Expand Down Expand Up @@ -744,13 +764,28 @@ def __get_from_regex(self):
def __get_eval(self):
# noinspection PyUnusedLocal
sh = self._sh
# noinspection PyUnusedLocal
shtime = self._shtime
patterns = [
"get_variable('current.",
'get_variable("current.',
"get_variable('next.",
'get_variable("next.'
]
if isinstance(self.__eval, str):
self.__eval = StateEngineTools.parse_relative(self.__eval, 'sh.', ['()', '.property.'])
if "stateengine_eval" in self.__eval or "se_eval" in self.__eval:
# noinspection PyUnusedLocal
stateengine_eval = se_eval = StateEngineEval.SeEval(self._abitem)
self._log_debug("Checking eval: {0}", self.__eval)
if self.__eval in self._abitem.cache:
self._log_increase_indent()
result = self._abitem.cache.get(self.__eval)
self._log_debug("Loading eval from cache: {}", result)
self._log_decrease_indent()
if 'eval:{}'.format(self.__eval) in self.__listorder:
self.__listorder[self.__listorder.index('eval:{}'.format(self.__eval))] = [result]
return result
self._log_increase_indent()
try:
_newvalue, _issue = self.__do_cast(eval(self.__eval))
Expand All @@ -762,6 +797,8 @@ def __get_eval(self):
values = _newvalue
self._log_decrease_indent()
self._log_debug("Eval result: {0} ({1}).", values, type(values))
if not any(pattern in self.__eval for pattern in patterns):
self._abitem.cache = {self.__eval: values}
self._log_increase_indent()
except Exception as ex:
self._log_decrease_indent()
Expand All @@ -785,6 +822,14 @@ def __get_eval(self):
pass
self._log_debug("Checking eval {0} from list {1}.", val, self.__eval)
self._log_increase_indent()
if val in self._abitem.cache:
result = self._abitem.cache.get(val)
self._log_debug("Loading eval in list from cache: {} ({})", result, type(result))
self._log_decrease_indent()
values.append(result)
if 'eval:{}'.format(val) in self.__listorder:
self.__listorder[self.__listorder.index('eval:{}'.format(val))] = [result]
continue
if isinstance(val, str):
if "stateengine_eval" in val or "se_eval" in val:
# noinspection PyUnusedLocal
Expand Down Expand Up @@ -830,9 +875,19 @@ def __get_eval(self):
value = None
if value is not None:
values.append(value)
if not any(pattern in val for pattern in patterns):
self._abitem.cache = {val: value}
self._log_decrease_indent()
else:
self._log_debug("Checking eval (no str, no list): {0}.", self.__eval)
if self.__eval in self._abitem.cache:
self._log_increase_indent()
result = self._abitem.cache.get(self.__eval)
self._log_debug("Loading eval (no str, no list) from cache: {}", result)
self._log_decrease_indent()
if 'eval:{}'.format(self.__eval) in self.__listorder:
self.__listorder[self.__listorder.index('eval:{}'.format(self.__eval))] = [result]
return result
try:
self._log_increase_indent()
_newvalue, _issue = self.__do_cast(self.__eval())
Expand All @@ -844,6 +899,7 @@ def __get_eval(self):
values = _newvalue
self._log_decrease_indent()
self._log_debug("Eval result (no str, no list): {0}.", values)
self._abitem.cache = {self.__eval: values}
self._log_increase_indent()
except Exception as ex:
self._log_decrease_indent()
Expand Down Expand Up @@ -963,11 +1019,10 @@ def update_value(varname):

if isinstance(self.__varname, list):
for var in self.__varname:
values.append(update_value(var))
self._log_debug("Checking variable in loop '{0}', value {1} from list {2}",
var, values[-1], self.__listorder)
values.append(update_value(var))
else:
values = update_value(self.__varname)
self._log_debug("Variable result: {0}", values)

self._log_debug("Variable result: {0}", values)
return values
Loading
Loading