# Path: sismic/model/elements.py
# class Transition(ContractMixin):
#     """
#     Represent a transition from a source state to a target state.
# 
#     A transition can be eventless (no event) or internal (no target).
#     A condition (code as string) can be specified as a guard.
# 
#     :param source: name of the source state
#     :param target: name of the target state (if transition is not internal)
#     :param event: event name (if any)
#     :param guard: condition as code (if any)
#     :param action: action as code (if any)
#     :param priority: priority (default to 0)
#     """
# 
#     LOW_PRIORITY = -1
#     DEFAULT_PRIORITY = 0
#     HIGH_PRIORITY = 1
# 
#     def __init__(self, source: str, target: str = None, event: str = None, guard: str = None,
#                  action: str = None, priority=None) -> None:
#         ContractMixin.__init__(self)
#         self._source = source
#         self._target = target
#         self.event = event
#         self.guard = guard
#         self.action = action
#         self.priority = 0 if priority is None else priority
# 
#     @property
#     def source(self):
#         return self._source
# 
#     @property
#     def target(self):
#         return self._target
# 
#     @property
#     def internal(self):
#         """
#         Boolean indicating whether this transition is an internal transition.
#         """
#         return self._target is None
# 
#     @property
#     def eventless(self):
#         """
#         Boolean indicating whether this transition is an eventless transition.
#         """
#         return self.event is None
# 
#     def __eq__(self, other):
#         if isinstance(other, Transition):
#             return (
#                 ContractMixin.__eq__(self, other)
#                 and self.source == other.source
#                 and self.target == other.target
#                 and self.event == other.event
#                 and self.guard == other.guard
#                 and self.action == other.action
#                 and self.priority == other.priority
#             )
#         else:
#             return NotImplemented
# 
#     def __repr__(self):
#         return 'Transition({!r}, {!r}, event={!r})'.format(self.source, self.target, self.event)
# 
#     def __str__(self):
#         return '{} -> {}{} [{}] -> {}'.format(
#             self.source,
#             '' if self.priority == 0 else '{}:'.format(self.priority),
#             self.event,
#             self.guard,
#             self.target if self.target else ''
#         )
# 
#     def __hash__(self):
#         return hash(self.source)
# 
# Path: sismic/model/events.py
# class Event:
#     """
#     An event with a name and (optionally) some data passed as named parameters.
# 
#     The list of parameters can be obtained using *dir(event)*. Notice that
#     *name* and *data* are reserved names. If a *delay* parameter is provided,
#     then this event will be considered as a delayed event (and won't be
#     executed until given delay has elapsed).
# 
#     When two events are compared, they are considered equal if their names
#     and their data are equal.
# 
#     :param name: name of the event.
#     :param data: additional data passed as named parameters.
#     """
# 
#     __slots__ = ['name', 'data']
# 
#     def __init__(self, name: str, **additional_parameters: Any) -> None:
#         self.name = name
#         self.data = additional_parameters
# 
#     def __eq__(self, other):
#         if isinstance(other, Event):
#             return (self.name == other.name and self.data == other.data)
#         else:
#             return NotImplemented
# 
#     def __getattr__(self, attr):
#         try:
#             return self.data[attr]
#         except KeyError:
#             raise AttributeError('{} has no attribute {}'.format(self, attr))
# 
#     def __getstate__(self):
#         # For pickle and implicitly for multiprocessing
#         return self.name, self.data
# 
#     def __setstate__(self, state):
#         # For pickle and implicitly for multiprocessing
#         self.name, self.data = state
# 
#     def __hash__(self):
#         return hash(self.name)
# 
#     def __dir__(self):
#         return ['name'] + list(self.data.keys())
# 
#     def __repr__(self):
#         if self.data:
#             return '{}({!r}, {})'.format(
#                 self.__class__.__name__, self.name, ', '.join(
#                     '{}={!r}'.format(k, v) for k, v in self.data.items()))
#         else:
#             return '{}({!r})'.format(self.__class__.__name__, self.name)


from typing import List, Optional
from .elements import Transition
from .events import Event


__all__ = ['MicroStep', 'MacroStep']


class MicroStep:
    """
    Create a micro step.

    A step consider *event*, takes a *transition* and results in a list
    of *entered_states* and a list of *exited_states*.
    Order in the two lists is REALLY important!

    :param event: Event or None in case of eventless transition
    :param transition: a *Transition* or None if no processed transition
    :param entered_states: possibly empty list of entered states
    :param exited_states: possibly empty list of exited states
    :param sent_events: a possibly empty list of events that are sent during the step
    """

    __slots__ = ['event', 'transition', 'entered_states', 'exited_states', 'sent_events']


# Path: sismic/model/elements.py
# class Transition(ContractMixin):
#     """
#     Represent a transition from a source state to a target state.
# 
#     A transition can be eventless (no event) or internal (no target).
#     A condition (code as string) can be specified as a guard.
# 
#     :param source: name of the source state
#     :param target: name of the target state (if transition is not internal)
#     :param event: event name (if any)
#     :param guard: condition as code (if any)
#     :param action: action as code (if any)
#     :param priority: priority (default to 0)
#     """
# 
#     LOW_PRIORITY = -1
#     DEFAULT_PRIORITY = 0
#     HIGH_PRIORITY = 1
# 
#     def __init__(self, source: str, target: str = None, event: str = None, guard: str = None,
#                  action: str = None, priority=None) -> None:
#         ContractMixin.__init__(self)
#         self._source = source
#         self._target = target
#         self.event = event
#         self.guard = guard
#         self.action = action
#         self.priority = 0 if priority is None else priority
# 
#     @property
#     def source(self):
#         return self._source
# 
#     @property
#     def target(self):
#         return self._target
# 
#     @property
#     def internal(self):
#         """
#         Boolean indicating whether this transition is an internal transition.
#         """
#         return self._target is None
# 
#     @property
#     def eventless(self):
#         """
#         Boolean indicating whether this transition is an eventless transition.
#         """
#         return self.event is None
# 
#     def __eq__(self, other):
#         if isinstance(other, Transition):
#             return (
#                 ContractMixin.__eq__(self, other)
#                 and self.source == other.source
#                 and self.target == other.target
#                 and self.event == other.event
#                 and self.guard == other.guard
#                 and self.action == other.action
#                 and self.priority == other.priority
#             )
#         else:
#             return NotImplemented
# 
#     def __repr__(self):
#         return 'Transition({!r}, {!r}, event={!r})'.format(self.source, self.target, self.event)
# 
#     def __str__(self):
#         return '{} -> {}{} [{}] -> {}'.format(
#             self.source,
#             '' if self.priority == 0 else '{}:'.format(self.priority),
#             self.event,
#             self.guard,
#             self.target if self.target else ''
#         )
# 
#     def __hash__(self):
#         return hash(self.source)
# 
# Path: sismic/model/events.py
# class Event:
#     """
#     An event with a name and (optionally) some data passed as named parameters.
# 
#     The list of parameters can be obtained using *dir(event)*. Notice that
#     *name* and *data* are reserved names. If a *delay* parameter is provided,
#     then this event will be considered as a delayed event (and won't be
#     executed until given delay has elapsed).
# 
#     When two events are compared, they are considered equal if their names
#     and their data are equal.
# 
#     :param name: name of the event.
#     :param data: additional data passed as named parameters.
#     """
# 
#     __slots__ = ['name', 'data']
# 
#     def __init__(self, name: str, **additional_parameters: Any) -> None:
#         self.name = name
#         self.data = additional_parameters
# 
#     def __eq__(self, other):
#         if isinstance(other, Event):
#             return (self.name == other.name and self.data == other.data)
#         else:
#             return NotImplemented
# 
#     def __getattr__(self, attr):
#         try:
#             return self.data[attr]
#         except KeyError:
#             raise AttributeError('{} has no attribute {}'.format(self, attr))
# 
#     def __getstate__(self):
#         # For pickle and implicitly for multiprocessing
#         return self.name, self.data
# 
#     def __setstate__(self, state):
#         # For pickle and implicitly for multiprocessing
#         self.name, self.data = state
# 
#     def __hash__(self):
#         return hash(self.name)
# 
#     def __dir__(self):
#         return ['name'] + list(self.data.keys())
# 
#     def __repr__(self):
#         if self.data:
#             return '{}({!r}, {})'.format(
#                 self.__class__.__name__, self.name, ', '.join(
#                     '{}={!r}'.format(k, v) for k, v in self.data.items()))
#         else:
#             return '{}({!r})'.format(self.__class__.__name__, self.name)


# Path: sismic/model/steps.py
from typing import List, Optional
from .elements import Transition
from .events import Event



__all__ = ['MicroStep', 'MacroStep']


class MicroStep:
    """
    Create a micro step.

    A step consider *event*, takes a *transition* and results in a list
    of *entered_states* and a list of *exited_states*.
    Order in the two lists is REALLY important!

    :param event: Event or None in case of eventless transition
    :param transition: a *Transition* or None if no processed transition
    :param entered_states: possibly empty list of entered states
    :param exited_states: possibly empty list of exited states
    :param sent_events: a possibly empty list of events that are sent during the step
    """

    __slots__ = ['event', 'transition', 'entered_states', 'exited_states', 'sent_events']


    def __init__(self, event: Event = None, transition: Transition = None,