Finite State Machine
Lightweight, decorator-based Python implementation of a Finite State Machine.
Table of Contents
Installation
pip install finite-state-machine
Usage
Subclass StateMachine and set the state instance variable:
from finite_state_machine import StateMachine, transition
class LightSwitch(StateMachine):
def __init__(self):
self.state = "off"
super().__init__()
The transition decorator can be used to specify valid state transitions
with an optional parameter for conditions.
States can be of type: string, int, bool, Enum, or IntEnum.
Can specify a single sate or a list of states for the source parameter;
can only specify a single state as the target target.
All condition functions need to return True for the transition to occur,
else a ConditionsNotMet exception will be raised.
Condition functions require the same positional position and
keyword arguments present in the transition function.
@transition(source="off", target="on", conditions=[light_is_off])
def turn_on(self):
# specify side effects
def light_is_off(machine):
return machine.state == "off"
Can also specify an on_error parameter to handle situations
where the transition function raises an exception:
@transition(source="off", target="on", on_error="failed")
def turn_on(self):
raise ValueError
Example
from finite_state_machine import StateMachine, transition
class Turnstile(StateMachine):
initial_state = "close"
def __init__(self):
self.state = self.initial_state
super().__init__()
@transition(source=["close", "open"], target="open")
def insert_coin(self):
pass
@transition(source="open", target="close")
def pass_thru(self):
pass
REPL
In [2]: turnstile = Turnstile()
In [3]: turnstile.state
Out[3]: 'close'
In [4]: turnstile.insert_coin()
In [5]: turnstile.state
Out[5]: 'open'
In [6]: turnstile.insert_coin()
In [7]: turnstile.state
Out[7]: 'open'
In [8]: turnstile.pass_thru()
In [9]: turnstile.state
Out[9]: 'close'
In [10]: turnstile.pass_thru()
---------------------------------------------------------------------------
InvalidStartState Traceback (most recent call last)
<ipython-input-10-6abc6f4be1cd> in <module>
----> 1 turnstile.pass_thru()
~/state_machine.py in _wrapper(*args, **kwargs)
32
33 if self.state not in source:
---> 34 raise InvalidStartState
35
36 for condition in conditions:
InvalidStartState:
The examples folder contains additional workflows.
State Diagram
State Machine workflows can be visualized using a state diagram.
finite-state-machine generates diagrams using
Mermaid Markdown syntax,
which can be viewed using the
Mermaid Live Editor.
Use the fsm_draw_state_diagram command and point to
State Machine workflow class
that inheritences from StateMachine.
# class parameter is required
$ fsm_draw_state_diagram --class examples.turnstile:Turnstile
# initial_state parameter is optional
$ fsm_draw_state_diagram --class examples.turnstile:Turnstile --initial_state close
Contributing
- Clone repo
- Create a virtual environment
pip install -r requirements_dev.txt- Install pre-commit
- Set up pre-commit hooks in repo:
pre-commit install
To install a package locally for development, run:
flit install [--symlink] [--python path/to/python]
Running Tests
pytest
Inspiration
This project is inspired by django-fsm. I wanted a decorator-based state machine without having to use Django.
Metadata
Release files for finite-state-machine 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| finite-state-machine-0.5.0.tar.gz | 2.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| finite_state_machine-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.4 MB
Release files / finite-state-machine-0.5.0.tar.gz
| Download URL | finite-state-machine-0.5.0.tar.gz |
|---|---|
| Size | 2.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ac08e609315e1c8ee1b374ddfb275820efb1cf8ea0a58c47699dfc8bee36f8a1
|
|
BLAKE2b-256 checksum How to use checksums |
c982cdf07d9673999c8c03c0e8405d8be57b6b8efb36c57fe45db8164c51eff7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-requests/2.23.0
|
Release files / finite_state_machine-0.5.0-py3-none-any.whl
| Download URL | finite_state_machine-0.5.0-py3-none-any.whl |
|---|---|
| Size | 7.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ad1e513e672f3ffda2ef06cb0504c9e1621ea7b13ab9d3ceefa77f88c12399c
|
|
BLAKE2b-256 checksum How to use checksums |
bc4457f4908755d25aa8400ec773c0a7f43178a9cc2daa7a1f7dcdb753edb7ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-requests/2.23.0
|