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
@@ -47,7 +47,7 @@ And these transitions are assigned to the {ref}`event` `cycle` defined at the cl
47
47
48
48
```{note}
49
49
50
-
In fact, before the full class body is evaluated, the assigments of transitions are instances of [](statemachine.transition_list.TransitionList). When the state machine is evaluated by our custom [metaclass](https://docs.python.org/3/reference/datamodel.html#metaclasses), these names will be transformed into a method that triggers an {ref}`Event`.
50
+
In fact, before the full class body is evaluated, the assigments of transitions are instances of [](statemachine.transition_list.TransitionList). When the state machine is evaluated by our custom [metaclass](https://docs.python.org/3/reference/datamodel.html#metaclasses), these names will be transformed into {ref}`Event` instances.
51
51
52
52
```
53
53
@@ -171,6 +171,153 @@ initiates a change in the state of the system.
171
171
172
172
In `python-statemachine`, an event is specified as an attribute of the state machine class declaration or directly on the {ref}`event` parameter on a {ref}`transition`.
173
173
174
+
175
+
### Declaring events
176
+
177
+
The simplest way to declare an {ref}`event`is by assiging a transitions list to a name at the
178
+
State machine class level. The name will be converted to an {ref}`Event (class)`:
179
+
180
+
```py
181
+
>>>from statemachine import Event
182
+
183
+
>>>class SimpleSM(StateMachine):
184
+
...initial= State(initial=True)
185
+
...final= State()
186
+
...
187
+
...start= initial.to(final) # start is a name that will be converted to an `Event`
188
+
189
+
>>>isinstance(SimpleSM.start, Event)
190
+
True
191
+
>>>sm= SimpleSM()
192
+
>>> sm.start() # call `start` event
193
+
194
+
```
195
+
196
+
```{versionadded} 2.6.7
197
+
You can also explict declare an {ref}`Event` instance, this helps IDEs to know that the event iscallableand also with transtation strings.
198
+
```
199
+
200
+
To declare an explicit event you must also import the {ref}`Event (class)`:
201
+
202
+
```py
203
+
>>>from statemachine import Event
204
+
205
+
>>>class SimpleSM(StateMachine):
206
+
...initial= State(initial=True)
207
+
...final= State()
208
+
...
209
+
...start= Event(
210
+
... initial.to(final),
211
+
...name="Start the state machine"# optional name, if not provided it will be derived from id
212
+
... )
213
+
214
+
>>> SimpleSM.start.name
215
+
'Start the state machine'
216
+
217
+
>>>sm= SimpleSM()
218
+
>>> sm.start() # call `start` event
219
+
220
+
```
221
+
222
+
An {ref}`Event (class)` instance or an event id string can also be used as the `event` parameter of a {ref}`transition`. So you can mix these options as you need.
...# The `event` parameter can be declared as `str` or `Event`, since `Event` is a subclass of `str`
245
+
...# Note also that in this example, we're using `on_transition` instead of `on_cycle`, as this
246
+
...# binds the action to run for every transition instead of a specific event ID.
247
+
...assert event_data.event == event
248
+
...return (
249
+
...f"Running {event.name} from {event_data.transition.source.id} to "
250
+
...f"{event_data.transition.target.id}"
251
+
... )
252
+
253
+
>>># Event IDs
254
+
>>> TrafficLightMachine.cycle.id
255
+
'cycle'
256
+
>>> TrafficLightMachine.slowdown.id
257
+
'slowdown'
258
+
>>> TrafficLightMachine.stop.id
259
+
'stop'
260
+
>>> TrafficLightMachine.go.id
261
+
'go'
262
+
263
+
>>># Event names
264
+
>>> TrafficLightMachine.cycle.name
265
+
'Loop'
266
+
>>> TrafficLightMachine.slowdown.name
267
+
'Slowing down'
268
+
>>> TrafficLightMachine.stop.name
269
+
'Please stop!'
270
+
>>> TrafficLightMachine.go.name
271
+
'go'
272
+
273
+
>>>sm= TrafficLightMachine()
274
+
275
+
>>> sm.cycle() # Your IDE is happy because it now knows that `cycle` is callable!
276
+
'Running Loop from green to yellow'
277
+
278
+
>>> sm.send("cycle") # You can also use `send` in order to process dynamic event sources
279
+
'Running Loop from yellow to red'
280
+
281
+
>>> sm.send("cycle")
282
+
'Running Loop from red to green'
283
+
284
+
>>> sm.send("slowdown")
285
+
'Running Slowing down from green to yellow'
286
+
287
+
>>> sm.send("stop")
288
+
'Running Please stop! from yellow to red'
289
+
290
+
>>> sm.send("go")
291
+
'Running go from red to green'
292
+
293
+
```
294
+
295
+
```{tip}
296
+
Avoid mixing these options within the same project; instead, choose the one that best serves your use case. Declaring events as strings has been the standard approach since the library’s inception and can be considered syntactic sugar, as the state machine metaclass will convert all events to {ref}`Event (class)` instances under the hood.
297
+
298
+
```
299
+
300
+
```{note}
301
+
In order to allow the seamless upgrade from using strings to `Event` instances, the {ref}`Event (class)` inherits from`str`.
302
+
303
+
Note that this is just an implementation detail and can change in the future.
304
+
305
+
>>>isinstance(TrafficLightMachine.cycle, str)
306
+
True
307
+
308
+
```
309
+
310
+
311
+
```{warning}
312
+
An {ref}`Event` declared as string will have its `name`set equal to its `id`. This isfor backward compatibility when migrating from previous versions.
313
+
314
+
In the next major release, `Event.name` will default to a capitalized version of `id` (i.e., `Event.id.replace("_", "").capitalize()`).
315
+
316
+
Starting from version 2.3.7, use `Event.id` to check for event identifiers instead of `Event.name`.
317
+
318
+
```
319
+
320
+
174
321
### Triggering events
175
322
176
323
Triggering an event on a state machine means invoking or sending a signal, initiating the
@@ -188,14 +335,13 @@ associated with the transition
188
335
See {ref}`actions`and {ref}`validators and guards`.
189
336
```
190
337
191
-
192
338
You can invoke the event in an imperative syntax:
193
339
194
340
```py
195
341
>>>machine= TrafficLightMachine()
196
342
197
343
>>> machine.cycle()
198
-
Running cyclefrom green to yellow
344
+
'Running Loop from green to yellow'
199
345
200
346
>>> machine.current_state.id
201
347
'yellow'
@@ -206,25 +352,13 @@ Or in an event-oriented style, events are `send`:
206
352
207
353
```py
208
354
>>> machine.send("cycle")
209
-
Running cyclefrom yellow to red
355
+
'Running Loop from yellow to red'
210
356
211
357
>>> machine.current_state.id
212
358
'red'
213
359
214
360
```
215
361
216
-
You can also pass positional and keyword arguments, that will be propagated
217
-
to the actions and guards. In this example, the :code:`TrafficLightMachine` implements
218
-
an action that `echoes` back the parameters informed.
0 commit comments