Python Finite State Machines made easy.
Project description
Python finite-state machines made easy.
Free software: MIT license
Documentation: https://python-statemachine.readthedocs.io.
Getting started
To install Python State Machine, run this command in your terminal:
$ pip install python-statemachine
Define your state machine:
from statemachine import StateMachine, State
class TrafficLightMachine(StateMachine):
green = State('Green', initial=True)
yellow = State('Yellow')
red = State('Red')
slowdown = green.to(yellow)
stop = yellow.to(red)
go = red.to(green)
You can now create an instance:
>>> traffic_light = TrafficLightMachine()
And inspect about the current state:
>>> traffic_light.current_state State('Green', identifier='green', value='green', initial=True) >>> traffic_light.current_state == TrafficLightMachine.green == traffic_light.green True
For each state, there’s a dinamically created property in the form is_<state.identifier>, that returns True if the current status matches the query:
>>> traffic_light.is_green True >>> traffic_light.is_yellow False >>> traffic_light.is_red False
Query about metadata:
>>> [s.identifier for s in m.states] ['green', 'red', 'yellow'] >>> [t.identifier for t in m.transitions] ['go', 'slowdown', 'stop']
Call a transition:
>>> traffic_light.slowdown()
And check for the current status:
>>> traffic_light.current_state State('Yellow', identifier='yellow', value='yellow', initial=False) >>> traffic_light.is_yellow True
You can’t run a transition from an invalid state:
>>> traffic_light.is_yellow True >>> traffic_light.slowdown() Traceback (most recent call last): ... LookupError: Can't slowdown when in Yellow.
You can also trigger events in an alternative way, calling the run(<transition.identificer>) method:
>>> traffic_light.is_yellow True >>> traffic_light.run('stop') >>> traffic_light.is_red True
A state machine can be instantiated with an initial value:
>>> machine = TrafficLightMachine(start_value='red') >>> traffic_light.is_red True
Models
If you need to persist the current state on another object, or you’re using the state machine to control the flow of another object, you can pass this object to the StateMachine constructor:
>>> class MyModel(object): ... def __init__(self, state): ... self.state = state ... >>> obj = MyModel(state='red') >>> traffic_light = TrafficLightMachine(obj) >>> traffic_light.is_red True >>> obj.state 'red' >>> obj.state = 'green' >>> traffic_light.is_green True >>> traffic_light.slowdown() >>> obj.state 'yellow' >>> traffic_light.is_yellow True
Callbacks
Callbacks when running events:
from statemachine import StateMachine, State
class TrafficLightMachine(StateMachine):
"A traffic light machine"
green = State('Green', initial=True)
yellow = State('Yellow')
red = State('Red')
slowdown = green.to(yellow)
stop = yellow.to(red)
go = red.to(green)
def on_slowdown(self):
print('Calma, lá!')
def on_stop(self):
print('Parou.')
def on_go(self):
print('Valendo!')
>>> stm = TrafficLightMachine() >>> stm.slowdown() Calma, lá! >>> stm.stop() Parou. >>> stm.go() Valendo!
Or when entering/exiting states:
from statemachine import StateMachine, State
class TrafficLightMachine(StateMachine):
"A traffic light machine"
green = State('Green', initial=True)
yellow = State('Yellow')
red = State('Red')
cycle = green.to(yellow) | yellow.to(red) | red.to(green)
def on_enter_green(self):
print('Valendo!')
def on_enter_yellow(self):
print('Calma, lá!')
def on_enter_red(self):
print('Parou.')
>>> stm = TrafficLightMachine() >>> stm.cycle() Calma, lá! >>> stm.cycle() Parou. >>> stm.cycle() Valendo!
Mixins
Your model can inherited from a custom mixin to auto-instantiate a state machine.
class CampaignMachineWithKeys(StateMachine):
"A workflow machine"
draft = State('Draft', initial=True, value=1)
producing = State('Being produced', value=2)
closed = State('Closed', value=3)
add_job = draft.to(draft) | producing.to(producing)
produce = draft.to(producing)
deliver = producing.to(closed)
class MyModel(MachineMixin):
state_machine_name = 'CampaignMachine'
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
super(MyModel, self).__init__()
def __repr__(self):
return "{}({!r})".format(type(self).__name__, self.__dict__)
model = MyModel(state='draft')
assert isinstance(model.statemachine, campaign_machine)
assert model.state == 'draft'
assert model.statemachine.current_state == model.statemachine.draft
History
0.7.0 (2018-04-01)
New event callbacks: on_enter_<state> and on_exit_<state>.
0.6.2 (2017-08-25)
Fix README.
0.6.1 (2017-08-25)
Fix deploy issues.
0.6.0 (2017-08-25)
Auto-discovering statemachine/statemachines under a Django project when they are requested using the mixin/registry feature.
0.5.1 (2017-07-24)
Fix bug on CombinedTransition._can_run not allowing transitions to run if there are more than two transitions combined.
0.5.0 (2017-07-13)
Custom exceptions.
Duplicated definition of on_execute callback is not allowed.
Fix bug on StateMachine.on_<transition.identifier> being called with extra self param.
0.4.2 (2017-07-10)
Python 3.6 support.
Drop official support for Python 3.3.
Transition can be used as decorator for on_execute callback definition.
Transition can point to multiple destination states.
0.3.0 (2017-03-22)
README getting started section.
Tests to state machine without model.
0.2.0 (2017-03-22)
State can hold a value that will be assigned to the model as the state value.
Travis-CI integration.
RTD integration.
0.1.0 (2017-03-21)
First release on PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file python-statemachine-0.7.0.tar.gz
.
File metadata
- Download URL: python-statemachine-0.7.0.tar.gz
- Upload date:
- Size: 24.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f6dfea765d952d713cf2e165686090c97b1942bb5a519ec61aab24e23a5db9ae |
|
MD5 | b9ff3b92ecc1802c864d506325e16d47 |
|
BLAKE2b-256 | b76e2dea4c51dc6d0bdeea8fb32d590ba79176cd145b678e38fa764bdb812831 |
File details
Details for the file python_statemachine-0.7.0-py2.py3-none-any.whl
.
File metadata
- Download URL: python_statemachine-0.7.0-py2.py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1252e8c0a162e1adb2e3dee6aa0fd1372ed6a734f227ab5df7ecaa304bc5993a |
|
MD5 | cfcdc04c2eb0b5b8738330cd42c9ec9b |
|
BLAKE2b-256 | 1c8e30d4e541f86907cbc00c90af3a541515bf90641db70523ca64b4e956305e |