lewis.core.statemachine

The statemachine module contains one of lewis’ central parts, the cycle-based StateMachine. The module also contains classes that make it easier to define the state machine (State, Transition). Despite its central nature, it’s unlikely to be used directly in client code for device simulations - these should be based on StateMachineDevice, which provides a more convenient interface for that purpose.

Members

HasContext

Mixin to provide a Context.

State

StateMachine state handler base class.

StateMachine

Cycle based state machine.

StateMachineException

Classes in this module should only raise this type of Exception.

Transition

StateMachine transition condition base class.

class lewis.core.statemachine.HasContext[source]

Bases: object

Mixin to provide a Context.

Creates a _context member variable that can be assigned with set_context().

Any state handler or transition callable that derives from this mixin will receive a context from its StateMachine upon initialization (assuming the StateMachine was provided with a context itself).

set_context(new_context) None[source]

Assigns the new context to the member variable _context.

class lewis.core.statemachine.State[source]

Bases: HasContext

StateMachine state handler base class.

Provides a way to implement StateMachine event handling behaviour using an object-oriented interface. Once the StateMachine is configured to do so, it will automatically invoke the events in this class when appropriate.

To use this class, create a derived class and override any events that need custom behaviour. Device context is provided via HasContext mixin.

in_state(dt) None[source]

Handle in-state event.

Raised repeatedly, once per cycle, while idling in this state. Exactly one in-state event occurs per cycle for every StateMachine. This is always the last event of the cycle.

Parameters:

dt – Delta T since last cycle.

on_entry(dt) None[source]

Handle entry event. Raised once, when this state is entered.

Parameters:

dt – Delta T since last cycle.

on_exit(dt) None[source]

Handle exit event. Raised once, when this state is exited.

Parameters:

dt – Delta T since last cycle.

class lewis.core.statemachine.StateMachine(cfg, context=None)[source]

Bases: CanProcess

Cycle based state machine.

Parameters:
  • cfg – dict which contains state machine configuration.

  • context – object which is assigned to State and Transition objects as their _context.

The configuration dict may contain the following keys:

  • initial: Name of the initial state of this machine

  • states: [optional] Dict of custom state handlers

  • transitions: [optional] Dict of transitions in this state machine.

State handlers may be given as a dict, list or State class:

  • dict: May contain keys ‘on_entry’, ‘in_state’ and ‘on_exit’.

  • list: May contain up to 3 entries, above events in that order.

  • class: Should be an instance of a class that derives from State.

In case of handlers being provided as a dict or a list, values should be callable and may take a single parameter: the Delta T since the last cycle.

Transitions should be provided as a dict where:

  • Each key is a tuple of two values, the FROM and TO states respectively.

  • Each value is a callable transition condition that return True or False.

Transition conditions are called once per cycle when in the FROM state. If one of the transition conditions returns True, the transition is executed that cycle. The remaining conditions aren’t called.

Consider using an OrderedDict if order matters.

Only one transition may occur per cycle. Every cycle will, at the very least, trigger an in_state event against the current state.

See also

See doProcess() for details.

bind_handlers_by_name(instance, override=False, prefix=None) None[source]

Auto-bind state handlers based on naming convention.

Parameters:
  • instance – Target object instance to search for handlers and bind events to.

  • override – If set to True, matching handlers will replace previously registered handlers.

  • prefix – Dict or list of prefixes to override defaults (keys: on_entry, in_state, on_exit)

This function enables automatically binding state handlers to events without having to specify them in the constructor. When called, this function searches instance for member functions that match the following patterns for all known states (states mentioned in ‘states’ or ‘transitions’ dicts of cfg):

  • instance._on_entry_[state]

  • instance._in_state_[state]

  • instance._on_exit_[state]

The default prefixes may be overridden using the prefix parameter. Supported keys are ‘on_entry’, ‘in_state’, and ‘on_exit’. Values should include any and all desired underscores.

Matching functions are assigned as handlers to the corresponding state events, iff no handler was previously assigned to that event.

If a state event already had a handler assigned (during construction or previous call to this function), no changes are made even if a matching function is found. To force previously assigned handlers to be overwritten, set the third parameter to True. This may be useful to implement inheritance-like specialization using multiple implementation classes but only one StateMachine instance.

can(state)[source]

Returns true if the transition to ‘state’ is allowed from the current state.

Parameters:

state – State to check transition to

Returns:

True if state is reachable from current

doProcess(dt) None[source]

Process a cycle of this state machine.

Parameters:

dt – Delta T. “Time” passed since last cycle, passed on to event handlers.

A cycle will perform at most one transition and exactly one in_state event.

A transition will only occur if one of the transition condition functions leaving the current state returns True.

When a transition occurs, the following events are raised:
  • on_exit_old_state()

  • on_entry_new_state()

  • in_state_new_state()

The first cycle after init or reset will never call transition checks and, instead, always performs on_entry and in_state on the initial state.

Whether a transition occurs or not, and regardless of any other circumstances, a cycle always ends by raising an in_state event on the current (potentially new) state.

reset() None[source]

Reset the state machine to before the first cycle. The next process() will enter the initial state.

property state

Name of the current state.

exception lewis.core.statemachine.StateMachineException[source]

Bases: Exception

Classes in this module should only raise this type of Exception.

class lewis.core.statemachine.Transition[source]

Bases: HasContext

StateMachine transition condition base class.

Provides a way to implement a transition that requires access to the device context. The device context is provided via HasContext mixin, and can be accessed as self._context.

To use this class, create a derived class and override the __call__() attribute.