Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if self.dest: # if self.dest is None this is an internal transition with no actual state change
await self._change_state(event_data)
await event_data.machine.callbacks(itertools.chain(self.after, event_data.machine.after_state_change), event_data)
_LOGGER.debug("%sExecuted callback after transition.", event_data.machine.name)
return True
async def _change_state(self, event_data):
await event_data.machine.get_state(self.source).exit(event_data)
event_data.machine.set_state(self.dest, event_data.model)
event_data.update(event_data.model.state)
await event_data.machine.get_state(self.dest).enter(event_data)
class AsyncEvent(Event):
""" A collection of transitions assigned to the same trigger """
async def trigger(self, model, *args, **kwargs):
""" Serially execute all transitions that match the current state,
halting as soon as one successfully completes. Note that `AsyncEvent` triggers must be awaited.
Args:
args and kwargs: Optional positional or named arguments that will
be passed onto the EventData object, enabling arbitrary state
information to be passed on to downstream triggered functions.
Returns: boolean indicating whether or not a transition was
successfully executed (True if successful, False if not).
"""
func = partial(self._trigger, model, *args, **kwargs)
t = asyncio.create_task(self.machine._process(func))
try:
return await t
# Prevent deep copying of callback lists since these include either references to callable 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 NestedEvent(Event):
""" An event type to work with nested states. """
def _trigger(self, model, *args, **kwargs):
state = self.machine.get_state(model.state)
while state.parent and state.name not in self.transitions:
state = state.parent
if state.name not in self.transitions:
msg = "%sCan't trigger event %s from state %s!" % (self.machine.name, self.name,
model.state)
if self.machine.get_state(model.state).ignore_invalid_triggers:
_LOGGER.warning(msg)
else:
raise MachineError(msg)
event_data = EventData(state, self, self.machine,
model, args=args, kwargs=kwargs)
return self._process(event_data)
self.lock = Lock()
def __getstate__(self):
return ''
def __setstate__(self, value):
return self.__init__()
def __enter__(self):
self.lock.__enter__()
def __exit__(self, exc_type, exc_val, exc_tb):
self.lock.__exit__(exc_type, exc_val, exc_tb)
class LockedEvent(Event):
""" An event type which uses the parent's machine context map when triggered. """
def trigger(self, model, *args, **kwargs):
""" Extends transitions.core.Event.trigger by using locks/machine contexts. """
# pylint: disable=protected-access
# noinspection PyProtectedMember
# LockedMachine._locked should not be called somewhere else. That's why it should not be exposed
# to Machine users.
if self.machine._locked != get_ident():
with nested(*self.machine.model_context_map[model]):
return _super(LockedEvent, self).trigger(model, *args, **kwargs)
else:
return _super(LockedEvent, self).trigger(model, *args, **kwargs)
class LockedMachine(Machine):
self.lock = Lock()
def __getstate__(self):
return ''
def __setstate__(self, value):
return self.__init__()
def __enter__(self):
self.lock.__enter__()
def __exit__(self, exc_type, exc_val, exc_tb):
self.lock.__exit__(exc_type, exc_val, exc_tb)
class LockedEvent(Event):
""" An event type which uses the parent's machine context map when triggered. """
def trigger(self, model, *args, **kwargs):
""" Extends transitions.core.Event.trigger by using locks/machine contexts. """
# pylint: disable=protected-access
# noinspection PyProtectedMember
# LockedMachine._locked should not be called somewhere else. That's why it should not be exposed
# to Machine users.
if self.machine._locked != get_ident():
with nested(*self.machine.model_context_map[model]):
return _super(LockedEvent, self).trigger(model, *args, **kwargs)
else:
return _super(LockedEvent, self).trigger(model, *args, **kwargs)
class LockedMachine(Machine):
def to_state(self, model, state_name, *args, **kwargs):
""" Helper function to add go to states in case a custom state separator is used.
Args:
model (class): The model that should be used.
state_name (str): Name of the destination state.
"""
event = EventData(self.get_state(model.state), Event('to', self), self,
model, args=args, kwargs=kwargs)
self._create_transition(model.state, state_name).execute(event)