Skip to content

Commit cb7cd6b

Browse files
Enhencement for remove_state_hops_from_sm and remove_state_from_sm (#559)
* Enhencement for remove_state_hops_from_sm and remove_state_from_sm * style * d * helpers * no more Python 3.7 on CI * f * d * style * test
1 parent 24608a7 commit cb7cd6b

File tree

3 files changed

+844
-40
lines changed

3 files changed

+844
-40
lines changed

moler/device/proxy_pc3.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"""
77

88
__author__ = 'Marcin Usielski'
9-
__copyright__ = 'Copyright (C) 2024, Nokia'
9+
__copyright__ = 'Copyright (C) 2024-2025, Nokia'
1010
__email__ = 'marcin.usielski@nokia.com'
1111
import six
1212
import abc
@@ -45,6 +45,27 @@ def __init__(self, sm_params, name=None, io_connection=None, io_type=None, varia
4545
lazy_cmds_events=lazy_cmds_events)
4646
self._log(level=logging.WARNING, msg="Experimental device. May be deleted at any moment. Please don't use it in your scripts.")
4747

48+
def _get_forbidden_states_no_proxy_pc(self):
49+
"""
50+
Get forbidden states when deleted states - no proxy pc.
51+
:return: dict with forbidden states or None if no forbidden states.
52+
"""
53+
return None
54+
55+
def _get_additional_state_hops_no_proxy_pc(self):
56+
"""
57+
Get additional state hops if states are removed. None if no additional states are required.
58+
:return: dict with additional states or None if no additional states.
59+
"""
60+
return None
61+
62+
def _get_forbidden_hops_no_proxy_pc(self):
63+
"""
64+
Get forbidden state hops when deleted states - no proxy pc.
65+
:return: dict with forbidden hops or None if no forbidden hops.
66+
"""
67+
return None
68+
4869
def _prepare_sm_data(self, sm_params):
4970
self._prepare_dicts_for_sm(sm_params=sm_params)
5071

@@ -102,9 +123,12 @@ def _trim_config_dicts(self, default_sm_configurations, transitions, state_hops)
102123
source_sm=default_sm_configurations[ProxyPc3.connection_hops],
103124
source_transitions=transitions,
104125
state_to_remove=ProxyPc3.proxy_pc,
126+
forbidden=self._get_forbidden_states_no_proxy_pc()
105127
)
106128
state_hops = remove_state_hops_from_sm(
107-
source_hops=state_hops, state_to_remove=ProxyPc3.proxy_pc
129+
source_hops=state_hops, state_to_remove=ProxyPc3.proxy_pc,
130+
additional_hops=self._get_additional_state_hops_no_proxy_pc(),
131+
forbidden_hops=self._get_forbidden_hops_no_proxy_pc(),
108132
)
109133
default_sm_configurations[ProxyPc3.connection_hops] = connection_hops
110134
return (default_sm_configurations, transitions, state_hops)

moler/helpers.py

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55

66
__author__ = "Grzegorz Latuszek, Michal Ernst, Marcin Usielski"
7-
__copyright__ = "Copyright (C) 2018-2024, Nokia"
7+
__copyright__ = "Copyright (C) 2018-2025, Nokia"
88
__email__ = (
99
"grzegorz.latuszek@nokia.com, michal.ernst@nokia.com, marcin.usielski@nokia.com"
1010
)
@@ -577,7 +577,7 @@ def regexp_without_anchors(regexp):
577577
return re.compile(regexp_str)
578578

579579

580-
def remove_state_from_sm(source_sm: dict, source_transitions: dict, state_to_remove: str) -> tuple:
580+
def remove_state_from_sm(source_sm: dict, source_transitions: dict, state_to_remove: str, forbidden: dict = None) -> tuple:
581581
"""
582582
Remove a state from a state machine dict.
583583
:param source_sm: a dict with a state machine description
@@ -594,29 +594,31 @@ def remove_state_from_sm(source_sm: dict, source_transitions: dict, state_to_rem
594594
if to_state == state_to_remove:
595595
states_from_state_to_remove.append(from_state)
596596

597-
for to_state in source_sm[state_to_remove].keys():
597+
for to_state in states_from_state_to_remove:
598598
if to_state == state_to_remove:
599599
continue
600600
for new_from in states_from_state_to_remove:
601-
if new_from != to_state:
602-
break
603-
if new_from not in new_sm:
604-
new_sm[new_from] = {}
605-
if new_from not in new_transitions:
606-
new_transitions[new_from] = {}
607-
608-
new_sm[new_from][to_state] = copy.deepcopy(source_sm[state_to_remove][to_state])
609-
if 'execute_command' in source_sm[new_from][state_to_remove]:
610-
new_sm[new_from][to_state]['execute_command'] = source_sm[new_from][state_to_remove]['execute_command']
611-
612-
if state_to_remove in source_transitions and to_state in source_transitions[state_to_remove]:
613-
new_transitions[new_from][to_state] = copy.deepcopy(source_transitions[state_to_remove][to_state])
614-
else:
615-
new_transitions[new_from][to_state] = {
616-
"action": [
617-
"_execute_command_to_change_state"
618-
],
619-
}
601+
if new_from == to_state:
602+
continue
603+
if forbidden and new_from in forbidden and forbidden[new_from] == to_state:
604+
continue
605+
if new_from not in new_sm:
606+
new_sm[new_from] = {}
607+
if new_from not in new_transitions:
608+
new_transitions[new_from] = {}
609+
610+
new_sm[new_from][to_state] = copy.deepcopy(source_sm[state_to_remove][to_state])
611+
if 'execute_command' in source_sm[new_from][state_to_remove]:
612+
new_sm[new_from][to_state]['execute_command'] = source_sm[new_from][state_to_remove]['execute_command']
613+
614+
if state_to_remove in source_transitions and to_state in source_transitions[state_to_remove]:
615+
new_transitions[new_from][to_state] = copy.deepcopy(source_transitions[state_to_remove][to_state])
616+
else:
617+
new_transitions[new_from][to_state] = {
618+
"action": [
619+
"_execute_command_to_change_state"
620+
],
621+
}
620622

621623
_delete_state(sm=new_sm, state_to_remove=state_to_remove)
622624
_delete_state(sm=new_transitions, state_to_remove=state_to_remove)
@@ -652,34 +654,43 @@ def _delete_empty_states(sm: dict) -> None:
652654
del sm[state]
653655

654656

655-
def remove_state_hops_from_sm(source_hops: dict, state_to_remove: str) -> dict:
657+
def remove_state_hops_from_sm(source_hops: dict, state_to_remove: str, additional_hops: dict = None, forbidden_hops: dict = None) -> dict:
656658
"""
657659
Remove a state from a state machine dict.
658660
:param source_sm: a dict with state machine description
659661
:param state_to_remove: name of state to remove
662+
:param forbidden_hops: dict with forbidden transitions after remove, key is source, value is destination
660663
:return: a new state machine hops dict without state_to_remove
661664
"""
662665
new_hops = copy.deepcopy(source_hops)
663666

664-
for from_state in source_hops.keys():
665-
item = source_hops[from_state]
666-
for dest_state in item.keys():
667-
direct_state = item[dest_state]
668-
if direct_state == state_to_remove:
669-
if state_to_remove in source_hops and dest_state in source_hops[state_to_remove]:
670-
if source_hops[state_to_remove][dest_state] == from_state:
671-
msg = f"Found cycle from '{from_state}' to '{dest_state}' via '{source_hops[state_to_remove][dest_state]}'. Please verify state hops: {source_hops}"
667+
for old_from_state in source_hops.keys():
668+
item = source_hops[old_from_state]
669+
for old_dest_state in item.keys():
670+
old_via_state = item[old_dest_state]
671+
if old_via_state == state_to_remove:
672+
if state_to_remove in source_hops and old_dest_state in source_hops[state_to_remove]:
673+
if source_hops[state_to_remove][old_dest_state] == old_from_state:
674+
msg = f"Found cycle from '{old_from_state}' to '{old_dest_state}' via '{source_hops[state_to_remove][old_dest_state]}'. Please verify state hops: {source_hops}"
672675
raise MolerException(msg)
673-
new_hops[from_state][dest_state] = source_hops[state_to_remove][dest_state]
676+
new_via_state = source_hops[old_via_state][old_dest_state]
677+
if forbidden_hops and old_from_state in forbidden_hops and old_dest_state in forbidden_hops[old_from_state] and forbidden_hops[old_from_state][old_dest_state] == new_via_state:
678+
if old_from_state in new_hops and old_dest_state in new_hops[old_from_state]:
679+
del new_hops[old_from_state][old_dest_state]
680+
else:
681+
new_hops[old_from_state][old_dest_state] = new_via_state
674682
else:
675-
del new_hops[from_state][dest_state]
683+
del new_hops[old_from_state][old_dest_state]
676684

677-
for from_state in source_hops.keys():
678-
if from_state in new_hops and state_to_remove in new_hops[from_state]:
679-
del new_hops[from_state][state_to_remove]
685+
for old_from_state in source_hops.keys():
686+
if old_from_state in new_hops and state_to_remove in new_hops[old_from_state]:
687+
del new_hops[old_from_state][state_to_remove]
680688

681689
if state_to_remove in new_hops:
682690
del new_hops[state_to_remove]
683691

684692
_delete_empty_states(new_hops)
693+
if additional_hops:
694+
update_dict(new_hops, additional_hops)
695+
685696
return new_hops

0 commit comments

Comments
 (0)