diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ecbebb33..f6f9f6eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,6 +31,17 @@ repos: types: [python] language: system pass_filenames: false + - id: generate-images + name: Generate README images + entry: >- + uv run python -m statemachine.contrib.diagram + tests.examples.traffic_light_machine.TrafficLightMachine + docs/images/readme_trafficlightmachine.png + language: system + pass_filenames: false + files: >- + (statemachine/contrib/diagram/ + |tests/examples/traffic_light_machine\.py) - id: pytest name: Pytest entry: uv run pytest -n auto --cov-fail-under=100 diff --git a/README.md b/README.md index 28e0c673..f3af4ecb 100644 --- a/README.md +++ b/README.md @@ -79,12 +79,8 @@ True Generate a diagram: -```py ->>> # This example will only run on automated tests if dot is present ->>> getfixture("requires_dot_installed") ->>> img_path = "docs/images/readme_trafficlightmachine.png" ->>> sm._graph().write_png(img_path) - +```python +sm._graph().write_png("traffic_light.png") ``` ![](https://raw.githubusercontent.com/fgmacedo/python-statemachine/develop/docs/images/readme_trafficlightmachine.png) diff --git a/docs/diagram.md b/docs/diagram.md index 5707d794..d607e339 100644 --- a/docs/diagram.md +++ b/docs/diagram.md @@ -33,14 +33,11 @@ For other systems, see the [Graphviz downloads page](https://graphviz.org/downlo Every state machine instance exposes a `_graph()` method that returns a [pydot.Dot](https://github.com/pydot/pydot) graph object: -```py ->>> from tests.examples.order_control_machine import OrderControl - ->>> sm = OrderControl() - ->>> sm._graph() # doctest: +ELLIPSIS ->> # This example will only run on automated tests if dot is present ->>> getfixture("requires_dot_installed") - ->>> from tests.examples.order_control_machine import OrderControl - ->>> sm = OrderControl() - ->>> sm.receive_payment(10) -[10] - ->>> sm._graph().write_png("docs/images/order_control_machine_processing.png") +```python +from tests.examples.traffic_light_machine import TrafficLightMachine +sm = TrafficLightMachine() +sm.send("cycle") +sm._graph().write_png("traffic_light_yellow.png") ``` -![OrderControl after receiving payment](images/order_control_machine_processing.png) +```{statemachine-diagram} tests.examples.traffic_light_machine.TrafficLightMachine +:events: cycle +:caption: TrafficLightMachine after one cycle +``` ### Exporting to a file @@ -71,24 +64,21 @@ Send events to advance the machine and see the active state change: The `pydot.Dot` object supports writing to many formats — use `write_png()`, `write_svg()`, `write_pdf()`, etc.: -```py ->>> from tests.examples.order_control_machine import OrderControl - ->>> sm = OrderControl() - ->>> sm._graph().write_png("docs/images/order_control_machine_initial.png") - +```python +sm = OrderControl() +sm._graph().write_png("order_control.png") ``` -![OrderControl](images/order_control_machine_initial.png) +```{statemachine-diagram} tests.examples.order_control_machine.OrderControl +:caption: OrderControl +``` For higher resolution PNGs, set the DPI before exporting: -```py ->>> sm._graph().set_dpi(300) - ->>> sm._graph().write_png("docs/images/order_control_machine_initial_300dpi.png") - +```python +graph = sm._graph() +graph.set_dpi(300) +graph.write_png("order_control_300dpi.png") ``` ```{note} @@ -258,11 +248,9 @@ The `DotGraphMachine` class gives you control over the diagram's visual properties. Subclass it and override the class attributes to customize fonts, colors, and layout: -```py ->>> from statemachine.contrib.diagram import DotGraphMachine - ->>> from tests.examples.order_control_machine import OrderControl - +```python +from statemachine.contrib.diagram import DotGraphMachine +from tests.examples.order_control_machine import OrderControl ``` Available attributes: @@ -279,34 +267,25 @@ Available attributes: For example, to generate a top-to-bottom diagram with a custom active state color: -```py ->>> class CustomDiagram(DotGraphMachine): -... graph_rankdir = "TB" -... state_active_fillcolor = "lightyellow" - ->>> sm = OrderControl() - ->>> sm.receive_payment(10) -[10] - ->>> graph = CustomDiagram(sm) - ->>> dot = graph() +```python +class CustomDiagram(DotGraphMachine): + graph_rankdir = "TB" + state_active_fillcolor = "lightyellow" ->>> dot.to_string() # doctest: +ELLIPSIS -'digraph OrderControl {... +sm = OrderControl() +sm.receive_payment(10) +graph = CustomDiagram(sm) +dot = graph() +dot.write_svg("order_control_custom.svg") ``` `DotGraphMachine` also works with **classes** (not just instances) to generate diagrams without an active state: -```py ->>> dot = DotGraphMachine(OrderControl)() - ->>> dot.to_string() # doctest: +ELLIPSIS -'digraph OrderControl {... - +```python +dot = DotGraphMachine(OrderControl)() +dot.write_png("order_control_class.png") ``` diff --git a/docs/images/order_control_machine_initial.png b/docs/images/order_control_machine_initial.png deleted file mode 100644 index 9ba36061..00000000 Binary files a/docs/images/order_control_machine_initial.png and /dev/null differ diff --git a/docs/images/order_control_machine_initial_300dpi.png b/docs/images/order_control_machine_initial_300dpi.png deleted file mode 100644 index 9ba36061..00000000 Binary files a/docs/images/order_control_machine_initial_300dpi.png and /dev/null differ diff --git a/docs/images/order_control_machine_processing.png b/docs/images/order_control_machine_processing.png deleted file mode 100644 index 5a66d93e..00000000 Binary files a/docs/images/order_control_machine_processing.png and /dev/null differ diff --git a/docs/images/readme_orderworkflow.png b/docs/images/readme_orderworkflow.png deleted file mode 100644 index 47f3c631..00000000 Binary files a/docs/images/readme_orderworkflow.png and /dev/null differ diff --git a/docs/images/readme_trafficlightmachine.png b/docs/images/readme_trafficlightmachine.png index add082de..6519080d 100644 Binary files a/docs/images/readme_trafficlightmachine.png and b/docs/images/readme_trafficlightmachine.png differ diff --git a/docs/releases/1.0.1.md b/docs/releases/1.0.1.md index cccd852f..d32b6fcb 100644 --- a/docs/releases/1.0.1.md +++ b/docs/releases/1.0.1.md @@ -47,7 +47,9 @@ You can generate diagrams from your state machine. Example: -![OrderControl](../images/order_control_machine_initial.png) +```{statemachine-diagram} tests.examples.order_control_machine.OrderControl +:caption: OrderControl +``` ```{seealso} diff --git a/tests/test_contrib_diagram.py b/tests/test_contrib_diagram.py index b4d7f373..159d4a50 100644 --- a/tests/test_contrib_diagram.py +++ b/tests/test_contrib_diagram.py @@ -1091,3 +1091,25 @@ def test_render_without_caption_uses_div(self, tmp_path): html = result[0].astext() assert "