Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
from transitions.extensions.markup import MarkupMachine
from transitions.core import Transition
import logging
_LOGGER = logging.getLogger(__name__)
_LOGGER.addHandler(logging.NullHandler())
class WebTransition(Transition):
def _change_state(self, event_data):
super(WebTransition, self)._change_state(event_data)
model_name = event_data.model.name if hasattr(event_data.model, 'name') else str(id(event_data.model))
transition = {"source": self.source,
"dest": self.dest,
"trigger": event_data.event.name}
event_data.machine.websocket_handler.send_message({"method": "state_changed",
"arg": {"model": model_name, "transition": transition}})
class WebMachine(MarkupMachine):
transition_cls = WebTransition
def __init__(self, *args, **kwargs):
condition (if event sending is enabled) or to extract arguments
from (if event sending is disabled). Also contains the data
model attached to the current machine which is used to invoke
the condition.
"""
predicate = event_data.machine.resolve_callable(self.func, event_data)
if asyncio.iscoroutinefunction(predicate):
if event_data.machine.send_event:
return await predicate(event_data) == self.target
else:
return await predicate(*event_data.args, **event_data.kwargs) == self.target
else:
return super(AsyncCondition, self).check(event_data)
class AsyncTransition(Transition):
""" Representation of an asynchronous transition managed by a ``AsyncMachine`` instance.
Attributes:
source (str): Source state of the transition.
dest (str): Destination state of the transition.
prepare (list): Callbacks executed before conditions checks.
conditions (list): Callbacks evaluated to determine if
the transition should be executed.
before (list): Callbacks executed before the transition is executed
but only if condition checks have been successful.
after (list): Callbacks executed after the transition is executed
but only if condition checks have been successful.
"""
condition_cls = AsyncCondition
@staticmethod
def set_edge_style(graph, edge, style='default'):
style_attr = graph.style_attributes.get('edge', {}).get(style)
edge.attr.update(style_attr)
@staticmethod
def set_graph_style(graph, item, style='default'):
style_attr = graph.style_attributes.get('graph', {}).get(style)
item.graph_attr.update(style_attr)
@staticmethod
def _create_transition(*args, **kwargs):
return TransitionGraphSupport(*args, **kwargs)
class TransitionGraphSupport(Transition):
def _change_state(self, event_data):
machine = event_data.machine
model = event_data.model
dest = machine.get_state(self.dest)
# Mark the active node
machine.reset_graph(model.graph)
# Mark the previous node and path used
if self.source is not None:
source = machine.get_state(self.source)
machine.set_node_state(model.graph, source.name,
state='previous')
machine.set_node_state(model.graph, dest.name, state='active')
self.set_node_style(node, 'default')
def set_node_style(self, item, style='default'):
style_attr = self.graph.style_attributes.get('node', {}).get(style)
item.attr.update(style_attr)
def set_edge_style(self, item, style='default'):
style_attr = self.graph.style_attributes.get('edge', {}).get(style)
item.attr.update(style_attr)
@staticmethod
def _create_transition(*args, **kwargs):
return TransitionGraphSupport(*args, **kwargs)
class TransitionGraphSupport(Transition):
def _change_state(self, event_data):
# Mark the active node
event_data.machine.set_node_state(self.dest, state='active', reset=True)
# Mark the previous node and path used
if self.source is not None:
event_data.machine.set_node_state(self.source, state='previous')
event_data.machine.set_edge_state(self.source, self.dest, state='previous')
super(TransitionGraphSupport, self)._change_state(event_data)
# Prevent deep copying of callback lists since these include either references to callables or
# strings. Deep copying a method reference would lead to the creation of an entire new (model) object
# (see https://github.com/pytransitions/transitions/issues/248)
def __deepcopy__(self, memo):
cls = self.__class__
result = cls.__new__(cls)
memo[id(self)] = result
for key, value in self.__dict__.items():
if key in cls.dynamic_methods:
setattr(result, key, copy(value))
else:
setattr(result, key, deepcopy(value, memo))
return result
class NestedTransition(Transition):
""" A transition which handles entering and leaving nested states.
Attributes:
dest (NestedState): The resolved transition destination in respect
to initial states of nested states.
"""
def execute(self, event_data):
""" Extends transitions.core.transitions to handle nested states. """
if self.dest is None:
return _super(NestedTransition, self).execute(event_data)
dest_state = event_data.machine.get_state(self.dest)
while dest_state.initial:
dest_state = event_data.machine.get_state(dest_state.initial)
self.dest = dest_state.name
return _super(NestedTransition, self).execute(event_data)