Skip to content

v2.2.0

Compare
Choose a tag to compare
@fgmacedo fgmacedo released this 07 May 00:32
· 81 commits to develop since this release

StateMachine 2.2.0

May 6, 2024

What's new in 2.2.0

In this release, we conducted a general cleanup and refactoring across various modules to enhance code readability and maintainability. We improved exception handling and reduced code redundancy.

As a result, we achieved a ~2.2x faster setup in our performance tests and significantly simplified the callback machinery.

Check of unreachable and non-final states

We included one more state machine definition validation for non-final states.

We already check if any states are unreachable from the initial state, if not, an InvalidDefinition exception is thrown.

>>> from statemachine import StateMachine, State

>>> class TrafficLightMachine(StateMachine):
...     "A workflow machine"
...     red = State('Red', initial=True, value=1)
...     green = State('Green', value=2)
...     orange = State('Orange', value=3)
...     hazard = State('Hazard', value=4)
...
...     cycle = red.to(green) | green.to(orange) | orange.to(red)
...     blink = hazard.to.itself()
Traceback (most recent call last):
...
InvalidDefinition: There are unreachable states. The statemachine graph should have a single component. Disconnected states: ['hazard']

From this release, StateMachine will also check that all non-final states have an outgoing transition,
and warn you if any states would result in the statemachine becoming trapped in a non-final state with no further transitions possible.

This will currently issue a warning, but can be turned into an exception by setting `strict_states=True` on the class.
>>> from statemachine import StateMachine, State

>>> class TrafficLightMachine(StateMachine, strict_states=True):
...     "A workflow machine"
...     red = State('Red', initial=True, value=1)
...     green = State('Green', value=2)
...     orange = State('Orange', value=3)
...     hazard = State('Hazard', value=4)
...
...     cycle = red.to(green) | green.to(orange) | orange.to(red)
...     fault = red.to(hazard) | green.to(hazard) | orange.to(hazard)
Traceback (most recent call last):
...
InvalidDefinition: All non-final states should have at least one outgoing transition. These states have no outgoing transition: ['hazard']
`strict_states=True` will become the default behavior in the next major release.

See State Transitions.

Bugfixes in 2.2.0

  • Fixes #424 allowing deepcopy of state machines.
  • Dispatch Mechanism: Resolved issues in the dispatch mechanism in statemachine/dispatcher.py that affected the reliability
    of event handling across different states. This fix ensures consistent behavior when events are dispatched in complex state
    machine configurations.