diff --git a/stateengine/StateEngineAction.py b/stateengine/StateEngineAction.py index 5f7258798..00b236358 100755 --- a/stateengine/StateEngineAction.py +++ b/stateengine/StateEngineAction.py @@ -301,7 +301,6 @@ def check_getitem_fromeval(self, check_item, check_value=None, check_mindelta=No def check_complete(self, state, check_item, check_status, check_mindelta, check_value, action_type, evals_items=None, use=None): _issue = {self._name: {'issue': None, 'issueorigin': [{'state': state.id, 'action': self._function}]}} - self._log_develop("For action {} check item {} status {} mindelta {} value {} actiontype {}, use {} evals_items {}", self, check_item, check_status, check_mindelta, check_value, action_type, use, evals_items) try: _name = evals_items.get(self.name) if _name is not None: diff --git a/stateengine/StateEngineActions.py b/stateengine/StateEngineActions.py index 35723c2b7..5bae5e249 100755 --- a/stateengine/StateEngineActions.py +++ b/stateengine/StateEngineActions.py @@ -334,12 +334,12 @@ def __ensure_action_exists(self, func, name): return True, _issue_list def __handle_combined_action_attribute(self, name, value_list): - def remove_action(ex): + def remove_action(e): if name in self.__actions: del self.__actions[name] - _issue = {name: {'issue': [ex], 'issueorigin': [{'state': 'unknown', 'action': parameter['function']}], 'ignore': True}} - _issue_list.append(_issue) - self._log_warning("Ignoring action {0} because: {1}", name, ex) + i = {name: {'issue': [e], 'issueorigin': [{'state': 'unknown', 'action': parameter['function']}], 'ignore': True}} + _issue_list.append(i) + self._log_warning("Ignoring action {0} because: {1}", name, e) parameter = {'function': None, 'force': None, 'repeat': None, 'delay': 0, 'order': None, 'nextconditionset': None, 'conditionset': None, 'previousconditionset': None, 'previousstate_conditionset': None, 'mode': None, 'instanteval': None} diff --git a/stateengine/StateEngineCondition.py b/stateengine/StateEngineCondition.py index e2ebabbe1..737130c34 100755 --- a/stateengine/StateEngineCondition.py +++ b/stateengine/StateEngineCondition.py @@ -292,14 +292,14 @@ def complete(self, state, use): if all(item is None for item in [self.__item, self.__status, self.__eval, self.__status_eval]): raise ValueError("Neither 'item' nor 'status' nor '(status)eval' given!") - if any(item is not None for item in [self.__item, self.__status, self.__eval, self.__status_eval])\ - and not self.__changedby.is_empty() and self.__changedbynegate is None: + if any(item is not None for item in [self.__item, self.__status, self.__eval, self.__status_eval]) \ + and not self.__changedby.is_empty() and self.__changedbynegate is None: self.__changedbynegate = False - if any(item is not None for item in [self.__item, self.__status, self.__eval, self.__status_eval])\ - and not self.__updatedby.is_empty() and self.__updatedbynegate is None: + if any(item is not None for item in [self.__item, self.__status, self.__eval, self.__status_eval]) \ + and not self.__updatedby.is_empty() and self.__updatedbynegate is None: self.__updatedbynegate = False - if any(item is not None for item in [self.__item, self.__status, self.__eval, self.__status_eval])\ - and not self.__triggeredby.is_empty() and self.__triggeredbynegate is None: + if any(item is not None for item in [self.__item, self.__status, self.__eval, self.__status_eval]) \ + and not self.__triggeredby.is_empty() and self.__triggeredbynegate is None: self.__triggeredbynegate = False # cast stuff @@ -462,19 +462,19 @@ def __convert(convert_value, convert_current): self.__value.set_cast(StateEngineTools.cast_str) convert_value = StateEngineTools.cast_str(convert_value) convert_current = StateEngineTools.cast_str(convert_current) - if not type(_oldvalue) == type(convert_value): + if not type(_oldvalue) is type(convert_value): self._log_debug("Value {} was type {} and therefore not the same" " type as item value {}. It got converted to {}.", _oldvalue, type(_oldvalue), convert_current, type(convert_value)) return convert_value, convert_current - current = self.__get_current(eval_type='changedby') if valuetype == "changedby" else\ - self.__get_current(eval_type='updatedby') if valuetype == "updatedby" else\ - self.__get_current(eval_type='triggeredby') if valuetype == "triggeredby" else\ + current = self.__get_current(eval_type='changedby') if valuetype == "changedby" else \ + self.__get_current(eval_type='updatedby') if valuetype == "updatedby" else \ + self.__get_current(eval_type='triggeredby') if valuetype == "triggeredby" else \ self.__get_current(eval_type='value') - negate = self.__changedbynegate if valuetype == "changedby" else\ - self.__updatedbynegate if valuetype == "updatedby" else\ - self.__triggeredbynegate if valuetype == "triggeredby" else\ + negate = self.__changedbynegate if valuetype == "changedby" else \ + self.__updatedbynegate if valuetype == "updatedby" else \ + self.__triggeredbynegate if valuetype == "triggeredby" else \ self.__negate _key_current = ['{}'.format(state.id), 'conditionsets', '{}'.format( self._abitem.get_variable('current.conditionset_name')), '{}'.format(self.__name), @@ -490,20 +490,20 @@ def __convert(convert_value, convert_current): for i, element in enumerate(value): regex_result = None regex_check = False - if valuetype == "value" and type(element) != type(current) and current is not None: + if valuetype == "value" and type(element) is not type(current) and current is not None: element, current = __convert(element, current) if isinstance(element, re.Pattern): regex_result = element.fullmatch(str(current)) regex_check = True if negate: - if (regex_result is not None and regex_check is True)\ - or (current == element and regex_check is False): + if (regex_result is not None and regex_check is True) \ + or (current == element and regex_check is False): self._log_debug("{0} found but negated -> not matching", element) self._abitem.update_webif(_key_match, 'no') return False else: - if (regex_result is not None and regex_check is True)\ - or (current == element and regex_check is False): + if (regex_result is not None and regex_check is True) \ + or (current == element and regex_check is False): self._log_debug("{0} found -> matching", element) self._abitem.update_webif(_key_match, 'yes') return True @@ -522,7 +522,7 @@ def __convert(convert_value, convert_current): regex_result = None regex_check = False # If current and value have different types, convert both to string - if valuetype == "value" and type(value) != type(current) and current is not None: + if valuetype == "value" and type(value) is not type(current) and current is not None: value, current = __convert(value, current) text = "Condition '{0}': {1}={2} negate={3} current={4}" self._abitem.update_webif(_key_current, str(current)) @@ -532,14 +532,14 @@ def __convert(convert_value, convert_current): regex_result = value.fullmatch(str(current)) regex_check = True if negate: - if (regex_result is None and regex_check is True)\ - or (current != value and regex_check is False): + if (regex_result is None and regex_check is True) \ + or (current != value and regex_check is False): self._log_debug("not OK but negated -> matching") self._abitem.update_webif(_key_match, 'yes') return True else: - if (regex_result is not None and regex_check is True)\ - or (current == value and regex_check is False): + if (regex_result is not None and regex_check is True) \ + or (current == value and regex_check is False): self._log_debug("OK -> matching") self._abitem.update_webif(_key_match, 'yes') return True @@ -823,10 +823,10 @@ def check_eval(eval_or_status_eval): eval_result = eval(eval_or_status_eval) if isinstance(eval_result, self.__itemClass): value = eval_result.property.last_change_age if eval_type == 'age' else \ - eval_result.property.last_change_by if eval_type == 'changedby' else \ - eval_result.property.last_update_by if eval_type == 'updatedby' else \ - eval_result.property.last_trigger_by if eval_type == 'triggeredby' else \ - eval_result.property.value + eval_result.property.last_change_by if eval_type == 'changedby' else \ + eval_result.property.last_update_by if eval_type == 'updatedby' else \ + eval_result.property.last_trigger_by if eval_type == 'triggeredby' else \ + eval_result.property.value else: value = eval_result except Exception as ex: @@ -840,10 +840,10 @@ def check_eval(eval_or_status_eval): if self.__status is not None: # noinspection PyUnusedLocal self._log_debug("Trying to get {} of status item {}", eval_type, self.__status.property.path) - return self.__status.property.last_change_age if eval_type == 'age' else\ - self.__status.property.last_change_by if eval_type == 'changedby' else\ - self.__status.property.last_update_by if eval_type == 'updatedby' else\ - self.__status.property.last_trigger_by if eval_type == 'triggeredby' else\ + return self.__status.property.last_change_age if eval_type == 'age' else \ + self.__status.property.last_change_by if eval_type == 'changedby' else \ + self.__status.property.last_update_by if eval_type == 'updatedby' else \ + self.__status.property.last_trigger_by if eval_type == 'triggeredby' else \ self.__status.property.value elif self.__status_eval is not None: self._log_debug("Trying to get {} of statuseval {}", eval_type, self.__status_eval) @@ -852,10 +852,10 @@ def check_eval(eval_or_status_eval): elif self.__item is not None: # noinspection PyUnusedLocal self._log_debug("Trying to get {} of item {}", eval_type, self.__item.property.path) - return self.__item.property.last_change_age if eval_type == 'age' else\ - self.__item.property.last_change_by if eval_type == 'changedby' else\ - self.__item.property.last_update_by if eval_type == 'updatedby' else\ - self.__item.property.last_trigger_by if eval_type == 'triggeredby' else\ + return self.__item.property.last_change_age if eval_type == 'age' else \ + self.__item.property.last_change_by if eval_type == 'changedby' else \ + self.__item.property.last_update_by if eval_type == 'updatedby' else \ + self.__item.property.last_trigger_by if eval_type == 'triggeredby' else \ self.__item.property.value elif self.__eval is not None: self._log_debug("Trying to get {} of eval {}", eval_type, self.__eval) diff --git a/stateengine/StateEngineFunctions.py b/stateengine/StateEngineFunctions.py index ae5c2d7b1..1e869d033 100755 --- a/stateengine/StateEngineFunctions.py +++ b/stateengine/StateEngineFunctions.py @@ -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 diff --git a/stateengine/StateEngineItem.py b/stateengine/StateEngineItem.py index aa4ce8285..57da47a73 100755 --- a/stateengine/StateEngineItem.py +++ b/stateengine/StateEngineItem.py @@ -217,8 +217,9 @@ def __init__(self, smarthome, item, se_plugin): self.__log_level = StateEngineValue.SeValue(self, "Log Level", False, "num") _default_log_level = self.__logger.default_log_level.get() - _returnvalue, _returntype, _using_default, _issue, _ = self.__log_level.set_from_attr(self.__item, "se_log_level", - _default_log_level) + _returnvalue, _returntype, _using_default, _issue, _ = self.__log_level.set_from_attr(self.__item, + "se_log_level", + _default_log_level) self.__using_default_log_level = _using_default _returnvalue = self.__log_level.get() if isinstance(_returnvalue, list) and len(_returnvalue) == 1: @@ -880,10 +881,10 @@ def __update_can_release(self, can_release, new_state=None): def __handle_releasedby(self, new_state, last_state, instant_leaveaction): def update_can_release_list(): - for e in _returnvalue: - e = self.__update_release_item_value(e, new_state) - e = e if isinstance(e, list) else [e] - for entry in e: + for r in _returnvalue: + r = self.__update_release_item_value(r, new_state) + r = r if isinstance(r, list) else [r] + for entry in r: if entry and state.id not in can_release.setdefault(entry, [state.id]): can_release[entry].append(state.id) @@ -1046,19 +1047,19 @@ def update_list(existing, new_entries): existing.append(entry) return existing - combined_dict = dict1.copy() + comb_dict = dict1.copy() for key, value in dict2.items(): - if key not in combined_dict: - combined_dict[key] = value + if key not in comb_dict: + comb_dict[key] = value continue - combined_entry = combined_dict[key] + combined_entry = comb_dict[key] if 'issue' in value: combined_entry['issue'] = update_list(combined_entry.get('issue', []), value['issue']) if 'issueorigin' in value: combined_entry['issueorigin'] = update_list(combined_entry.get('issueorigin', []), value['issueorigin']) - return combined_dict + return comb_dict if issue_type == "state": combined_dict = combine_dicts(issues, self.__state_issues) @@ -1317,7 +1318,7 @@ def __initialize_state(self, item_state, _statecount): _issue = _state.update_order(_statecount) if _issue: self.__config_issues.update({item_state.property.path: - {'issue': _issue, 'attribute': 'se_stateorder'}}) + {'issue': _issue, 'attribute': 'se_stateorder'}}) self.__logger.error("Issue with state {0} while setting order: {1}", item_state.property.path, _issue) self.__states.append(_state) @@ -1330,13 +1331,13 @@ def __initialize_state(self, item_state, _statecount): return _statecount + 1 except ValueError as ex: self.update_issues('state', {item_state.property.path: {'issue': ex, 'issueorigin': - [{'conditionset': 'None', 'condition': 'ValueError'}]}}) + [{'conditionset': 'None', 'condition': 'ValueError'}]}}) self.__logger.error("Ignoring state {0} because ValueError: {1}", item_state.property.path, ex) return _statecount except Exception as ex: self.update_issues('state', {item_state.property.path: {'issue': ex, 'issueorigin': - [{'conditionset': 'None', 'condition': 'GeneralError'}]}}) + [{'conditionset': 'None', 'condition': 'GeneralError'}]}}) self.__logger.error("Ignoring state {0} because: {1}", item_state.property.path, ex) return _statecount @@ -1790,11 +1791,11 @@ def process_returnvalue(value): return _returnvalue_issue def update_can_release_list(): - for i, value in enumerate(_convertedlist): - if _converted_typelist[i] == 'item': - value = self.__update_release_item_value(_converted_evaluatedlist[i], state) - elif _converted_typelist[i] == 'eval': - value = _converted_evaluatedlist[i] + for z, value in enumerate(_convertedlist): + if _converted_typelist[z] == 'item': + value = self.__update_release_item_value(_converted_evaluatedlist[z], state) + elif _converted_typelist[z] == 'eval': + value = _converted_evaluatedlist[z] value = value if isinstance(value, list) else [value] for v in value: if v and can_release.get(v) and state.id not in can_release.get(v): @@ -1913,7 +1914,7 @@ def cli_detail(self, handler): handler.push("\tPrevious conditionset: {0} ('{1}')\n".format(self.get_previousconditionset_id(), self.get_previousconditionset_name())) handler.push("\tNext conditionset: {0} ('{1}')\n".format(self.get_nextconditionset_id(), - self.get_nextconditionset_name())) + self.get_nextconditionset_name())) handler.push(self.__startup_delay.get_text("\t", "\n")) handler.push("\tCycle: {0}\n".format(cycles)) handler.push("\tCron: {0}\n".format(crons)) diff --git a/stateengine/StateEngineState.py b/stateengine/StateEngineState.py index 4a236e031..5d241a940 100755 --- a/stateengine/StateEngineState.py +++ b/stateengine/StateEngineState.py @@ -489,9 +489,8 @@ def __initialize_se_use(self, state, recursion_depth): _configorigvalue[i] in item)): _issue_list = [item for key, value in _issues.items() if value for item in value] self._log_warning("se_use {} points to invalid item. Ignoring.", _configorigvalue[i]) - self._abitem.update_issues('config', {state.id: - {'issue': _issue_list, - 'attribute': 'se_use', 'origin': state_type}}) + self._abitem.update_issues('config', {state.id: {'issue': _issue_list, + 'attribute': 'se_use', 'origin': state_type}}) self.__use_ignore_list.append(_configorigvalue[i]) _path = None elif _returntype[i] in ['item', 'eval']: @@ -505,9 +504,8 @@ def __initialize_se_use(self, state, recursion_depth): _issue_list = [item for key, value in _issues.items() if value for item in value] self._log_warning("se_use {} defined by invalid item/eval. Ignoring.", _path) - self._abitem.update_issues('config', {state.id: - {'issue': _issue_list, - 'attribute': 'se_use', 'origin': state_type}}) + self._abitem.update_issues('config', {state.id: {'issue': _issue_list, + 'attribute': 'se_use', 'origin': state_type}}) self.__use_ignore_list.append(_path) _path = None if _path is None: diff --git a/stateengine/StateEngineStructs.py b/stateengine/StateEngineStructs.py index de630d0ab..98a6afeb2 100755 --- a/stateengine/StateEngineStructs.py +++ b/stateengine/StateEngineStructs.py @@ -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}) diff --git a/stateengine/StateEngineValue.py b/stateengine/StateEngineValue.py index 061f231df..b5aefdf75 100755 --- a/stateengine/StateEngineValue.py +++ b/stateengine/StateEngineValue.py @@ -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): @@ -470,7 +471,6 @@ def get_type(self): # Write condition to logger def write_to_logger(self): - eval_result = None if self.__template is not None: self._log_info("{0}: Using template(s) {1}", self.__name, self.__template) if self.__value is not None: @@ -1007,6 +1007,6 @@ def update_value(varname): var, values[-1], self.__listorder) else: values = update_value(self.__varname) - self._log_debug("Variable result: {0}", values) + self._log_debug("Variable result: {0}", values) return values diff --git a/stateengine/StateEngineWebif.py b/stateengine/StateEngineWebif.py index ab3e4df9b..4a9b99b06 100755 --- a/stateengine/StateEngineWebif.py +++ b/stateengine/StateEngineWebif.py @@ -59,19 +59,27 @@ def __init__(self, abitem): def __repr__(self): return "WebInterface item: {}, id {}".format(self.__states, self.__name) if REQUIRED_PACKAGE_IMPORTED else "None" + def _strip_regex(self, regex_list): + pattern_strings = [] + if not isinstance(regex_list, list): + regex_list = [regex_list] + for item in regex_list: + if isinstance(item, re.Pattern): + pattern_strings.append(item.pattern) + else: + pattern_match = re.search(r"re\.compile\('([^']*)'", item) + if pattern_match: + item = f"regex:{pattern_match.group(1)}" + pattern_strings.append(str(item)) + if len(pattern_strings) <= 1: + pattern_strings = pattern_strings[0] + return str(pattern_strings) + def _actionlabel(self, state, label_type, conditionset, previousconditionset, previousstate_conditionset, next_conditionset): # Check if conditions for action are met or not # action_dict: abitem[state]['on_enter'/'on_stay'/'on_enter_or_stay'/'on_leave'].get(action) # condition_to_meet: 'conditionset'/'previousconditionset'/'previousstate_conditionset'/'nextconditionset' # conditionset: name of conditionset that should get checked - def _strip_regex(regex_list): - pattern_strings = [] - for item in regex_list: - if isinstance(item, re.Pattern): - pattern_strings.append(item.pattern) - else: - pattern_strings.append(str(item)) - return str(pattern_strings) def _check_webif_conditions(action_dict, condition_to_meet: str, conditionset: str): _condition_check = action_dict.get(condition_to_meet) @@ -136,10 +144,10 @@ def _check_webif_conditions(action_dict, condition_to_meet: str, conditionset: s (not condition_met or (_repeat is False and originaltype == 'actions_stay'))) \ else "#5c5646" if _delay > 0 else "darkred" if _delay < 0 \ else "#303030" if not condition_met or _issue else "black" - condition_info = _strip_regex(condition_to_meet) if condition1 is False \ - else _strip_regex(previouscondition_to_meet) if condition2 is False \ - else _strip_regex(previousstate_condition_to_meet) if condition3 is False \ - else _strip_regex(next_condition_to_meet) if condition4 is False \ + condition_info = self._strip_regex(condition_to_meet) if condition1 is False \ + else self._strip_regex(previouscondition_to_meet) if condition2 is False \ + else self._strip_regex(previousstate_condition_to_meet) if condition3 is False \ + else self._strip_regex(next_condition_to_meet) if condition4 is False \ else "" if _issue: if tooltip_count > 0: @@ -237,7 +245,7 @@ def _conditionlabel(self, state, conditionset, i): text = " Current {}".format(current_clean) if current and len(current) > 0 else " Not evaluated." conditionlist += ('' - '' + '' '
{}:{}
').format(condition.upper(), text) conditions_done.append(condition) conditionlist += '' @@ -246,6 +254,7 @@ def _conditionlabel(self, state, conditionset, i): info_eval = str(condition_dict.get('eval') or '') info_status_eval = str(condition_dict.get('status_eval') or '') info_compare = str(condition_dict.get(compare) or '') + info_compare = self._strip_regex(info_compare) if not status_none: textlength = len(info_status) if textlength > self.__textlimit: @@ -502,7 +511,7 @@ def drawgraph(self, filename): self.__nodes['{}_{}'.format(state, conditionset)] = pydotplus.Node( '{}_{}'.format(state, conditionset), style="filled", fillcolor=color, shape="diamond", label=label, pos=position) - #self._log_debug('Node {} {} drawn', state, conditionset) + #self._log_debug('Node {} {} drawn. Conditionlist {}', state, conditionset, conditionlist) position = '{},{}!'.format(0.2, new_y) xlabel = '1 tooltip' if condition_tooltip_count == 1\ else '{} tooltips'.format(condition_tooltip_count)\ @@ -562,7 +571,7 @@ def drawgraph(self, filename): xlabel = "" if j == 0: self.__graph.add_edge(pydotplus.Edge(self.__nodes[state], self.__nodes['{}_right'.format(state)], - style='bold', color='black', dir='none', + style='bold', color='black', dir='none', xlabel=xlabel, edgetooltip='check first conditionset')) self.__graph.add_edge(pydotplus.Edge(self.__nodes['{}_right'.format(state)], self.__nodes['{}_{}'.format(state, conditionset)],