State machine analysis library
Project description
smcheck
Automatic analysis, testing, and visualization for python-statemachine state machines.
smcheck gives you confidence in your state machines by:
- ๐ Validating 9 structural properties (reachability, liveness, determinism, completeness, etc.)
- ๐ Analyzing all possible paths through your state machine
- ๐งช Generating pytest tests for every transition and path
- ๐ Exporting interactive Mermaid diagrams with guard labels
Installation
pip install smcheck
For LLM-powered path explanations (optional):
pip install smcheck[llm]
Requires Python โฅ3.11 and python-statemachine โฅ3.0.
Quick Start โ 5 minutes
Define your state machine normally:
# myapp/machine.py
from statemachine import State, StateChart
class OrderFlow(StateChart):
waiting = State(initial=True)
processing = State()
shipped = State(final=True)
cancelled = State(final=True)
submit = waiting.to(processing)
ship = processing.to(shipped)
cancel = processing.to(cancelled) # can cancel during processing
Now run smcheck:
from smcheck import SMCheck
sm = SMCheck(OrderFlow)
# Validation report (9 checks)
sm.report_validation()
# Path analysis
analysis = sm.analyze_paths()
print(f"Total paths: {analysis.combined_count}")
# Auto-generate tests
sm.write_tests(
sm_import="myapp.machine",
output_dir="tests/generated/"
)
# Export diagram
sm.write_mermaid("diagram.mmd")
That's it! You now have:
- โ A validation report
- โ All states are reachable
- โ No deadlocks or infinite loops
- โ Pytest test files for every transition and path
- โ A diagram you can share with stakeholders
The 9 Validation Checks
smcheck validates that your state machine is:
| Check | Detects | Level |
|---|---|---|
| Reachability | States you can't reach from the start | โ ๏ธ WARN |
| Liveness | Deadlocks (states with no way out) | ๐จ ERROR |
| Determinism | Ambiguous transitions (multiple targets for one event) | โ ๏ธ WARN |
| Completeness | Unfinished states (no outgoing transitions) | โ ๏ธ WARN |
| Trap cycles | Infinite loops with no exit | ๐จ ERROR |
| Class flags | Risky behavioral settings | โ ๏ธ WARN |
| Invoke states | States that fire events spontaneously | โน๏ธ INFO |
| Self-transitions | Loops that trigger entry/exit callbacks | โน๏ธ INFO |
| Hook names | Typos in convention method names | โ ๏ธ WARN |
Example:
sm = SMCheck(OrderFlow)
v = sm.validate()
for finding in v.run_all():
print(f"[{finding.level}] {finding.category}")
if finding.detail:
print(f" {finding.detail}")
Common Tasks
Task: Add guards with conditions
class OrderFlow(StateChart):
# ... states ...
def can_proceed(self) -> bool:
"""Payment verified."""
return self._payment_approved
submit = waiting.to(processing, cond="can_proceed")
def __init__(self):
self._payment_approved = False
super().__init__()
smcheck automatically detects the guard and generates setup code in tests.
Task: Add sub-machines (compound states)
class OrderFlow(StateChart):
waiting = State(initial=True)
class processing(StateChart):
checking = State(initial=True)
shipping = State()
done = shipping # shorthand for final
check_inv = checking.to(shipping)
finish_ship = shipping.to(done)
cancelled = State(final=True)
submit = waiting.to(processing)
cancel = waiting.to(cancelled) | processing.to(cancelled)
Task: See the diagram before generating tests
sm = SMCheck(OrderFlow)
diagram_text = sm.to_mermaid()
print(diagram_text)
# โ copy/paste into https://mermaid.live
Understanding the Output
Validation Report Example
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ VALIDATION FINDINGS โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ [PASS] reachability All 8 states reachable โ
โ [PASS] liveness No deadlocks (all non-final states exit) โ
โ [INFO] invoke_states processing [auto-timeout] โ
โ [WARN] hook_names on_exit_old_state: state 'old_state' not โ
โ found (typo?) โ remove or fix โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Generated Tests
generated_tests/
โโโ test_transitions.py # One test per (state, event) โ target
โโโ test_paths.py # One test per enumerated path
Tests are self-contained and can run offline (no real dependencies).
Mermaid Diagram
The exported diagram includes:
- Guard conditions in
[square brackets] - Constraint notes (e.g., "Only if payment verified")
- Compound states grouped together
- Auto-generated from your state machine โ always in sync
Advanced: Custom Guard Setup
If your machine uses dynamic guards that can't be inspected statically:
sm = SMCheck(OrderFlow)
# Tell smcheck how to set up each guarded event
guard_setup = {
"submit": {"_payment_approved": True},
"ship": {"_inventory_reserved": True},
}
tests = sm.generate_tests(guard_setup_map=guard_setup)
sm.write_tests(...)
Detailed Analysis with PathAnalysis
analysis = sm.analyze_paths()
print(f"Top-level paths: {len(analysis.top_level_paths)}")
print(f"Parallel track paths: {analysis.track_paths}")
print(f"Total combinations: {analysis.combined_count}")
# Each path is an SMPath object
for path in analysis.top_level_paths:
for edge in path.edges:
print(f" {edge.source} --{edge.event}--> {edge.target}")
Why smcheck?
For teams developing state machines:
- Catch structural bugs early (deadlocks, unreachable states)
- Auto-generate test boilerplate (no manual path enumeration)
- Share diagrams with non-technical stakeholders
- Refactor with confidence (re-run validation in CI)
For library authors:
- Document state machine behavior with generated tests
- Ensure compatibility with new python-statemachine versions
- Give users example state machines + their tests
For teaching:
- Teach students to think about paths and edge cases
- Let students focus on business logic, not test scaffolding
- Visualize complex state machines
Further Reading
See Feature Catalogue for details on:
- Graph extraction (adjacency maps, path algorithms)
- Detailed validation rules
- Code generation internals
- Mermaid export options
For python-statemachine docs, see python-statemachine.readthedocs.io.
Contributing
Issues and PRs welcome at github.com/brunolnetto/smcheck.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file smcheck-0.0.1.tar.gz.
File metadata
- Download URL: smcheck-0.0.1.tar.gz
- Upload date:
- Size: 296.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ed588717bdcb0f5083624697518299d066852a59256dab09592cb50bb712821
|
|
| MD5 |
b28e1148bce9243b4867c932fa1b8000
|
|
| BLAKE2b-256 |
a40c22fcdb061c2bc146e96d156bcb34956dd8455030ad78942e7202c8e9c9a1
|
File details
Details for the file smcheck-0.0.1-py3-none-any.whl.
File metadata
- Download URL: smcheck-0.0.1-py3-none-any.whl
- Upload date:
- Size: 63.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b77726df53fb78275abf2e41a98c50901ffb1b625dced48127d64185cc278447
|
|
| MD5 |
8ac287821b4b3ead709dbb0e82d84685
|
|
| BLAKE2b-256 |
970d62491f46710a466ef5417744087a567284a33b9b13a0881baacde17a263d
|