Skip to main content

Basic Finite State Machine (FSM) tools.

Short summary:

  • CancellationError: Subclass of FSMError Raised when trying to make use of an FSM which is cancelled.

  • FSM: Base class for a finite state machine (FSM).

  • FSMError: An exception associated with an FSM.

  • FSMSubType: Type variable.

  • FSMTransitionEvent: FSMTransitionEvent(old_state, new_state, event, when, extra).

Symbols


Type variable.

The preferred way to construct a type variable is via the dedicated syntax for generic functions, classes, and type aliases::

class Sequence[T]:  # T is a TypeVar
    ...

This syntax can also be used to create bound and constrained type variables::

# S is a TypeVar bound to str
class StrSequence[S: str]:
    ...

# A is a TypeVar constrained to str or bytes
class StrOrBytesSequence[A: (str, bytes)]:
    ...

Type variables can also have defaults:

class IntDefault[T = int]:
    ...

However, if desired, reusable type variables can also be constructed manually, like so::

T = TypeVar('T') # Can be anything S = TypeVar('S', bound=str) # Can be any subtype of str A = TypeVar('A', str, bytes) # Must be exactly str or bytes D = TypeVar('D', default=int) # Defaults to int

Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function and type alias definitions.

The variance of type variables is inferred by type checkers when they are created through the type parameter syntax and when infer_variance=True is passed. Manually created type variables may be explicitly marked covariant or contravariant by passing covariant=True or contravariant=True. By default, manually created type variables are invariant. See PEP 484 and PEP 695 for more details.



FSMSubType = ~FSMSubType

Classes

class CancellationError(FSMError)

Subclass of FSMError Raised when trying to make use of an FSM which is cancelled.

For example, this is raised by a cs.result.Result when accessing .result or .exc_info after cancellation.

CancellationError.__init__(self, message=None, *, fsm=None, **kw)

Initialise the CancellationError.

The optional message parameter (default "cancelled") is set as the message attribute. Other keyword parameters set their matching attributes.

class FSM(cs.gvutils.DOTNodeMixin)

Base class for a finite state machine (FSM).

The allowed states and transitions are defined by the class attribute FSM_TRANSITIONS, a mapping of state->event->new_state.

Each instance has the following attributes:

  • fsm_state: the current state value.
  • fsm_history: an optional iterable of FSMTransitionEvent state transitions recorded by the fsm_event method. Usually this would be None (the default) or a list.
FSM State Diagram

FSM.__init__(self, state=None, *, history=None, lock=None, transitions=None)

Initialise the FSM from:

  • state: optional positional parameter for the initial state, default self.FSM_DEFAULT_STATE or the first key from self.FSM_TRANSITIONS
  • history: an optional object to record state transition history, default None; if not None this should be an iterable object with a .append(entry) method such as a list.
  • lock: an optional mutex to control access; if presupplied and shared with the caller it should probably be an RLock; the default is a Lock, which is enough for FSM private use
  • transitions: optional state->event->state mapping; if provided, this will override the class FSM_TRANSITIONS mapping

Note that the FSM base class does not provide a FSM_DEFAULT_STATE attribute; a default state value of None will leave .fsm_state unset.

This behaviour is is chosen mostly to support subclasses with unusual behaviour, particularly Django's Model class whose refresh_from_db method seems to not refresh fields which already exist, and setting .fsm_state from a FSM_DEFAULT_STATE class attribute thus breaks this method. Subclasses of this class and Model should not provide a FSM_DEFAULT_STATE attribute, instead relying on the field definition to provide this default in the usual way.

FSM.FSM_ANY_STATE

<object object at 0x10c4ed270>

FSM.FSM_TRANSITIONS

{}

FSM.__getattr__(self, attr)

Provide the following attributes:

  • present the state names as attributes, for example: self.PENDING=='PENDING' if there is a 'PENDING' state
  • present is_statename as a Boolean testing whether self.fsm_state==statename.upper()
  • a callable calling self.fsm_event(attr) if attr is an event name for the current state Fall back to the superclass __getattr__.

FSM.dot_node_palette_key

<property object at 0x10e10eca0>

FSM.fsm_as_svg(self, layout=None, history_style=None, **dot_kw) -> str

Render the state transition diagram as SVG.

FSM.fsm_callback(self, state, callback)

Register a callback to be called immediately on transition to state as callback(self,FSMEventTransition). The special state value FSM.FSM_ANY_STATE may be supplied to register a callback which fires for every state transition.

>>> fsm = FSM('state1',transitions={
...   'state1':{'ev_a':'state2'},
...   'state2':{'ev_b':'state1'},
... })
>>> fsm.fsm_callback('state2',lambda task, transition: print(task, transition))
>>> fsm.fsm_callback(FSM.FSM_ANY_STATE,lambda task, transition: print("ANY", task, transition))
>>> fsm.ev_a(foo=3) # doctest: +ELLIPSIS
ANY FSM:state2 FSMTransitionEvent(old_state='state1', new_state='state2', event='ev_a', when=..., extra={'foo': 3})
FSM:state2 FSMTransitionEvent(old_state='state1', new_state='state2', event='ev_a', when=..., extra={'foo': 3})
'state2'
>>> fsm.ev_b(foo=4) # doctest: +ELLIPSIS
ANY FSM:state1 FSMTransitionEvent(old_state='state2', new_state='state1', event='ev_b', when=..., extra={'foo': 4})
'state1'

FSM.fsm_callback_discard(self, state, callback)

Deregister a callback for state.

FSM.fsm_dot

<property object at 0x10e10ec50>

FSM.fsm_event(self, event, **extra)

Transition the FSM from the current state to a new state based on event. Call any callbacks associated with the new state. Returns the new state.

Optional information may be passed as keyword arguments.

A transition instance of FSMTransitionEvent is created with the following attributes:

  • old_state: the state when fsm_event was called
  • new_state: the new state
  • event: the event
  • when: a UNIX timestamp from time.time()
  • extra: a dict with the extra information

If self.fsm_history is not None, transition is appended to it.

If there are callbacks for new_state or FSM.FSM_ANY_STATE, call each callback as callback(self,transition).

Important note: the callbacks are run in series in the current Thread. If you need to dispatch a long running activity from a state transtion, the callback should still return promptly.

FSM.fsm_event_is_allowed(self, event)

Test whether event is permitted in the current state. This can be handy as a pretest.

FSM.fsm_events

<property object at 0x10e10ebb0>

FSM.fsm_history

<property object at 0x10e10f010>

FSM.fsm_print(self, file=None, fmt=None, layout=None, **dot_kw)

Print the state transition diagram to file, default sys.stdout, in format fmt using the engine specified by layout, default 'dot'. This is a wrapper for cs.gvutils.gvprint.

FSM.fsm_print_state_diagram(file=None, *, fmt=None, graph_name=None, history=None, history_style=None, state=None, transitions=None, **gvprint_kw)

Print the state diagram via cs.gvutils.gvprint.

The DOT syntax graph description is computed with FSM.fsm_state_diagram_as_dot and the graph_name, history, history_style, state and transitions parameters are passed through to this.

If fmt is specified as dot then the DOT and any remaining keyword arguments are passed to print().

Otherwise any remaining keyword paramaeters are passed to gvprint.

FSM.fsm_state_diagram_as_dot(transitions=None, *, sep='\n', state=None, graph_name=None, history=None, history_style=None) -> str

Compute a DOT syntax graph description of the state diagram.

Parameters:

  • transitions: optional mapping of state->event->state, default cls.FSM_TRANSITIONS
  • state: optional current state name, a key of the transitions
  • sep: optional separator between "lines", default '\n'
  • graph_name: optional name for the graph, default the class name
  • history: optional event transition history
  • history_style: optional style mapping for event transition history, used to style edges which have been traversed

FSM.fsm_svg

<property object at 0x10e10ed40>

FSM.fsm_transitions_as_dot(self, transitions=None, **diagram_kw) -> str

Compute a DOT syntax graph description of the state diagram.

Parameters:

  • transitions: optional mapping of state->event->state, default self.FSM_TRANSITIONS
  • sep: optional separator between "lines", default '\n'
  • graph_name: optional name for the graph, default the class name
  • history_style: optional style mapping for event transition history, used to style edges which have been traversed

class FSMError(builtins.Exception)

An exception associated with an FSM.

These have a .fsm attribute storing an (optional) FSM reference supplied at initialisation.

class FSMTransitionEvent(builtins.tuple)

FSMTransitionEvent(old_state, new_state, event, when, extra)

FSMTransitionEvent.__replace__(self, /, **kwds)

Return a new FSMTransitionEvent object replacing specified fields with new values

FSMTransitionEvent.event

_tuplegetter(2, 'Alias for field number 2')

FSMTransitionEvent.extra

_tuplegetter(4, 'Alias for field number 4')

FSMTransitionEvent.new_state

_tuplegetter(1, 'Alias for field number 1')

FSMTransitionEvent.old_state

_tuplegetter(0, 'Alias for field number 0')

FSMTransitionEvent.when

_tuplegetter(3, 'Alias for field number 3')

Metadata

Release files for cs-fsm 20261016

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cs-fsm 20261016
File Size Uploaded
cs_fsm-20261016.tar.gz 8.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cs-fsm 20261016
File Interpreter ABI Platform
cs_fsm-20261016-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 18.8 kB

Release files / cs_fsm-20261016.tar.gz

Download URL cs_fsm-20261016.tar.gz
Size 8.5 kB
Tags Source
SHA-256 checksum
How to use checksums
9dc8a2ba667601a720fead6321dccd82704250b2cc018bb799ce959cba322a32
BLAKE2b-256 checksum
How to use checksums
00b7b563a0e0651d0679a5dde0a332c6a4c014ed2c2957efd0f80d13f080a543
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.1

Release files / cs_fsm-20261016-py2.py3-none-any.whl

Download URL cs_fsm-20261016-py2.py3-none-any.whl
Size 10.4 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
dea2a68889dc8998d42ad7de2fc81ff98514e33b4aed12150a49a72fbe1d1e4b
BLAKE2b-256 checksum
How to use checksums
354a5f48b7200a4073143c83839d1cd0d62ca7ce3d2ea4825f61e3ec3c6bcad8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.1
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page