state machine for humans
There are two types of developers in this world: those who love state machines and those who will eventually.
I fall in the first camp. I think it is really important to have a
declarative way to define the states of an object. That’s why I
developed state_machine.
pip install state_machine@acts_as_state_machine()
class Person():
name = 'Billy'
sleeping = State(initial=True)
running = State()
cleaning = State()
run = Event(from_states=sleeping, to_state=running)
cleanup = Event(from_states=running, to_state=cleaning)
sleep = Event(from_states=(running, cleaning), to_state=sleeping)
@before('sleep')
def do_one_thing(self, param):
print "{} is sleepy".format(self.name)
@before('sleep')
def do_another_thing(self, param):
print "{} is REALLY sleepy and will sleep {}".format(self.name, param)
@after('sleep')
def snore(self, param):
print "Zzzzzzzzzzzz"
@after('sleep')
def big_snore(self, param):
print "Zzzzzzzzzzzzzzzzzzzzzz (%r)"%param
person = Person()
print person.current_state == Person.sleeping # True
print person.is_sleeping # True
print person.is_running # False
person.run()
print person.is_running # True
person.sleep('a long time')
# Billy is sleepy
# Billy is REALLY sleepy and will sleep a long time
# Zzzzzzzzzzzz
# Zzzzzzzzzzzzzzzzzzzzzz (a long time)
print person.is_sleeping # TrueYou can add callback hooks that get executed before or after an event (see example above). If a event is called with parameters, all the before/after callback must be defined with a compatible signature
Important: if the before event causes an exception or returns
False, the state will not change (transition is blocked) and the
after event will not be executed.
An InvalidStateTransition Exception will be thrown if you try to move into an invalid state.
The default name of the state field is "aasm_state". If the field already exist in the object il will be used as so (beware to initialize it with the default state value yourself in the init function) If you want to change it, you just have to give it as an argument to the acts_as_state_machine decorator:
@acts_as_state_machine('my_field_name') class Person():
...
It should be done independently
- Allow multiple state_machines per object
Feel free to ping me on twitter: @tushman or add issues or PRs at https://github.com/jtushman/state_machine
to aasm and ruby’s state_machine and all other state machines that I loved before