You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/releases/3.0.0.md
+81-11
Original file line number
Diff line number
Diff line change
@@ -4,11 +4,21 @@
4
4
5
5
## What's new in 3.0.0
6
6
7
-
Statecharts are there! Now the library has support for Compound and Parallel states.
7
+
Statecharts are there! 🎉
8
8
9
-
### Python compatibility in 3.0.0
9
+
Statecharts are a powerful extension to state machines, in a way to organize complex reactive systems as a hierarchical state machine. They extend the concept of state machines by adding two new kinds of states: **parallel states** and **compound states**.
10
10
11
-
StateMachine 3.0.0 supports Python 3.9, 3.10, 3.11, 3.12, and 3.13.
11
+
**Parallel states** are states that can be active at the same time. They are useful for separating the state machine in multiple orthogonal state machines that can be active at the same time.
12
+
13
+
**Compound states** are states that have inner states. They are useful for breaking down complex state machines into multiple simpler ones.
14
+
15
+
The support for statecharts in this release follows the [SCXML specification](https://www.w3.org/TR/scxml/)*, which is a W3C standard for statecharts notation. Adhering as much as possible to this specification ensures compatibility with other tools and platforms that also implement SCXML, but more important,
16
+
sets a standard on the expected behaviour that the library should assume on various edge cases, enabling easier integration and interoperability in complex systems.
17
+
18
+
To verify the standard adoption, now the automated tests suite includes several `.scxml` testcases provided by the W3C group. Many thanks for this amazing work! Some of the tests are still failing, and some of the tags are still not implemented like `<invoke>` , in such cases, we've added an `xfail` mark by including a `test<number>.scxml.md` markdown file with details of the execution output.
19
+
20
+
While these are exiting news for the library and our community, it also introduces several backwards incompatible changes. Due to the major version release, the new behaviour is assumed by default, but we put
21
+
a lot of effort to minimize the changes needed in your codebase, and also introduced a few configuration options that you can enable to restore the old behaviour when possible. The following sections navigate to the new features and includes a migration guide.
12
22
13
23
14
24
### Create state machine class from a dict definition
@@ -73,9 +83,9 @@ A not so usefull example:
73
83
74
84
### Event matching following SCXML spec
75
85
76
-
Now events matching follows the SCXML spec.
86
+
Now events matching follows the [SCXML spec](https://www.w3.org/TR/scxml/#events):
77
87
78
-
For example, a transition with an `event` attribute of `"error foo"` will match event names `error`, `error.send`, `error.send.failed`, etc. (or `foo`, `foo.bar` etc.)
88
+
> For example, a transition with an `event` attribute of `"error foo"` will match event names `error`, `error.send`, `error.send.failed`, etc. (or `foo`, `foo.bar` etc.)
79
89
but would not match events named `errors.my.custom`, `errorhandler.mistake`, `error.send` or `foobar`.
80
90
81
91
An event designator consisting solely of `*` can be used as a wildcard matching any sequence of tokens, and thus any event.
@@ -90,6 +100,7 @@ TODO: Example of delayed events
90
100
Also, delayed events can be revoked by it's `send_id`.
- Dropped support for Python `3.7` and `3.8`. If you need support for these versios use the 2.* series.
114
+
115
+
### Python compatibility in 3.0.0
116
+
117
+
We've dropped support for Python `3.7` and `3.8`. If you need support for these versios use the 2.* series.
118
+
119
+
StateMachine 3.0.0 supports Python 3.9, 3.10, 3.11, 3.12, and 3.13.
104
120
105
121
106
-
## Non-RTC model removed
122
+
###Non-RTC model removed
107
123
108
124
This option was deprecated on version 2.3.2. Now all new events are put on a queue before being processed.
109
125
110
126
111
-
## Multiple current states
127
+
###Multiple current states
112
128
113
129
Due to the support of compound and parallel states, it's now possible to have multiple active states at the same time.
114
130
115
-
This introduces an impedance mismatch into the old public API, specifically, `sm.current_state` is deprecated and `sm.current_state_value` can returns a flat value if no compound state or a `list` instead.
131
+
This introduces an impedance mismatch into the old public API, specifically, `sm.current_state` is deprecated and `sm.current_state_value` can returns a flat value if no compound state or a `set` instead.
116
132
117
133
```{note}
118
-
To allow a smooth migration, these properties still work as before if there's no compound states in the state machine definition.
134
+
To allow a smooth migration, these properties still work as before if there's no compound/parallel states in the state machine definition.
119
135
```
120
136
121
137
Old
@@ -130,9 +146,63 @@ New
130
146
defcurrent_state(self) -> "State | MutableSet[State]":
131
147
```
132
148
133
-
We recomend using the new `sm.configuration` that has a stable API returning an `OrderedSet` on all cases:
149
+
We **strongly**recomend using the new `sm.configuration` that has a stable API returning an `OrderedSet` on all cases:
134
150
135
151
```py
136
152
@property
137
153
defconfiguration(self) -> OrderedSet["State"]:
138
154
```
155
+
156
+
### Entering and exiting states
157
+
158
+
Previous versions performed an atomic update of the active state just after the execution of the transition `on` actions.
159
+
160
+
Now, we follow the [SCXML spec](https://www.w3.org/TR/scxml/#SelectingTransitions):
161
+
162
+
> To execute a microstep, the SCXML Processor MUST execute the transitions in the corresponding optimal enabled transition set. To execute a set of transitions, the SCXML Processor MUST first exit all the states in the transitions' exit set in exit order. It MUST then execute the executable content contained in the transitions in document order. It MUST then enter the states in the transitions' entry set in entry order.
163
+
164
+
This introduces backward-incompatible changes, as previously, the `current_state` was never empty, allowing queries on `sm.current_state` or `sm.<any_state>.is_active` even while executing an `on` transition action.
165
+
166
+
Now, by default, during a transition, all states in the exit set are exited first, performing the `before` and `exit` callbacks. The `on` callbacks are then executed in an intermediate state that contains only the states that will not be exited, which can be an empty set. Following this, the states in the enter set are entered, with `enter` callbacks executed for each state in document order, and finally, the `after` callbacks are executed with the state machine in the final new configuration.
167
+
168
+
We have added two new keyword arguments available only in the `on` callbacks to assist with queries that were performed against `sm.current_state` or active states using `<state>.is_active`:
169
+
170
+
-`previous_configuration: OrderedSet[State]`: Contains the set of states that were active before the microstep was taken.
171
+
-`new_configuration: OrderedSet[State]`: Contains the set of states that will be active after the microstep finishes.
172
+
173
+
Additionally, you can create a state machine instance by passing `atomic_configuration_update=True` (default `False`) to restore the old behavior. When set to `False`, the `sm.configuration` will be updated only once per microstep, just after the `on` callbacks with the `new_configuration`, the set of states that should be active after the microstep.
The `validate` event is bound to several transitions, and the `on_validate` is expected to return `congrats` only when the state machine was with the `accepted` state active before the event occurs. In the old behavior, checking for `accepted.is_active` evaluates to `True` because the state were not exited before the `on` callback.
198
+
199
+
Due to the new behaviour, at the time of the `on_validate` call, the state machine configuration (a.k.a the current set of active states) is empty. So at this point in time `accepted.is_active` evaluates to `False`. To mitigate this case, now you can request one of the two new keyword arguments: `previous_configuration` and `new_configration` in `on` callbacks.
200
+
201
+
New way using `previous_configuration`:
202
+
203
+
```py
204
+
defon_validate(self, previous_configuration):
205
+
ifself.accepted in previous_configuration andself.model.is_ok():
0 commit comments