python-statemachine 2.5.0__py3-none-any.whl → 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. python_statemachine-3.0.0.dist-info/METADATA +414 -0
  2. python_statemachine-3.0.0.dist-info/RECORD +48 -0
  3. {python_statemachine-2.5.0.dist-info → python_statemachine-3.0.0.dist-info}/WHEEL +1 -1
  4. statemachine/__init__.py +14 -2
  5. statemachine/callbacks.py +131 -38
  6. statemachine/contrib/diagram.py +178 -50
  7. statemachine/contrib/timeout.py +68 -0
  8. statemachine/contrib/weighted.py +193 -0
  9. statemachine/dispatcher.py +2 -2
  10. statemachine/engines/async_.py +495 -92
  11. statemachine/engines/base.py +921 -18
  12. statemachine/engines/sync.py +163 -87
  13. statemachine/event.py +92 -23
  14. statemachine/event_data.py +26 -11
  15. statemachine/events.py +12 -3
  16. statemachine/exceptions.py +8 -4
  17. statemachine/factory.py +165 -67
  18. statemachine/graph.py +46 -4
  19. statemachine/invoke.py +603 -0
  20. statemachine/io/__init__.py +225 -0
  21. statemachine/io/scxml/__init__.py +0 -0
  22. statemachine/io/scxml/actions.py +649 -0
  23. statemachine/io/scxml/invoke.py +233 -0
  24. statemachine/io/scxml/parser.py +473 -0
  25. statemachine/io/scxml/processor.py +263 -0
  26. statemachine/io/scxml/schema.py +175 -0
  27. statemachine/locale/en/LC_MESSAGES/statemachine.po +78 -37
  28. statemachine/locale/hi_IN/LC_MESSAGES/statemachine.po +86 -35
  29. statemachine/locale/pt_BR/LC_MESSAGES/statemachine.po +87 -35
  30. statemachine/locale/zh_CN/LC_MESSAGES/statemachine.po +64 -29
  31. statemachine/mixins.py +11 -0
  32. statemachine/orderedset.py +118 -0
  33. statemachine/registry.py +4 -10
  34. statemachine/signature.py +82 -8
  35. statemachine/spec_parser.py +112 -17
  36. statemachine/state.py +227 -26
  37. statemachine/statemachine.py +310 -78
  38. statemachine/states.py +22 -19
  39. statemachine/transition.py +46 -8
  40. statemachine/transition_list.py +7 -0
  41. statemachine/transition_mixin.py +14 -3
  42. statemachine/utils.py +2 -1
  43. python_statemachine-2.5.0.dist-info/METADATA +0 -429
  44. python_statemachine-2.5.0.dist-info/RECORD +0 -37
  45. {python_statemachine-2.5.0.dist-info → python_statemachine-3.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,414 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-statemachine
3
+ Version: 3.0.0
4
+ Summary: Python Finite State Machines made easy.
5
+ Project-URL: homepage, https://github.com/fgmacedo/python-statemachine
6
+ Author-email: Fernando Macedo <fgmacedo@gmail.com>
7
+ Maintainer-email: Fernando Macedo <fgmacedo@gmail.com>
8
+ License: MIT License
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Framework :: AsyncIO
12
+ Classifier: Framework :: Django
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Natural Language :: English
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Home Automation
23
+ Classifier: Topic :: Software Development :: Libraries
24
+ Requires-Python: >=3.9
25
+ Provides-Extra: diagrams
26
+ Requires-Dist: pydot>=2.0.0; extra == 'diagrams'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # Python StateMachine
30
+
31
+ [![pypi](https://img.shields.io/pypi/v/python-statemachine.svg)](https://pypi.python.org/pypi/python-statemachine)
32
+ [![downloads total](https://static.pepy.tech/badge/python-statemachine)](https://pepy.tech/project/python-statemachine)
33
+ [![downloads](https://img.shields.io/pypi/dm/python-statemachine.svg)](https://pypi.python.org/pypi/python-statemachine)
34
+ [![Coverage report](https://codecov.io/gh/fgmacedo/python-statemachine/branch/develop/graph/badge.svg)](https://codecov.io/gh/fgmacedo/python-statemachine)
35
+ [![Documentation Status](https://readthedocs.org/projects/python-statemachine/badge/?version=latest)](https://python-statemachine.readthedocs.io/en/latest/?badge=latest)
36
+ [![GitHub commits since last release (main)](https://img.shields.io/github/commits-since/fgmacedo/python-statemachine/main/develop)](https://github.com/fgmacedo/python-statemachine/compare/main...develop)
37
+
38
+ Expressive [statecharts](https://statecharts.dev/) and [FSMs](https://en.wikipedia.org/wiki/Finite-state_machine) for modern Python.
39
+
40
+ <div align="center">
41
+
42
+ ![](https://github.com/fgmacedo/python-statemachine/blob/develop/docs/images/python-statemachine.png?raw=true)
43
+
44
+ </div>
45
+
46
+ Welcome to python-statemachine, an intuitive and powerful state machine library designed for a
47
+ great developer experience. Define flat state machines or full statecharts with compound states,
48
+ parallel regions, and history — all with a clean, _pythonic_, declarative API that works in both
49
+ sync and async Python codebases.
50
+
51
+
52
+ ## Quick start
53
+
54
+ ```py
55
+ >>> from statemachine import StateChart, State
56
+
57
+ >>> class TrafficLightMachine(StateChart):
58
+ ... "A traffic light machine"
59
+ ... green = State(initial=True)
60
+ ... yellow = State()
61
+ ... red = State()
62
+ ...
63
+ ... cycle = (
64
+ ... green.to(yellow)
65
+ ... | yellow.to(red)
66
+ ... | red.to(green)
67
+ ... )
68
+ ...
69
+ ... def before_cycle(self, event: str, source: State, target: State):
70
+ ... return f"Running {event} from {source.id} to {target.id}"
71
+ ...
72
+ ... def on_enter_red(self):
73
+ ... print("Don't move.")
74
+ ...
75
+ ... def on_exit_red(self):
76
+ ... print("Go ahead!")
77
+
78
+ ```
79
+
80
+ Create an instance and send events:
81
+
82
+ ```py
83
+ >>> sm = TrafficLightMachine()
84
+ >>> sm.send("cycle")
85
+ 'Running cycle from green to yellow'
86
+
87
+ >>> sm.send("cycle")
88
+ Don't move.
89
+ 'Running cycle from yellow to red'
90
+
91
+ >>> sm.send("cycle")
92
+ Go ahead!
93
+ 'Running cycle from red to green'
94
+
95
+ ```
96
+
97
+ Check which states are active:
98
+
99
+ ```py
100
+ >>> sm.configuration
101
+ OrderedSet([State('Green', id='green', value='green', initial=True, final=False, parallel=False)])
102
+
103
+ >>> sm.green.is_active
104
+ True
105
+
106
+ ```
107
+
108
+ Generate a diagram:
109
+
110
+ ```py
111
+ >>> # This example will only run on automated tests if dot is present
112
+ >>> getfixture("requires_dot_installed")
113
+ >>> img_path = "docs/images/readme_trafficlightmachine.png"
114
+ >>> sm._graph().write_png(img_path)
115
+
116
+ ```
117
+
118
+ ![](https://raw.githubusercontent.com/fgmacedo/python-statemachine/develop/docs/images/readme_trafficlightmachine.png)
119
+
120
+ Parameters are injected into callbacks automatically — the library inspects the
121
+ signature and provides only the arguments each callback needs:
122
+
123
+ ```py
124
+ >>> sm.send("cycle")
125
+ 'Running cycle from green to yellow'
126
+
127
+ ```
128
+
129
+
130
+ ## Guards and conditional transitions
131
+
132
+ Use `cond=` and `unless=` to add guards. When multiple transitions share the same
133
+ event, declaration order determines priority:
134
+
135
+ ```py
136
+ >>> from statemachine import StateChart, State
137
+
138
+ >>> class ApprovalWorkflow(StateChart):
139
+ ... pending = State(initial=True)
140
+ ... approved = State(final=True)
141
+ ... rejected = State(final=True)
142
+ ...
143
+ ... review = (
144
+ ... pending.to(approved, cond="is_valid")
145
+ ... | pending.to(rejected)
146
+ ... )
147
+ ...
148
+ ... def is_valid(self, score: int = 0):
149
+ ... return score >= 70
150
+
151
+ >>> sm = ApprovalWorkflow()
152
+ >>> sm.send("review", score=50)
153
+ >>> sm.rejected.is_active
154
+ True
155
+
156
+ >>> sm = ApprovalWorkflow()
157
+ >>> sm.send("review", score=85)
158
+ >>> sm.approved.is_active
159
+ True
160
+
161
+ ```
162
+
163
+ The first transition whose guard passes wins. When `score < 70`, `is_valid` returns
164
+ `False` so the second transition (no guard — always matches) fires instead.
165
+
166
+
167
+ ## Compound states — hierarchy
168
+
169
+ Break complex behavior into hierarchical levels with `State.Compound`. Entering a
170
+ compound activates both the parent and its `initial` child. Exiting removes the
171
+ parent and all descendants:
172
+
173
+ ```py
174
+ >>> from statemachine import StateChart, State
175
+
176
+ >>> class DocumentWorkflow(StateChart):
177
+ ... class editing(State.Compound):
178
+ ... draft = State(initial=True)
179
+ ... review = State()
180
+ ... submit = draft.to(review)
181
+ ... revise = review.to(draft)
182
+ ...
183
+ ... published = State(final=True)
184
+ ... approve = editing.to(published)
185
+
186
+ >>> sm = DocumentWorkflow()
187
+ >>> set(sm.configuration_values) == {"editing", "draft"}
188
+ True
189
+
190
+ >>> sm.send("submit")
191
+ >>> "review" in sm.configuration_values
192
+ True
193
+
194
+ >>> sm.send("approve")
195
+ >>> set(sm.configuration_values) == {"published"}
196
+ True
197
+
198
+ ```
199
+
200
+
201
+ ## Parallel states — concurrency
202
+
203
+ `State.Parallel` activates all child regions simultaneously. Events in one
204
+ region don't affect others. A `done.state` event fires only when **all**
205
+ regions reach a final state:
206
+
207
+ ```py
208
+ >>> from statemachine import StateChart, State
209
+
210
+ >>> class DeployPipeline(StateChart):
211
+ ... class deploy(State.Parallel):
212
+ ... class build(State.Compound):
213
+ ... compiling = State(initial=True)
214
+ ... compiled = State(final=True)
215
+ ... finish_build = compiling.to(compiled)
216
+ ... class tests(State.Compound):
217
+ ... running = State(initial=True)
218
+ ... passed = State(final=True)
219
+ ... finish_tests = running.to(passed)
220
+ ... released = State(final=True)
221
+ ... done_state_deploy = deploy.to(released)
222
+
223
+ >>> sm = DeployPipeline()
224
+ >>> "compiling" in sm.configuration_values and "running" in sm.configuration_values
225
+ True
226
+
227
+ >>> sm.send("finish_build")
228
+ >>> "compiled" in sm.configuration_values and "running" in sm.configuration_values
229
+ True
230
+
231
+ >>> sm.send("finish_tests")
232
+ >>> set(sm.configuration_values) == {"released"}
233
+ True
234
+
235
+ ```
236
+
237
+
238
+ ## History states
239
+
240
+ `HistoryState()` records which child was active when a compound is exited.
241
+ Re-entering via the history pseudo-state restores the previous child instead
242
+ of starting from the initial one:
243
+
244
+ ```py
245
+ >>> from statemachine import HistoryState, StateChart, State
246
+
247
+ >>> class EditorWithHistory(StateChart):
248
+ ... class editor(State.Compound):
249
+ ... source = State(initial=True)
250
+ ... visual = State()
251
+ ... h = HistoryState()
252
+ ... toggle = source.to(visual) | visual.to(source)
253
+ ... settings = State()
254
+ ... open_settings = editor.to(settings)
255
+ ... back = settings.to(editor.h)
256
+
257
+ >>> sm = EditorWithHistory()
258
+ >>> sm.send("toggle")
259
+ >>> "visual" in sm.configuration_values
260
+ True
261
+
262
+ >>> sm.send("open_settings")
263
+ >>> sm.send("back")
264
+ >>> "visual" in sm.configuration_values
265
+ True
266
+
267
+ ```
268
+
269
+ Use `HistoryState(type="deep")` for deep history that remembers the exact leaf
270
+ state across nested compounds.
271
+
272
+
273
+ ## Eventless transitions
274
+
275
+ Transitions without an event trigger fire automatically. With a guard, they
276
+ fire after any event processing when the condition is met:
277
+
278
+ ```py
279
+ >>> from statemachine import StateChart, State
280
+
281
+ >>> class AutoCounter(StateChart):
282
+ ... counting = State(initial=True)
283
+ ... done = State(final=True)
284
+ ...
285
+ ... counting.to(done, cond="limit_reached")
286
+ ... increment = counting.to.itself(internal=True, on="do_increment")
287
+ ...
288
+ ... count = 0
289
+ ...
290
+ ... def do_increment(self):
291
+ ... self.count += 1
292
+ ... def limit_reached(self):
293
+ ... return self.count >= 3
294
+
295
+ >>> sm = AutoCounter()
296
+ >>> sm.send("increment")
297
+ >>> sm.send("increment")
298
+ >>> "counting" in sm.configuration_values
299
+ True
300
+
301
+ >>> sm.send("increment")
302
+ >>> "done" in sm.configuration_values
303
+ True
304
+
305
+ ```
306
+
307
+
308
+ ## Error handling
309
+
310
+ When using `StateChart`, runtime exceptions in callbacks are caught and
311
+ turned into `error.execution` events. Define a transition for that event
312
+ to handle errors within the state machine itself:
313
+
314
+ ```py
315
+ >>> from statemachine import StateChart, State
316
+
317
+ >>> class ResilientService(StateChart):
318
+ ... running = State(initial=True)
319
+ ... failed = State(final=True)
320
+ ...
321
+ ... process = running.to(running, on="do_work")
322
+ ... error_execution = running.to(failed)
323
+ ...
324
+ ... def do_work(self):
325
+ ... raise RuntimeError("something broke")
326
+
327
+ >>> sm = ResilientService()
328
+ >>> sm.send("process")
329
+ >>> sm.failed.is_active
330
+ True
331
+
332
+ ```
333
+
334
+
335
+ ## Async support
336
+
337
+ Async callbacks just work — same API, no changes needed. The engine
338
+ detects async callbacks and switches to the async engine automatically:
339
+
340
+ ```py
341
+ >>> import asyncio
342
+ >>> from statemachine import StateChart, State
343
+
344
+ >>> class AsyncWorkflow(StateChart):
345
+ ... idle = State(initial=True)
346
+ ... done = State(final=True)
347
+ ...
348
+ ... finish = idle.to(done)
349
+ ...
350
+ ... async def on_finish(self):
351
+ ... return 42
352
+
353
+ >>> async def run():
354
+ ... sm = AsyncWorkflow()
355
+ ... result = await sm.finish()
356
+ ... print(f"Result: {result}")
357
+ ... print(sm.done.is_active)
358
+
359
+ >>> asyncio.run(run())
360
+ Result: 42
361
+ True
362
+
363
+ ```
364
+
365
+
366
+ ## More features
367
+
368
+ There's a lot more to explore:
369
+
370
+ - **DoneData** on final states — pass structured data to `done.state` handlers
371
+ - **Delayed events** — schedule events with `sm.send("event", delay=500)`
372
+ - **`In(state)` conditions** — cross-region guards in parallel states
373
+ - **`prepare_event`** callback — inject custom data into all callbacks
374
+ - **Observer pattern** — register external listeners to watch events and state changes
375
+ - **Django integration** — auto-discover state machines in Django apps with `MachineMixin`
376
+ - **Diagram generation** — from the CLI, at runtime, or in Jupyter notebooks
377
+ - **Dictionary-based definitions** — create state machines from data structures
378
+ - **Internationalization** — error messages in multiple languages
379
+
380
+ Full documentation: https://python-statemachine.readthedocs.io
381
+
382
+
383
+ ## Installing
384
+
385
+ ```
386
+ pip install python-statemachine
387
+ ```
388
+
389
+ To generate diagrams, install with the `diagrams` extra (requires
390
+ [Graphviz](https://graphviz.org/)):
391
+
392
+ ```
393
+ pip install python-statemachine[diagrams]
394
+ ```
395
+
396
+
397
+ ## Contributing
398
+
399
+ - If you found this project helpful, please consider giving it a star on GitHub.
400
+
401
+ - **Contribute code**: If you would like to contribute code, please submit a pull
402
+ request. For more information on how to contribute, please see our [contributing.md](contributing.md) file.
403
+
404
+ - **Report bugs**: If you find any bugs, please report them by opening an issue
405
+ on our GitHub issue tracker.
406
+
407
+ - **Suggest features**: If you have an idea for a new feature, or feel something is harder than it should be,
408
+ please let us know by opening an issue on our GitHub issue tracker.
409
+
410
+ - **Documentation**: Help improve documentation by submitting pull requests.
411
+
412
+ - **Promote the project**: Help spread the word by sharing on social media,
413
+ writing a blog post, or giving a talk about it. Tag me on Twitter
414
+ [@fgmacedo](https://twitter.com/fgmacedo) so I can share it too!
@@ -0,0 +1,48 @@
1
+ statemachine/__init__.py,sha256=KP0MJDUTjW1ds6_fMRp5ijZdyVERZjr8bPi5z28dEx4,445
2
+ statemachine/callbacks.py,sha256=mY_RAl86240vG2C94ij6AdD7CgsIM8mr0wvpSAMAPv0,14644
3
+ statemachine/dispatcher.py,sha256=xvA1Kf1xGQivHTpaGm_HC22vqAmE_tTm9LQwyVLRWLE,7841
4
+ statemachine/event.py,sha256=OFYe1ra46VXmlIEOt6Daj1exxws2FgatV5O8htcrTs8,7287
5
+ statemachine/event_data.py,sha256=4pDNcrlhqTTIaP_IlcmyB4g8kJkjj6XNb33rHKAQ924,3076
6
+ statemachine/events.py,sha256=OPg7DgocYfe5TCsLd-gLGp9BPInHGSHgeYu4yyQjUIk,1224
7
+ statemachine/exceptions.py,sha256=gXFvDsEtIxKdcGrRG9mwDgXqFQDXfw8v66_VXaQgGr4,1305
8
+ statemachine/factory.py,sha256=UlLLzh5VxGd2V3MalpQ-Amg7LmC4UsJF5ww7wEyCaIM,13442
9
+ statemachine/graph.py,sha256=r-8L7jXab1_VLtVu-Ig8bpe4Szo-r6WDFTdbfcepyZM,1981
10
+ statemachine/i18n.py,sha256=NLvGseaORmQ0G-V_J8tkjoxh_piWMOm2CI6mBQpLamc,362
11
+ statemachine/invoke.py,sha256=3hFzMXACEtxdUCi97_6gOHrvQYJRDGjk3sF-OdgAFpU,23384
12
+ statemachine/mixins.py,sha256=8qxZZfBwVdFcr3oPFVWHGzgmAubH6VgQus5x3c6VEE0,1706
13
+ statemachine/model.py,sha256=OylI3FjMiHpYyDl9mtK1zEJMeSvemaN4giQDonpc8kI,211
14
+ statemachine/orderedset.py,sha256=PjbegcS7WPJAzC7jQ411_JrFJYEz6mmLRsAZ7aI9BWc,2543
15
+ statemachine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ statemachine/registry.py,sha256=onT8U5QgYlCSJxgxvi_TY1c1oDetHykOwnyiFk5qoN0,756
17
+ statemachine/signature.py,sha256=N8Vt4X3YOA-NB8oidPAbYZxBgqZm6GYAiuHxBWb1l1s,9922
18
+ statemachine/spec_parser.py,sha256=Io0J5D9s-nu2YdgUlr2cSethGfCS0pSLNmxMCXdwMqQ,8307
19
+ statemachine/state.py,sha256=X1gKN1p75eUKL_Zkso3lDXFIsjNVEGlu05zXocgszKo,16349
20
+ statemachine/statemachine.py,sha256=VBm0X-lpN4701e0TuA_WXC1c79x46mE7qB2PrGTvOas,20281
21
+ statemachine/states.py,sha256=kWo7y95ikXxNmcf_-J2UoMIwd3NaIdxpHMfoHr3cQ_Y,4934
22
+ statemachine/transition.py,sha256=x9hhxIEyQ7tqsvaXkHg1bVO5hMAjemgHfZhyuypHoOY,6936
23
+ statemachine/transition_list.py,sha256=6NAyOGEgoGOzTYiLfPM21CBVI1tPO63ZIwbaZlqOPI4,4376
24
+ statemachine/transition_mixin.py,sha256=XGGd2J4DnFrqIpeej3QFDOuqI0CAiYwnIb8-_9DpemA,2993
25
+ statemachine/utils.py,sha256=tyJqMSQLKcKMwV7xI0oepNVw1Pse243gS7JKvIQWtUk,1080
26
+ statemachine/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ statemachine/contrib/diagram.py,sha256=tGKbw6w7FExev8H6hXpfR4L0Inh9c__z84f5lmtPpOY,11803
28
+ statemachine/contrib/timeout.py,sha256=VXkdLpxNeUKihkbtLv8XTWdG-meQlSFtxJfcxXgV8Uw,2251
29
+ statemachine/contrib/weighted.py,sha256=jcKkm25df6NnzBzuss1-ewDEasZ_CyME03xgJXrwcso,6866
30
+ statemachine/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ statemachine/engines/async_.py,sha256=4oURLGw0DGRQbootRUY5WhOBIkxoFqykghTW4K6SIXs,22629
32
+ statemachine/engines/base.py,sha256=QfCjQyEIWTcOd5lJtFq7u6SUMZA6PDyUPlY2T4unn3E,37467
33
+ statemachine/engines/sync.py,sha256=Z7ItPaKzFwFmm6NSheuekevsYmlmSOmHJs_au0U0D8M,9251
34
+ statemachine/io/__init__.py,sha256=1J_oVSWrWmx9bLrGU-YoWyO-YYbO6T9Z6vUAnerKe3Q,8739
35
+ statemachine/io/scxml/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ statemachine/io/scxml/actions.py,sha256=sxDuJb6AY6TJy6PZpEXBmAclRcnlYytpDcnNKpb_gS4,22447
37
+ statemachine/io/scxml/invoke.py,sha256=raRStlMBOfxto6KIkCbi3jJ3UQ3QfuT0ezn4B48A670,8443
38
+ statemachine/io/scxml/parser.py,sha256=zggZwu0rHZNWDaJTHD2XC3MrCy_bi4CNHStfWE9NHgU,16582
39
+ statemachine/io/scxml/processor.py,sha256=_hjW4VTuzbPK2q5a7dp2kYMBcbRBZFbjz-wJKSZLI8I,9467
40
+ statemachine/io/scxml/schema.py,sha256=xNpW_nkS2Z_hye5p1WLr8VhuM85Nic2HqRLCnoFN3ss,3927
41
+ statemachine/locale/en/LC_MESSAGES/statemachine.po,sha256=m6Fb8W-AQnSPTxYMZ8Xw68rScY4tjZ3wh8KVZQedDE0,4581
42
+ statemachine/locale/hi_IN/LC_MESSAGES/statemachine.po,sha256=3le5j-3QqZ6zW0dE0rBEID9EfOkilyk66IFWSI68aG0,7035
43
+ statemachine/locale/pt_BR/LC_MESSAGES/statemachine.po,sha256=3OYJ_WUKIxmve4yDvIZ9PHBuXYQHCgHXx9bQC1pnIsI,5037
44
+ statemachine/locale/zh_CN/LC_MESSAGES/statemachine.po,sha256=PjOMlWHdgzFXxvjTV1ZgYhOL3NeDpAxlMnJFHsPFdS4,4605
45
+ python_statemachine-3.0.0.dist-info/METADATA,sha256=3nqo-g3T-ibZKRoIVgzEGex90C-rwTgchEexdZDORAE,12121
46
+ python_statemachine-3.0.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
47
+ python_statemachine-3.0.0.dist-info/licenses/LICENSE,sha256=zcP7TsJMqaFxuTvLRZPT7nJl3_ppjxR9Z76BE9pL5zc,1074
48
+ python_statemachine-3.0.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.26.3
2
+ Generator: hatchling 1.29.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
statemachine/__init__.py CHANGED
@@ -1,9 +1,21 @@
1
1
  from .event import Event
2
+ from .state import HistoryState
3
+ from .state import HistoryType
2
4
  from .state import State
5
+ from .statemachine import StateChart
3
6
  from .statemachine import StateMachine
7
+ from .statemachine import TModel
4
8
 
5
9
  __author__ = """Fernando Macedo"""
6
10
  __email__ = "fgmacedo@gmail.com"
7
- __version__ = "2.5.0"
11
+ __version__ = "3.0.0"
8
12
 
9
- __all__ = ["StateMachine", "State", "Event"]
13
+ __all__ = [
14
+ "StateChart",
15
+ "StateMachine",
16
+ "State",
17
+ "HistoryState",
18
+ "HistoryType",
19
+ "Event",
20
+ "TModel",
21
+ ]