Skip to content

Commit 1e4ba19

Browse files
committed
docs: revise diagram.md for new features and narrative coherence
- Reorganize into unified "Text representations" section with format table (name, aliases, description, dependencies) - Add formatter API section with render(), supported_formats(), and custom format registration example - Add live Mermaid directive example in Sphinx section - Add --format dot to CLI examples - Replace MermaidGraphMachine usage with formatter - Add autodoc integration example with SimpleSC - Add auto-expanding docstrings section with format recommendations - Update release notes
1 parent bb3f554 commit 1e4ba19

1 file changed

Lines changed: 131 additions & 78 deletions

File tree

docs/diagram.md

Lines changed: 131 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ sudo apt install graphviz
2727

2828
For other systems, see the [Graphviz downloads page](https://graphviz.org/download/).
2929

30-
3130
## Generating diagrams
3231

3332
Every state machine instance exposes a `_graph()` method that returns a
@@ -77,8 +76,7 @@ For higher resolution PNGs, set the DPI before exporting:
7776

7877
```python
7978
graph = sm._graph()
80-
graph.set_dpi(300)
81-
graph.write_png("order_control_300dpi.png")
79+
graph.set_dpi(300).write_png("order_control_300dpi.png")
8280
```
8381

8482
```{note}
@@ -89,52 +87,24 @@ complete list.
8987
```
9088

9189

92-
## Command line
93-
94-
You can generate diagrams without writing Python code:
95-
96-
```bash
97-
python -m statemachine.contrib.diagram <classpath> <output_file>
98-
```
99-
100-
The output format is inferred from the file extension:
101-
102-
```bash
103-
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine diagram.png
104-
```
90+
## Text representations
10591

106-
To highlight the current state, use `--events` to instantiate the machine and
107-
send events before rendering:
92+
State machines support multiple text-based output formats, all accessible
93+
through Python's built-in `format()` protocol, the `formatter` API, or
94+
the command line.
10895

109-
```bash
110-
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine diagram.png --events cycle cycle cycle
111-
```
96+
| Format | Aliases | Description | Dependencies |
97+
|--------|---------|-------------|--------------|
98+
| `mermaid` | | [Mermaid stateDiagram-v2](https://mermaid.js.org/syntax/stateDiagram.html) source | None |
99+
| `md` | `markdown` | Transition table (pipe-delimited Markdown) | None |
100+
| `rst` | | Transition table (RST grid table) | None |
101+
| `dot` | | [Graphviz DOT](https://graphviz.org/doc/info/lang.html) language source | pydot |
102+
| `svg` | | SVG markup (generated via DOT) | pydot, Graphviz |
112103

113-
Use `--format` to produce **Mermaid source** or a **transition table** instead
114-
of a Graphviz image:
115-
116-
```bash
117-
# Mermaid stateDiagram-v2
118-
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine output.mmd --format mermaid
119-
120-
# Markdown transition table
121-
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine output.md --format md
122-
123-
# RST transition table
124-
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine output.rst --format rst
125-
```
126-
127-
Use `-` as the output file to write to stdout (handy for piping):
128-
129-
```bash
130-
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine - --format mermaid
131-
```
132104

105+
### Using `format()`
133106

134-
## Text representations with `format()`
135-
136-
State machines support Python's built-in `format()` protocol for quick text
137-
output — no diagram imports needed:
107+
Use f-strings or the built-in `format()` function — no diagram imports needed:
138108

139109
```py
140110
>>> from tests.examples.traffic_light_machine import TrafficLightMachine
@@ -181,11 +151,7 @@ stateDiagram-v2
181151

182152
```
183153

184-
Supported format specs: `dot`, `svg`, `mermaid`, `md` (or `markdown`), `rst`.
185-
An empty spec falls back to `repr()`.
186-
187-
The `dot` format returns the Graphviz DOT language source (same output as
188-
`sm._graph().to_string()`):
154+
The `dot` format returns the Graphviz DOT language source:
189155

190156
```py
191157
>>> print(f"{sm:dot}") # doctest: +ELLIPSIS
@@ -195,6 +161,101 @@ digraph TrafficLightMachine {
195161

196162
```
197163

164+
An empty format spec (e.g., `f"{sm:}"`) falls back to `repr()`.
165+
166+
167+
### Using the `formatter` API
168+
169+
The `formatter` object is the programmatic entry point for rendering
170+
state machines in any registered text format:
171+
172+
```py
173+
>>> from statemachine.contrib.diagram import formatter
174+
>>> from tests.examples.traffic_light_machine import TrafficLightMachine
175+
176+
>>> print(formatter.render(TrafficLightMachine, "mermaid"))
177+
stateDiagram-v2
178+
direction LR
179+
state "Green" as green
180+
state "Yellow" as yellow
181+
state "Red" as red
182+
[*] --> green
183+
green --> yellow : cycle
184+
yellow --> red : cycle
185+
red --> green : cycle
186+
<BLANKLINE>
187+
188+
>>> formatter.supported_formats()
189+
['dot', 'markdown', 'md', 'mermaid', 'rst', 'svg']
190+
191+
```
192+
193+
Both `format()` and the Sphinx directive delegate to this same `formatter`
194+
under the hood.
195+
196+
197+
#### Registering custom formats
198+
199+
The `formatter` is extensible — register your own format with a
200+
decorator and it becomes available everywhere (`format()`, CLI,
201+
Sphinx directive):
202+
203+
```python
204+
from statemachine.contrib.diagram import formatter
205+
206+
@formatter.register_format("plantuml", "puml")
207+
def _render_plantuml(machine_or_class):
208+
# your PlantUML renderer here
209+
...
210+
```
211+
212+
After registration, `f"{sm:plantuml}"` and `--format plantuml` work
213+
immediately.
214+
215+
216+
### Command line
217+
218+
You can generate diagrams without writing Python code:
219+
220+
```bash
221+
python -m statemachine.contrib.diagram <classpath> <output_file>
222+
```
223+
224+
The output format is inferred from the file extension:
225+
226+
```bash
227+
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine diagram.png
228+
```
229+
230+
To highlight the current state, use `--events` to instantiate the machine and
231+
send events before rendering:
232+
233+
```bash
234+
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine diagram.png --events cycle cycle cycle
235+
```
236+
237+
Use `--format` to produce a text format instead of a Graphviz image:
238+
239+
```bash
240+
# Mermaid stateDiagram-v2
241+
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine output.mmd --format mermaid
242+
243+
# DOT source
244+
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine output.dot --format dot
245+
246+
# Markdown transition table
247+
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine output.md --format md
248+
249+
# RST transition table
250+
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine output.rst --format rst
251+
```
252+
253+
Use `-` as the output file to write to stdout (handy for piping):
254+
255+
```bash
256+
python -m statemachine.contrib.diagram tests.examples.traffic_light_machine.TrafficLightMachine - --format mermaid
257+
```
258+
198259

199260
## Auto-expanding docstrings
200261

@@ -261,33 +322,6 @@ And here is the rendered autodoc output:
261322
```
262323

263324

264-
## Mermaid output
265-
266-
The `MermaidGraphMachine` facade generates
267-
[Mermaid `stateDiagram-v2`](https://mermaid.js.org/syntax/stateDiagram.html)
268-
source text from any state machine — no external dependencies required:
269-
270-
```py
271-
>>> from statemachine.contrib.diagram import MermaidGraphMachine
272-
>>> from tests.examples.traffic_light_machine import TrafficLightMachine
273-
>>> print(MermaidGraphMachine(TrafficLightMachine).get_mermaid())
274-
stateDiagram-v2
275-
direction LR
276-
state "Green" as green
277-
state "Yellow" as yellow
278-
state "Red" as red
279-
[*] --> green
280-
green --> yellow : cycle
281-
yellow --> red : cycle
282-
red --> green : cycle
283-
<BLANKLINE>
284-
285-
```
286-
287-
Compound states, parallel regions, history pseudo-states, guards, and
288-
active-state highlighting are all supported.
289-
290-
291325
## Sphinx directive
292326

293327
If you use [Sphinx](https://www.sphinx-doc.org/) to build your documentation, the
@@ -356,6 +390,26 @@ zoom and pan freely:
356390
:align: center
357391
```
358392

393+
### Mermaid format
394+
395+
Use `:format: mermaid` to render via
396+
[sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid)
397+
instead of Graphviz SVG — useful when you don't want to install Graphviz
398+
in your docs build environment:
399+
400+
````markdown
401+
```{statemachine-diagram} myproject.machines.TrafficLight
402+
:format: mermaid
403+
:caption: Rendered as Mermaid
404+
```
405+
````
406+
407+
```{statemachine-diagram} tests.examples.traffic_light_machine.TrafficLightMachine
408+
:format: mermaid
409+
:caption: TrafficLightMachine (Mermaid)
410+
:align: center
411+
```
412+
359413
### Directive options
360414

361415
The directive supports the same layout options as the standard `image` and
@@ -368,8 +422,7 @@ The directive supports the same layout options as the standard `image` and
368422
each event is sent before rendering.
369423

370424
`:format:` *(string)*
371-
: Output format. Use `mermaid` to render via
372-
[sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid)
425+
: Output format. Use `mermaid` to render via sphinxcontrib-mermaid
373426
instead of Graphviz SVG. Default: DOT/SVG.
374427

375428
**Image/figure options:**

0 commit comments

Comments
 (0)