Skip to content

Commit be9ec1e

Browse files
committed
chore: Improved docs. Conditions renamed to 'cond' to follow SCXML
1 parent f135e4f commit be9ec1e

36 files changed

Lines changed: 324 additions & 789 deletions

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,10 @@ A simple didactic state machine for controlling an ``Order``:
231231
...
232232
... add_to_order = waiting_for_payment.to(waiting_for_payment)
233233
... receive_payment = (
234-
... waiting_for_payment.to(processing, conditions="payments_enough")
234+
... waiting_for_payment.to(processing, cond="payments_enough")
235235
... | waiting_for_payment.to(waiting_for_payment, unless="payments_enough")
236236
... )
237-
... process_order = processing.to(shipping, conditions="payment_received")
237+
... process_order = processing.to(shipping, cond="payment_received")
238238
... ship_order = shipping.to(completed)
239239
...
240240
... def __init__(self):

docs/actions.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ For each event, you can register `before_<event>` and `after_<event>`
4444
- `after_<event>(event_data)`
4545

4646

47-
(validators-and-guards)=
48-
4947
## Other callbacks
5048

5149
In addition to {ref}`actions`, you can specify {ref}`validators-and-guards` that are checked
@@ -60,27 +58,32 @@ See {ref}`guards` and {ref}`validators`.
6058

6159
Actions and Guards will be executed in the following order:
6260

63-
- `validators(event_data)` (attached to the transition)
61+
- `validators()` (attached to the transition)
6462

65-
- `conditions(event_data)` (attached to the transition)
63+
- `conditions()` (attached to the transition)
6664

67-
- `unless(event_data)` (attached to the transition)
65+
- `unless()` (attached to the transition)
6866

69-
- `before_transition(event_data)`
67+
- `before_transition()`
7068

71-
- `before_<event>(event_data)`
69+
- `before_<event>()`
7270

73-
- `on_exit_state(event_data)`
71+
- `on_exit_state()`
7472

75-
- `on_exit_<state_identifier>(event_data)`
73+
- `on_exit_<state_identifier>()`
7674

77-
- `on_enter_state(event_data)`
75+
- `on_transition()`
7876

79-
- `on_enter_<state_identifier>(event_data)`
77+
- `on_<event>()`
8078

81-
- `after_<event>(event_data)`
79+
- `on_enter_state()`
80+
81+
- `on_enter_<state_identifier>()`
82+
83+
- `after_<event>()`
84+
85+
- `after_transition()`
8286

83-
- `after_transition(event_data)`
8487

8588

8689
(dynamic-dispatch)=
@@ -90,8 +93,8 @@ python-statemachine implements a custom dispatch mechanism on all those availabl
9093
Guards, this means that you can declare an arbitrary number of `*args` and `**kwargs`, and the
9194
library will match your method signature of what's expect to receive with the provided arguments.
9295

93-
This means that if on your `on_enter_<state>()` or `on_execute_<event>()` method, you also
94-
need to know the `source` ({ref}`state`), or the `event` ({ref}`event`), or access a keyword
96+
This means that if on your `on_enter_<state>()` or `on_execute_<event>()` method, you need to know
97+
the `source` ({ref}`state`), or the `event` ({ref}`event`), or access a keyword
9598
argument passed with the trigger, just add this parameter to the method and It will be passed
9699
by the dispatch mechanics.
97100

@@ -116,7 +119,8 @@ For your convenience, all these parameters are available for you on any Action o
116119

117120
- `transition`: The {ref}`Transition` instance that was activated by the {ref}`Event`.
118121

119-
So, you can implement Actions and Guards like these, but this list is not exaustive, it's only to give you a few examples... any combination of parameters will work, including extra parameters
122+
So, you can implement Actions and Guards like these, but this list is not exaustive, it's only
123+
to give you a few examples... any combination of parameters will work, including extra parameters
120124
that you may inform when triggering an {ref}`event`:
121125

122126
```py

docs/auto_examples/all_actions_machine.ipynb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
"outputs": [],
2828
"source": [
29-
"import mock\n\nfrom statemachine import StateMachine, State\n\n\nclass AllActionsMachine(StateMachine):\n\n initial = State(\"Initial\", initial=True)\n final = State(\"Final\", final=True)\n\n go = initial.to(\n final,\n validators=[\"validation_1\", \"validation_2\"],\n conditions=[\"condition_1\", \"condition_2\"],\n unless=[\"unless_1\", \"unless_2\"],\n on_execute=[\"on_execute_1\", \"on_execute_2\"],\n before=[\"before_go_inline_1\", \"before_go_inline_2\"],\n after=[\"after_go_inline_1\", \"after_go_inline_2\"],\n )\n\n def __init__(self, *args, **kwargs):\n self.spy = mock.Mock(side_effect=lambda x: x)\n super(AllActionsMachine, self).__init__(*args, **kwargs)\n\n # validations and conditions\n\n def validation_1(self):\n # this method may raise an exception\n return self.spy(\"validation_1\")\n\n def validation_2(self):\n # this method may raise an exception\n return self.spy(\"validation_2\")\n\n def condition_1(self):\n self.spy(\"condition_1\")\n return True\n\n def condition_2(self):\n self.spy(\"condition_2\")\n return True\n\n def unless_1(self):\n self.spy(\"unless_1\")\n return False\n\n def unless_2(self):\n self.spy(\"unless_2\")\n return False\n\n # generics state\n\n def on_enter_state(self):\n return self.spy(\"on_enter_state\")\n\n def on_exit_state(self):\n return self.spy(\"on_exit_state\")\n\n # generics transition\n\n def before_transition(self):\n return self.spy(\"before_transition\")\n\n def after_transition(self):\n return self.spy(\"after_transition\")\n\n # before / after specific\n\n def on_execute_1(self):\n return self.spy(\"on_execute_1\")\n\n def on_execute_2(self):\n return self.spy(\"on_execute_2\")\n\n def before_go_inline_1(self):\n return self.spy(\"before_go_inline_1\")\n\n def before_go_inline_2(self):\n return self.spy(\"before_go_inline_2\")\n\n def before_go(self):\n return self.spy(\"before_go\")\n\n def on_go(self):\n return self.spy(\"on_go\")\n\n def after_go_inline_1(self):\n return self.spy(\"after_go_inline_1\")\n\n def after_go_inline_2(self):\n return self.spy(\"after_go_inline_2\")\n\n def after_go(self):\n return self.spy(\"after_go\")\n\n # enter / exit specific\n\n def on_enter_initial(self):\n return self.spy(\"on_enter_initial\")\n\n def on_exit_initial(self):\n return self.spy(\"on_exit_initial\")\n\n def on_enter_final(self):\n return self.spy(\"on_enter_final\")\n\n def on_exit_final(self):\n \"hopefully this will not be called\"\n return self.spy(\"on_exit_final\")"
29+
"import mock\n\nfrom statemachine import StateMachine, State\n\n\nclass AllActionsMachine(StateMachine):\n\n initial = State(\"Initial\", initial=True)\n final = State(\"Final\", final=True)\n\n go = initial.to(\n final,\n validators=[\"validation_1\", \"validation_2\"],\n cond=[\"condition_1\", \"condition_2\"],\n unless=[\"unless_1\", \"unless_2\"],\n on_execute=[\"on_execute_1\", \"on_execute_2\"],\n before=[\"before_go_inline_1\", \"before_go_inline_2\"],\n after=[\"after_go_inline_1\", \"after_go_inline_2\"],\n )\n\n def __init__(self, *args, **kwargs):\n self.spy = mock.Mock(side_effect=lambda x: x)\n super(AllActionsMachine, self).__init__(*args, **kwargs)\n\n # validators and guards\n\n def validation_1(self):\n # this method may raise an exception\n return self.spy(\"validation_1\")\n\n def validation_2(self):\n # this method may raise an exception\n return self.spy(\"validation_2\")\n\n def condition_1(self):\n self.spy(\"condition_1\")\n return True\n\n def condition_2(self):\n self.spy(\"condition_2\")\n return True\n\n def unless_1(self):\n self.spy(\"unless_1\")\n return False\n\n def unless_2(self):\n self.spy(\"unless_2\")\n return False\n\n # generics state\n\n def on_enter_state(self):\n return self.spy(\"on_enter_state\")\n\n def on_exit_state(self):\n return self.spy(\"on_exit_state\")\n\n # generics transition\n\n def before_transition(self):\n return self.spy(\"before_transition\")\n\n def on_transition(self):\n return self.spy(\"on_transition\")\n\n def after_transition(self):\n return self.spy(\"after_transition\")\n\n # before / after specific\n\n def before_go_inline_1(self):\n return self.spy(\"before_go_inline_1\")\n\n def before_go_inline_2(self):\n return self.spy(\"before_go_inline_2\")\n\n def before_go(self):\n return self.spy(\"before_go\")\n\n def on_execute_1(self):\n return self.spy(\"on_execute_1\")\n\n def on_execute_2(self):\n return self.spy(\"on_execute_2\")\n\n def on_go(self):\n return self.spy(\"on_go\")\n\n def after_go_inline_1(self):\n return self.spy(\"after_go_inline_1\")\n\n def after_go_inline_2(self):\n return self.spy(\"after_go_inline_2\")\n\n def after_go(self):\n return self.spy(\"after_go\")\n\n # enter / exit specific\n\n def on_enter_initial(self):\n return self.spy(\"on_enter_initial\")\n\n def on_exit_initial(self):\n return self.spy(\"on_exit_initial\")\n\n def on_enter_final(self):\n return self.spy(\"on_enter_final\")\n\n def on_exit_final(self):\n \"hopefully this will not be called\"\n return self.spy(\"on_exit_final\")"
3030
]
3131
},
3232
{
@@ -51,7 +51,7 @@
5151
"cell_type": "markdown",
5252
"metadata": {},
5353
"source": [
54-
"Only before actions have their result collected.\n\n"
54+
"Only before/on actions have their result collected.\n\n"
5555
]
5656
},
5757
{
@@ -62,7 +62,7 @@
6262
},
6363
"outputs": [],
6464
"source": [
65-
"result = machine.go()\nassert result == [\n \"before_transition\",\n \"before_go_inline_1\",\n \"before_go_inline_2\",\n \"on_execute_1\",\n \"on_execute_2\",\n \"before_go\",\n \"on_go\",\n]"
65+
"result = machine.go()\nassert result == [\n \"before_transition\",\n \"before_go_inline_1\",\n \"before_go_inline_2\",\n \"before_go\",\n \"on_transition\",\n \"on_execute_1\",\n \"on_execute_2\",\n \"on_go\",\n]"
6666
]
6767
},
6868
{
@@ -80,7 +80,7 @@
8080
},
8181
"outputs": [],
8282
"source": [
83-
"assert spy.call_args_list == [\n mock.call(\"on_enter_state\"),\n mock.call(\"on_enter_initial\"),\n mock.call(\"validation_1\"),\n mock.call(\"validation_2\"),\n mock.call(\"condition_1\"),\n mock.call(\"condition_2\"),\n mock.call(\"unless_1\"),\n mock.call(\"unless_2\"),\n mock.call(\"before_transition\"),\n mock.call(\"before_go_inline_1\"),\n mock.call(\"before_go_inline_2\"),\n mock.call(\"on_execute_1\"),\n mock.call(\"on_execute_2\"),\n mock.call(\"before_go\"),\n mock.call(\"on_go\"),\n mock.call(\"on_exit_state\"),\n mock.call(\"on_exit_initial\"),\n mock.call(\"on_enter_state\"),\n mock.call(\"on_enter_final\"),\n mock.call(\"after_go_inline_1\"),\n mock.call(\"after_go_inline_2\"),\n mock.call(\"after_go\"),\n mock.call(\"after_transition\"),\n]"
83+
"assert spy.call_args_list == [\n mock.call(\"on_enter_state\"),\n mock.call(\"on_enter_initial\"),\n\n mock.call(\"validation_1\"),\n mock.call(\"validation_2\"),\n\n mock.call(\"condition_1\"),\n mock.call(\"condition_2\"),\n\n mock.call(\"unless_1\"),\n mock.call(\"unless_2\"),\n\n mock.call(\"before_transition\"),\n mock.call(\"before_go_inline_1\"),\n mock.call(\"before_go_inline_2\"),\n mock.call(\"before_go\"),\n\n mock.call(\"on_exit_state\"),\n mock.call(\"on_exit_initial\"),\n\n mock.call(\"on_transition\"),\n mock.call(\"on_execute_1\"),\n mock.call(\"on_execute_2\"),\n mock.call(\"on_go\"),\n\n mock.call(\"on_enter_state\"),\n mock.call(\"on_enter_final\"),\n\n mock.call(\"after_go_inline_1\"),\n mock.call(\"after_go_inline_2\"),\n mock.call(\"after_go\"),\n mock.call(\"after_transition\"),\n]"
8484
]
8585
}
8686
],

docs/auto_examples/all_actions_machine.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class AllActionsMachine(StateMachine):
1919
go = initial.to(
2020
final,
2121
validators=["validation_1", "validation_2"],
22-
conditions=["condition_1", "condition_2"],
22+
cond=["condition_1", "condition_2"],
2323
unless=["unless_1", "unless_2"],
2424
on_execute=["on_execute_1", "on_execute_2"],
2525
before=["before_go_inline_1", "before_go_inline_2"],
@@ -30,7 +30,7 @@ def __init__(self, *args, **kwargs):
3030
self.spy = mock.Mock(side_effect=lambda x: x)
3131
super(AllActionsMachine, self).__init__(*args, **kwargs)
3232

33-
# validations and conditions
33+
# validators and guards
3434

3535
def validation_1(self):
3636
# this method may raise an exception
@@ -69,17 +69,14 @@ def on_exit_state(self):
6969
def before_transition(self):
7070
return self.spy("before_transition")
7171

72+
def on_transition(self):
73+
return self.spy("on_transition")
74+
7275
def after_transition(self):
7376
return self.spy("after_transition")
7477

7578
# before / after specific
7679

77-
def on_execute_1(self):
78-
return self.spy("on_execute_1")
79-
80-
def on_execute_2(self):
81-
return self.spy("on_execute_2")
82-
8380
def before_go_inline_1(self):
8481
return self.spy("before_go_inline_1")
8582

@@ -89,6 +86,12 @@ def before_go_inline_2(self):
8986
def before_go(self):
9087
return self.spy("before_go")
9188

89+
def on_execute_1(self):
90+
return self.spy("on_execute_1")
91+
92+
def on_execute_2(self):
93+
return self.spy("on_execute_2")
94+
9295
def on_go(self):
9396
return self.spy("on_go")
9497

@@ -126,16 +129,17 @@ def on_exit_final(self):
126129

127130

128131
# %%
129-
# Only before actions have their result collected.
132+
# Only before/on actions have their result collected.
130133

131134
result = machine.go()
132135
assert result == [
133136
"before_transition",
134137
"before_go_inline_1",
135138
"before_go_inline_2",
139+
"before_go",
140+
"on_transition",
136141
"on_execute_1",
137142
"on_execute_2",
138-
"before_go",
139143
"on_go",
140144
]
141145

@@ -145,23 +149,32 @@ def on_exit_final(self):
145149
assert spy.call_args_list == [
146150
mock.call("on_enter_state"),
147151
mock.call("on_enter_initial"),
152+
148153
mock.call("validation_1"),
149154
mock.call("validation_2"),
155+
150156
mock.call("condition_1"),
151157
mock.call("condition_2"),
158+
152159
mock.call("unless_1"),
153160
mock.call("unless_2"),
161+
154162
mock.call("before_transition"),
155163
mock.call("before_go_inline_1"),
156164
mock.call("before_go_inline_2"),
157-
mock.call("on_execute_1"),
158-
mock.call("on_execute_2"),
159165
mock.call("before_go"),
160-
mock.call("on_go"),
166+
161167
mock.call("on_exit_state"),
162168
mock.call("on_exit_initial"),
169+
170+
mock.call("on_transition"),
171+
mock.call("on_execute_1"),
172+
mock.call("on_execute_2"),
173+
mock.call("on_go"),
174+
163175
mock.call("on_enter_state"),
164176
mock.call("on_enter_final"),
177+
165178
mock.call("after_go_inline_1"),
166179
mock.call("after_go_inline_2"),
167180
mock.call("after_go"),
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7979f9d577527eade21568387d8b23c5
1+
ff6a3215a488de0dcf9626396f8640c4

docs/auto_examples/all_actions_machine.rst

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ All actions machine
2323

2424
A StateMachine that exercices all possible :ref:`Actions` and :ref:`Guards`.
2525

26-
.. GENERATED FROM PYTHON SOURCE LINES 8-120
26+
.. GENERATED FROM PYTHON SOURCE LINES 8-123
2727
2828
.. code-block:: default
2929
@@ -41,7 +41,7 @@ A StateMachine that exercices all possible :ref:`Actions` and :ref:`Guards`.
4141
go = initial.to(
4242
final,
4343
validators=["validation_1", "validation_2"],
44-
conditions=["condition_1", "condition_2"],
44+
cond=["condition_1", "condition_2"],
4545
unless=["unless_1", "unless_2"],
4646
on_execute=["on_execute_1", "on_execute_2"],
4747
before=["before_go_inline_1", "before_go_inline_2"],
@@ -52,7 +52,7 @@ A StateMachine that exercices all possible :ref:`Actions` and :ref:`Guards`.
5252
self.spy = mock.Mock(side_effect=lambda x: x)
5353
super(AllActionsMachine, self).__init__(*args, **kwargs)
5454
55-
# validations and conditions
55+
# validators and guards
5656
5757
def validation_1(self):
5858
# this method may raise an exception
@@ -91,17 +91,14 @@ A StateMachine that exercices all possible :ref:`Actions` and :ref:`Guards`.
9191
def before_transition(self):
9292
return self.spy("before_transition")
9393
94+
def on_transition(self):
95+
return self.spy("on_transition")
96+
9497
def after_transition(self):
9598
return self.spy("after_transition")
9699
97100
# before / after specific
98101
99-
def on_execute_1(self):
100-
return self.spy("on_execute_1")
101-
102-
def on_execute_2(self):
103-
return self.spy("on_execute_2")
104-
105102
def before_go_inline_1(self):
106103
return self.spy("before_go_inline_1")
107104
@@ -111,6 +108,12 @@ A StateMachine that exercices all possible :ref:`Actions` and :ref:`Guards`.
111108
def before_go(self):
112109
return self.spy("before_go")
113110
111+
def on_execute_1(self):
112+
return self.spy("on_execute_1")
113+
114+
def on_execute_2(self):
115+
return self.spy("on_execute_2")
116+
114117
def on_go(self):
115118
return self.spy("on_go")
116119
@@ -151,12 +154,12 @@ A StateMachine that exercices all possible :ref:`Actions` and :ref:`Guards`.
151154

152155

153156

154-
.. GENERATED FROM PYTHON SOURCE LINES 121-123
157+
.. GENERATED FROM PYTHON SOURCE LINES 124-126
155158
156159
Testing
157160
-------
158161

159-
.. GENERATED FROM PYTHON SOURCE LINES 123-128
162+
.. GENERATED FROM PYTHON SOURCE LINES 126-131
160163
161164
.. code-block:: default
162165
@@ -172,11 +175,11 @@ Testing
172175
173176
174177
175-
.. GENERATED FROM PYTHON SOURCE LINES 129-130
178+
.. GENERATED FROM PYTHON SOURCE LINES 132-133
176179
177-
Only before actions have their result collected.
180+
Only before/on actions have their result collected.
178181

179-
.. GENERATED FROM PYTHON SOURCE LINES 130-142
182+
.. GENERATED FROM PYTHON SOURCE LINES 133-146
180183
181184
.. code-block:: default
182185
@@ -186,9 +189,10 @@ Only before actions have their result collected.
186189
"before_transition",
187190
"before_go_inline_1",
188191
"before_go_inline_2",
192+
"before_go",
193+
"on_transition",
189194
"on_execute_1",
190195
"on_execute_2",
191-
"before_go",
192196
"on_go",
193197
]
194198
@@ -199,35 +203,44 @@ Only before actions have their result collected.
199203
200204
201205
202-
.. GENERATED FROM PYTHON SOURCE LINES 143-144
206+
.. GENERATED FROM PYTHON SOURCE LINES 147-148
203207
204208
Checking the method resolution order
205209

206-
.. GENERATED FROM PYTHON SOURCE LINES 144-170
210+
.. GENERATED FROM PYTHON SOURCE LINES 148-183
207211
208212
.. code-block:: default
209213
210214
211215
assert spy.call_args_list == [
212216
mock.call("on_enter_state"),
213217
mock.call("on_enter_initial"),
218+
214219
mock.call("validation_1"),
215220
mock.call("validation_2"),
221+
216222
mock.call("condition_1"),
217223
mock.call("condition_2"),
224+
218225
mock.call("unless_1"),
219226
mock.call("unless_2"),
227+
220228
mock.call("before_transition"),
221229
mock.call("before_go_inline_1"),
222230
mock.call("before_go_inline_2"),
223-
mock.call("on_execute_1"),
224-
mock.call("on_execute_2"),
225231
mock.call("before_go"),
226-
mock.call("on_go"),
232+
227233
mock.call("on_exit_state"),
228234
mock.call("on_exit_initial"),
235+
236+
mock.call("on_transition"),
237+
mock.call("on_execute_1"),
238+
mock.call("on_execute_2"),
239+
mock.call("on_go"),
240+
229241
mock.call("on_enter_state"),
230242
mock.call("on_enter_final"),
243+
231244
mock.call("after_go_inline_1"),
232245
mock.call("after_go_inline_2"),
233246
mock.call("after_go"),

0 commit comments

Comments
 (0)