Skip to content

Commit fe2fd15

Browse files
committed
docs: Update readme
1 parent 2bc483c commit fe2fd15

2 files changed

Lines changed: 64 additions & 47 deletions

File tree

README.md

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,52 @@
11
# Python StateMachine
22

33
[![pypi](https://img.shields.io/pypi/v/python-statemachine.svg)](https://pypi.python.org/pypi/python-statemachine)
4+
[![downloads total](https://static.pepy.tech/badge/python-statemachine)](https://pepy.tech/project/python-statemachine)
45
[![downloads](https://img.shields.io/pypi/dm/python-statemachine.svg)](https://pypi.python.org/pypi/python-statemachine)
5-
[![build status](https://github.com/fgmacedo/python-statemachine/actions/workflows/python-package.yml/badge.svg?branch=develop)](https://github.com/fgmacedo/python-statemachine/actions/workflows/python-package.yml?query=branch%3Adevelop)
66
[![Coverage report](https://codecov.io/gh/fgmacedo/python-statemachine/branch/develop/graph/badge.svg)](https://codecov.io/gh/fgmacedo/python-statemachine)
77
[![Documentation Status](https://readthedocs.org/projects/python-statemachine/badge/?version=latest)](https://python-statemachine.readthedocs.io/en/latest/?badge=latest)
88
[![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)
99

1010

1111
Python [finite-state machines](https://en.wikipedia.org/wiki/Finite-state_machine) made easy.
1212

13+
<div align="center">
1314

14-
* Free software: MIT license
15-
* Documentation: https://python-statemachine.readthedocs.io.
15+
![](https://github.com/fgmacedo/python-statemachine/blob/develop/docs/images/python-statemachine.png?raw=true)
1616

17+
</div>
1718

1819
Welcome to python-statemachine, an intuitive and powerful state machine framework designed for a
19-
great developer experience.
20-
21-
🚀 With StateMachine, you can easily create complex, dynamic systems with clean, readable code.
22-
23-
💡 Our framework makes it easy to understand and reason about the different states, events and
24-
transitions in your system, so you can focus on building great products.
25-
26-
🔒 python-statemachine also provides robust error handling and ensures that your system stays
27-
in a valid state at all times.
28-
29-
30-
A few reasons why you may consider using it:
31-
32-
* 📈 python-statemachine is designed to help you build scalable,
33-
maintainable systems that can handle any complexity.
34-
* 💪 You can easily create and manage multiple state machines within a single application.
35-
* 🚫 Prevents common mistakes and ensures that your system stays in a valid state at all times.
36-
37-
38-
## Getting started
39-
20+
great developer experience. We provide an _pythonic_ and expressive API for implementing state
21+
machines in sync or asynchonous Python codebases.
22+
23+
## Features
24+
25+
-**Basic components**: Easily define **States**, **Events**, and **Transitions** to model your logic.
26+
- ⚙️ **Actions and handlers**: Attach actions and handlers to states, events, and transitions to control behavior dynamically.
27+
- 🛡️ **Conditional transitions**: Implement **Guards** and **Validators** to conditionally control transitions, ensuring they only occur when specific conditions are met.
28+
- 🚀 **Full async support**: Enjoy full asynchronous support. Await events, and dispatch callbacks asynchronously for seamless integration with async codebases.
29+
- 🔄 **Full sync support**: Use the same state machine from synchronous codebases without any modifications.
30+
- 🎨 **Declarative and simple API**: Utilize a clean, elegant, and readable API to define your state machine, making it easy to maintain and understand.
31+
- 👀 **Observer pattern support**: Register external and generic objects to watch events and register callbacks.
32+
- 🔍 **Decoupled design**: Separate concerns with a decoupled "state machine" and "model" design, promoting cleaner architecture and easier maintenance.
33+
-**Correctness guarantees**: Ensured correctness with validations at class definition time:
34+
- Ensures exactly one `initial` state.
35+
- Disallows transitions from `final` states.
36+
- Requires ongoing transitions for all non-final states.
37+
- Guarantees all non-final states have at least one path to a final state if final states are declared.
38+
- Validates the state machine graph representation has a single component.
39+
- 📦 **Flexible event dispatching**: Dispatch events with any extra data, making it available to all callbacks, including actions and guards.
40+
- 🔧 **Dependency injection**: Needed parameters are injected into callbacks.
41+
- 📊 **Graphical representation**: Generate and output graphical representations of state machines. Create diagrams from the command line, at runtime, or even in Jupyter notebooks.
42+
- 🌍 **Internationalization support**: Provides error messages in different languages, making the library accessible to a global audience.
43+
- 🛡️ **Robust testing**: Ensured reliability with a codebase that is 100% covered by automated tests, including all docs examples. Releases follow semantic versioning for predictable releases.
44+
- 🏛️ **Domain model integration**: Seamlessly integrate with domain models using Mixins.
45+
- 🔧 **Django integration**: Automatically discover state machines in Django applications.
46+
47+
48+
49+
## Installing
4050

4151
To install Python State Machine, run this command in your terminal:
4252

@@ -48,6 +58,8 @@ our docs for more details.
4858

4959
pip install python-statemachine[diagrams]
5060

61+
## First example
62+
5163
Define your state machine:
5264

5365
```py
@@ -108,7 +120,27 @@ Then start sending events to your new state machine:
108120

109121
```
110122

111-
That's it. This is all an external object needs to know about your state machine: How to send events.
123+
You can use the exactly same state machine from an async codebase:
124+
125+
126+
```py
127+
>>> async def run_sm():
128+
... asm = TrafficLightMachine()
129+
... results = []
130+
... for _i in range(4):
131+
... result = await asm.send("cycle")
132+
... results.append(result)
133+
... return results
134+
135+
>>> asyncio.run(run_sm())
136+
Don't move.
137+
Go ahead!
138+
['Running cycle from green to yellow', 'Running cycle from yellow to red', ...
139+
140+
```
141+
142+
143+
**That's it.** This is all an external object needs to know about your state machine: How to send events.
112144
Ideally, all states, transitions, and actions should be kept internally and not checked externally to avoid unnecessary coupling.
113145

114146
But if your use case needs, you can inspect state machine properties, like the current state:

docs/releases/2.3.0.md

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44

55
## What's new in 2.3.0
66

7-
In this release, we conducted a significant update focusing on adding asynchronous support, and enhancing overall functionality. In fact, the approach we took was to go all the way down changing the internals of the library to be fully async, keeping only the current external API as a thin sync wrapper.
7+
This release has a high expected feature, we're adding [asynchronous support](../async.md), and enhancing overall functionality. In fact, the approach we took was to go all the way down changing the internals of the library to be fully async, keeping only the current external API as a thin sync/async adapter.
88

9-
Here are the major changes and new features:
9+
10+
### Python compatibility 2.3.0
11+
12+
StateMachine 2.3.0 supports Python 3.7, 3.8, 3.9, 3.10, 3.11 and 3.12.
13+
14+
We've fixed a bug on the package declaration that was preventing users from Python 3.7 to install the latest version.
1015

1116
### Asynchronous Support in 2.3.0
1217

@@ -37,23 +42,3 @@ async code with a state machine.
3742
Final
3843

3944
```
40-
41-
42-
### Manual Initial State Activation for Async Code
43-
44-
When working with asynchronous state machines from async code, users must manually activate
45-
the initial state . This change ensures proper state initialization and execution flow given that
46-
Python don't allow awaiting at class initalization time and the initial state activation may contain
47-
async callbacks that must be awaited.
48-
49-
```py
50-
>>> async def initialize_sm():
51-
... sm = AsyncStateMachine()
52-
... await sm.activate_initial_state()
53-
... return sm
54-
55-
>>> sm = asyncio.run(initialize_sm())
56-
>>> print(sm.current_state)
57-
Initial
58-
59-
```

0 commit comments

Comments
 (0)