Skip to content

Commit 5bd27b7

Browse files
committed
release: New 2.4.0 release doc
1 parent 9cadf84 commit 5bd27b7

9 files changed

Lines changed: 103 additions & 12 deletions

File tree

docs/actions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ It's also possible to use an event name as action.
160160

161161
## Transition actions
162162

163-
For each {ref}`event`, you can register `before`, `on`, and `after` callbacks.
163+
For each {ref}`events`, you can register `before`, `on`, and `after` callbacks.
164164

165165
### Declare transition actions by naming convention
166166

docs/guards.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,13 @@ Boolean Expression:
104104
```
105105

106106
```{seealso}
107-
See {ref}`sphx_glr_auto_examples_air_conditioner_machine.py` for an example of
108-
combining multiple transitions to the same event.
107+
See {ref}`sphx_glr_auto_examples_lor_machine.py` for an example of
108+
using boolean algebra in conditions.
109109
```
110110

111111
```{seealso}
112-
See {ref}`sphx_glr_auto_examples_lor_machine.py` for an example of
113-
using boolean algebra in conditions.
112+
See {ref}`sphx_glr_auto_examples_air_conditioner_machine.py` for an example of
113+
combining multiple transitions to the same event.
114114
```
115115

116116
```{hint}

docs/releases/2.4.0.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# StateMachine 2.4.0
2+
3+
*November 5, 2024*
4+
5+
## What's new in 2.4.0
6+
7+
This release introduces powerful new features for the `StateMachine` library: {ref}`Condition expressions` and explicit definition of {ref}`Events`. These updates make it easier to define complex transition conditions and enhance performance, especially in workflows with nested or recursive event structures.
8+
9+
### Python compatibility in 2.4.0
10+
11+
StateMachine 2.4.0 supports Python 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13.
12+
13+
### Conditions expressions in 2.4.0
14+
15+
This release introduces support for conditionals with Boolean algebra. You can now use expressions like `or`, `and`, and `not` directly within transition conditions, simplifying the definition of complex state transitions. This allows for more flexible and readable condition setups in your state machine configurations.
16+
17+
Example (with a spoiler of the next highlight):
18+
19+
```py
20+
>>> from statemachine import StateMachine, State, Event
21+
22+
>>> class AnyConditionSM(StateMachine):
23+
... start = State(initial=True)
24+
... end = State(final=True)
25+
...
26+
... submit = Event(
27+
... start.to(end, cond="used_money or used_credit"),
28+
... name="finish order",
29+
... )
30+
...
31+
... used_money: bool = False
32+
... used_credit: bool = False
33+
34+
>>> sm = AnyConditionSM()
35+
>>> sm.submit()
36+
Traceback (most recent call last):
37+
TransitionNotAllowed: Can't finish order when in Start.
38+
39+
>>> sm.used_credit = True
40+
>>> sm.submit()
41+
>>> sm.current_state.id
42+
'end'
43+
44+
```
45+
46+
```{seealso}
47+
See {ref}`Condition expressions` for more details or take a look at the {ref}`sphx_glr_auto_examples_lor_machine.py` example.
48+
```
49+
50+
### Explicit event creation in 2.4.0
51+
52+
Now you can explicit declare {ref}`Events` using the {ref}`event` class. This allows custom naming, translations, and also helps your IDE to know that events are callable.
53+
54+
```py
55+
>>> from statemachine import StateMachine, State, Event
56+
57+
>>> class StartMachine(StateMachine):
58+
... created = State(initial=True)
59+
... started = State(final=True)
60+
...
61+
... start = Event(created.to(started), name="Launch the machine")
62+
...
63+
>>> [e.id for e in StartMachine.events]
64+
['start']
65+
>>> [e.name for e in StartMachine.events]
66+
['Launch the machine']
67+
>>> StartMachine.start.name
68+
'Launch the machine'
69+
70+
```
71+
72+
```{seealso}
73+
See {ref}`Events` for more details.
74+
```
75+
76+
### Recursive state machines (infinite loop)
77+
78+
We removed a note from the docs saying to avoid recursion loops. Since the {ref}`StateMachine 2.0.0` release we've turned the RTC model enabled by default, allowing nested events to occour as all events are put on an internal queue before being executed.
79+
80+
```{seealso}
81+
See {ref}`sphx_glr_auto_examples_recursive_event_machine.py` for an example of an infinite loop state machine declaration using `after` action callback to call the same event over and over again.
82+
83+
```
84+
85+
86+
## Bugfixes in 2.4.0
87+
88+
- Fixes [#484](https://github.com/fgmacedo/python-statemachine/issues/484) issue where nested events inside loops could leak memory by incorrectly
89+
referencing previous `event_data` when queuing the next event. This fix improves performance and stability in event-heavy workflows.

docs/releases/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Below are release notes through StateMachine and its patch releases.
1515
```{toctree}
1616
:maxdepth: 2
1717
18+
2.4.0
1819
2.3.6
1920
2.3.5
2021
2.3.4

docs/transitions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ An {ref}`Event` declared as string will have its `name` set equal to its `id`. T
313313

314314
In the next major release, `Event.name` will default to a capitalized version of `id` (i.e., `Event.id.replace("_", " ").capitalize()`).
315315

316-
Starting from version 2.3.7, use `Event.id` to check for event identifiers instead of `Event.name`.
316+
Starting from version 2.4.0, use `Event.id` to check for event identifiers instead of `Event.name`.
317317

318318
```
319319

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "python-statemachine"
3-
version = "2.3.6"
3+
version = "2.4.0"
44
description = "Python Finite State Machines made easy."
55
authors = ["Fernando Macedo <fgmacedo@gmail.com>"]
66
maintainers = ["Fernando Macedo <fgmacedo@gmail.com>"]

statemachine/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44

55
__author__ = """Fernando Macedo"""
66
__email__ = "fgmacedo@gmail.com"
7-
__version__ = "2.3.6"
7+
__version__ = "2.4.0"
88

99
__all__ = ["StateMachine", "State", "Event"]

statemachine/exceptions.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .i18n import _
44

55
if TYPE_CHECKING:
6+
from .event import Event
67
from .state import State
78

89

@@ -31,8 +32,8 @@ class AttrNotFound(InvalidDefinition):
3132
class TransitionNotAllowed(StateMachineError):
3233
"Raised when there's no transition that can run from the current :ref:`state`."
3334

34-
def __init__(self, event: str, state: "State"):
35+
def __init__(self, event: "Event", state: "State"):
3536
self.event = event
3637
self.state = state
37-
msg = _("Can't {} when in {}.").format(self.event, self.state.name)
38+
msg = _("Can't {} when in {}.").format(self.event.name, self.state.name)
3839
super().__init__(msg)

tests/examples/async_guess_the_number_machine.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ async def connect_stdin_stdout():
130130

131131

132132
# %%
133-
# Executing
134-
# ---------
133+
# Executing the game
134+
# ------------------
135135
#
136136
# This script only run by passing the `-i` flag, avoiding blocking while running automated tests.
137137
#

0 commit comments

Comments
 (0)