States

State, as the name sais, holds the representation of a state in a statemachine.

State

class statemachine.state.State(name: str, value: Optional[Any] = None, initial: bool = False, final: bool = False, enter: Optional[Any] = None, exit: Optional[Any] = None)[source]

A State in a state machine describes a particular behaviour of the machine. When we say that a machine is “in” a state, it means that the machine behaves in the way that state describes.

Parameters
  • name – An human readable representation of the state.

  • value – A specific value to the storage and retrieval of states. If specified, you can use It to map a more friendly representation to a low-level value.

  • initial – Set ‘ True` if the State is the initial one. There must be one and only one initial state in a statemachine. Defaults to False.

  • final – Set True if represents a final state. A machine can have optionally many final states. Final states have no Transition starting from It. Defaults to False.

  • enter – One or more callbacks assigned to be executed when the state is entered. See Actions.

  • exit – One or more callbacks assigned to be executed when the state is exited. See Actions.

State is a core component on how this library implements an expressive API to declare StateMachines.

>>> from statemachine import State

Given a few states…

>>> draft = State("Draft", initial=True)
>>> producing = State("Producing")
>>> closed = State('Closed', final=True)

Transitions are declared using the State.to() or State.from_() (reversed) methods.

>>> draft.to(producing)
TransitionList([Transition(State('Draft', ...

The result is a TransitionList. Don’t worry about this internal class. But the good thing is that it implements the OR operator to combine transitions, so you can use the | syntax to compound a list of transitions and assign to the same event.

>>> transitions = draft.to(draft) | draft.to(producing)
>>> [(t.source.name, t.target.name) for t in transitions]
[('Draft', 'Draft'), ('Draft', 'Producing')]

There are handy shortcuts that you can use to express this same set of transitions.

The first one, draft.to(draft), is also called a Self transition, and can be expressed using an alternative syntax:

>>> draft.to.itself()
TransitionList([Transition(State('Draft', ...

You can even pass a list of target states to declare at once all transitions starting from the same state.

>>> transitions = draft.to(draft, producing, closed)
>>> [(t.source.name, t.target.name) for t in transitions]
[('Draft', 'Draft'), ('Draft', 'Producing'), ('Draft', 'Closed')]
property from_

Create transitions from the given target states (reversed).

property to

Create transitions to the given target states.

Initial state

A StateMachine should have one and only one initial state.

The initial State is entered when the machine starts and the corresponding enterirng state Actions are called if defined.

Final state

You can explicitly set final states. Transitions from these states are not allowed and will raise exception.

>>> from statemachine import StateMachine, State

>>> class CampaignMachine(StateMachine):
...     "A workflow machine"
...     draft = State('Draft', initial=True, value=1)
...     producing = State('Being produced', value=2)
...     closed = State('Closed', final=True, value=3)
...
...     add_job = draft.to.itself() | producing.to.itself() | closed.to(producing)
...     produce = draft.to(producing)
...     deliver = producing.to(closed)
Traceback (most recent call last):
...
InvalidDefinition: Cannot declare transitions from final state. Invalid state(s): ['closed']

You can retrieve all final states.

>>> class CampaignMachine(StateMachine):
...     "A workflow machine"
...     draft = State('Draft', initial=True, value=1)
...     producing = State('Being produced', value=2)
...     closed = State('Closed', final=True, value=3)
...
...     add_job = draft.to.itself() | producing.to.itself()
...     produce = draft.to(producing)
...     deliver = producing.to(closed)

>>> machine = CampaignMachine()

>>> machine.final_states
[State('Closed', id='closed', value=3, initial=False, final=True)]

See also

How to define and attach Actions to States.