0
# Core State Machine and States
1
2
Fundamental state machine functionality that provides the foundation for finite state machine implementation in Python. This includes the main StateMachine class, State objects, and basic state management operations.
3
4
## Capabilities
5
6
### StateMachine Class
7
8
The main class that orchestrates states, events, and transitions with support for both synchronous and asynchronous execution.
9
10
```python { .api }
11
class StateMachine:
12
"""
13
Main state machine class providing finite state machine functionality.
14
15
Parameters:
16
- model: External object to store state (optional)
17
- state_field: Model field name for state storage (default: "state")
18
- start_value: Initial state value if no current state assigned (optional)
19
- rtc: Run-to-completion model control (default: True)
20
- allow_event_without_transition: Allow events without transitions (default: False)
21
- listeners: Optional list of listener objects for callbacks (optional)
22
"""
23
def __init__(self, model=None, state_field: str = "state", start_value=None, rtc: bool = True, allow_event_without_transition: bool = False, listeners=None): ...
24
25
def send(self, event: str, *args, **kwargs):
26
"""
27
Send an event to the state machine to trigger transitions.
28
29
Parameters:
30
- event: Event identifier string
31
- args: Positional arguments passed to callbacks
32
- kwargs: Keyword arguments passed to callbacks
33
34
Returns:
35
Result from event processing or callback return values
36
"""
37
38
@property
39
def current_state(self) -> State:
40
"""Get the currently active state."""
41
42
@property
43
def current_state_value(self):
44
"""Get or set the current state value (for external model integration)."""
45
46
@current_state_value.setter
47
def current_state_value(self, value):
48
"""Set the current state value."""
49
50
@property
51
def states(self) -> States:
52
"""Get States collection containing all states in the machine."""
53
54
@property
55
def events(self) -> list:
56
"""Get list of all events in the machine."""
57
58
@property
59
def allowed_events(self) -> list:
60
"""Get list of events allowed from current state."""
61
62
def activate_initial_state(self):
63
"""Manually activate the initial state (useful for async state machines)."""
64
65
def bind_events_to(self, *targets):
66
"""
67
Bind event methods to target objects.
68
69
Parameters:
70
- targets: Objects to bind event methods to
71
"""
72
73
def add_listener(self, *listeners):
74
"""
75
Add listener objects for callback notifications.
76
77
Parameters:
78
- listeners: Objects that will receive callback notifications
79
"""
80
81
def _graph(self):
82
"""Get DotGraphMachine instance for diagram generation."""
83
84
def _repr_html_(self):
85
"""HTML representation for Jupyter notebooks."""
86
87
def _repr_svg_(self):
88
"""SVG representation for Jupyter notebooks."""
89
```
90
91
### State Class
92
93
Represents individual states in the state machine with support for initial/final states, entry/exit actions, and transition building.
94
95
```python { .api }
96
class State:
97
"""
98
Represents a state in the state machine.
99
100
Parameters:
101
- name: Human-readable state name (derived from variable name if not provided)
102
- value: Specific value for state storage and retrieval (optional)
103
- initial: Set True if this is the initial state (default: False)
104
- final: Set True if this is a final state (default: False)
105
- enter: Entry action callbacks (optional)
106
- exit: Exit action callbacks (optional)
107
"""
108
def __init__(self, name: str = "", value=None, initial: bool = False, final: bool = False, enter=None, exit=None): ...
109
110
def to(self, *states, **kwargs) -> TransitionList:
111
"""
112
Create transitions from this state to target states.
113
114
Parameters:
115
- states: Target State objects
116
- kwargs: Transition parameters (event, cond, unless, on, before, after, etc.)
117
118
Returns:
119
TransitionList containing the created transitions
120
"""
121
122
def from_(self, *states, **kwargs) -> TransitionList:
123
"""
124
Create transitions from source states to this state.
125
126
Parameters:
127
- states: Source State objects
128
- kwargs: Transition parameters
129
130
Returns:
131
TransitionList containing the created transitions
132
"""
133
134
@property
135
def is_active(self) -> bool:
136
"""Check if this state is currently active."""
137
138
@property
139
def transitions(self) -> TransitionList:
140
"""Get transitions originating from this state."""
141
142
@property
143
def id(self) -> str:
144
"""Get the state identifier."""
145
146
@property
147
def name(self) -> str:
148
"""Get the human-readable state name."""
149
150
@property
151
def value(self):
152
"""Get the state value used for storage."""
153
154
@property
155
def initial(self) -> bool:
156
"""Check if this is the initial state."""
157
158
@property
159
def final(self) -> bool:
160
"""Check if this is a final state."""
161
162
@property
163
def enter(self):
164
"""Entry callbacks grouper for adding entry actions."""
165
166
@property
167
def exit(self):
168
"""Exit callbacks grouper for adding exit actions."""
169
```
170
171
### States Collection Class
172
173
Helper class for managing collections of State objects, particularly useful when creating states from external sources like Enums.
174
175
```python { .api }
176
class States:
177
"""
178
Collection class for managing multiple State objects.
179
180
Supports dictionary-like access and creation from Enum classes.
181
"""
182
def __init__(self, states=None): ...
183
184
@classmethod
185
def from_enum(cls, enum_type, initial, final=None, use_enum_instance=False):
186
"""
187
Create States collection from an Enum class.
188
189
Parameters:
190
- enum_type: Enum class to convert to states
191
- initial: Enum value to mark as initial state
192
- final: Enum value(s) to mark as final states (optional)
193
- use_enum_instance: Whether to use enum instances as state values (default: False)
194
195
Returns:
196
States instance with states created from enum values
197
"""
198
199
def append(self, state: State):
200
"""Add a state to the collection."""
201
202
def items(self):
203
"""Get (id, state) pairs for all states."""
204
205
def __getattr__(self, name: str) -> State:
206
"""Access states by attribute name."""
207
208
def __getitem__(self, key: str) -> State:
209
"""Access states by key name."""
210
211
def __iter__(self):
212
"""Iterate over states."""
213
214
def __len__(self) -> int:
215
"""Get number of states in collection."""
216
```
217
218
### Specialized State Classes
219
220
Extended state functionality for specific use cases.
221
222
```python { .api }
223
class InstanceState(State):
224
"""Runtime state instance with machine binding."""
225
226
class AnyState(State):
227
"""Special state representing any state for transition building."""
228
```
229
230
## Usage Examples
231
232
### Basic State Machine Definition
233
234
```python
235
from statemachine import StateMachine, State
236
237
class DocumentWorkflow(StateMachine):
238
# Define states
239
draft = State(initial=True)
240
review = State()
241
approved = State()
242
published = State(final=True)
243
rejected = State(final=True)
244
245
# Define transitions
246
submit = draft.to(review)
247
approve = review.to(approved)
248
publish = approved.to(published)
249
reject = review.to(rejected) | approved.to(rejected)
250
revise = review.to(draft) | approved.to(draft)
251
252
# Create instance
253
workflow = DocumentWorkflow()
254
print(workflow.current_state.id) # "draft"
255
print(workflow.draft.is_active) # True
256
```
257
258
### Using External Model
259
260
```python
261
class Document:
262
def __init__(self):
263
self.status = "draft"
264
265
# Bind to external model
266
doc = Document()
267
workflow = DocumentWorkflow(doc, state_field="status")
268
269
# State is stored in document object
270
workflow.send("submit")
271
print(doc.status) # "review"
272
```
273
274
### Creating States from Enum
275
276
```python
277
from enum import Enum
278
from statemachine.states import States
279
280
class Status(Enum):
281
PENDING = "pending"
282
PROCESSING = "processing"
283
COMPLETED = "completed"
284
FAILED = "failed"
285
286
class JobMachine(StateMachine):
287
states = States.from_enum(
288
Status,
289
initial=Status.PENDING,
290
final=[Status.COMPLETED, Status.FAILED]
291
)
292
293
start = states.pending.to(states.processing)
294
complete = states.processing.to(states.completed)
295
fail = states.processing.to(states.failed)
296
```
297
298
### Async State Machine
299
300
```python
301
import asyncio
302
from statemachine import StateMachine, State
303
304
class AsyncMachine(StateMachine):
305
idle = State(initial=True)
306
working = State()
307
done = State(final=True)
308
309
start = idle.to(working)
310
finish = working.to(done)
311
312
async def on_enter_working(self):
313
print("Starting async work...")
314
await asyncio.sleep(1)
315
print("Work completed")
316
317
# Usage
318
async def main():
319
machine = AsyncMachine()
320
await machine.send_async("start")
321
await machine.send_async("finish")
322
323
asyncio.run(main())
324
```