Metadata-Version: 2.4
Name: state-mate
Version: 0.1.0
Summary: Generate python-statemachine classes from Sismic YAML statecharts
Project-URL: Documentation, https://terradue.github.io/state-mate/
Project-URL: Issues, https://github.com/Terradue/state-mate/issues
Project-URL: Source, https://github.com/Terradue/state-mate
Author-email: Simone Tripodi <simone.tripodi@terradue.com>, Fabrice Brito <fabrice.brito@terradue.com>
License: Apache-2.0
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Python: >=3.11
Requires-Dist: click>=8.1
Requires-Dist: jinja2>=3.1
Requires-Dist: sismic>=1.6.11
Description-Content-Type: text/markdown

# state-mate

[![PyPI - Version](https://img.shields.io/pypi/v/state-mate.svg)](https://pypi.org/project/state-mate)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/state-mate.svg)](https://pypi.org/project/state-mate)

Generate a `python-statemachine` implementation directly from a constrained **Sismic YAML** statechart using Jinja2.

Sismic is the authoritative parser and in-memory model. The generator deliberately does **not** redefine states, transitions, or the state machine in its own domain model.

## Input

```yaml
statechart:
  name: Order
  root state:
    name: lifecycle
    initial: orderable
    states:
      - name: orderable
        transitions:
          - event: order
            target: ordered

      - name: ordered
        transitions:
          - event: process
            target: pending

      - name: pending
        transitions:
          - event: ship
            target: shipping
          - event: cancel
            target: canceled
          - event: fail
            target: failed

      - name: shipping
        transitions:
          - event: succeed
            target: succeeded
          - event: cancel
            target: canceled
          - event: fail
            target: failed

      - name: succeeded
        type: final

      - name: canceled
        type: final

      - name: failed
        transitions:
          - event: retry
            target: ordered
```

`load_statechart()` calls `sismic.io.import_from_yaml(filepath=...)`. Sismic therefore performs its normal YAML-schema and statechart validation first.

## Architecture

```text
Sismic YAML
    |
    v
sismic.io.import_from_yaml()
    |
    v
sismic.model.Statechart
    |
    +--> validate_supported_subset()
    |
    v
Jinja2 + small rendering helpers
    |
    v
python-statemachine source
```

There is no secondary `Machine`, `State`, or `Transition` model. Sismic objects are passed directly to the renderer and template.

The only derived rendering structure is a grouping of Sismic `Transition` objects by event. This is needed to generate combined `python-statemachine` event declarations such as:

```python
cancel = (
    states.PENDING.to(states.CANCELED)
    | states.SHIPPING.to(states.CANCELED)
)
```

## Supported subset

The generator intentionally targets a flat finite-state-machine subset:

- one compound root state;
- basic and final states directly below the root;
- one initial child state;
- external transitions with one event and one target;
- repeated event names across source states.

The following Sismic features are rejected explicitly because the current `python-statemachine` output cannot preserve their semantics faithfully:

- nested compound states;
- parallel states;
- history states;
- eventless transitions;
- internal transitions;
- guards;
- transition actions;
- priorities;
- state entry/exit actions;
- state and transition contracts.

## Source layout

```text
src/state_mate/
├── __init__.py
├── cli.py
├── loader.py
├── render.py
└── templates/
    └── machine.py.j2
```

`loader.py` is intentionally limited to loading and subset validation. `render.py` contains only Python naming helpers, event grouping, and Jinja2 setup.

## Install and run

```bash
uv sync --extra test
```

Generate a Python state machine:

```bash
uv run state-mate examples/order.yaml \
  --output build/order_machine.py
```

Without `--output`, generated source is written to stdout:

```bash
uv run state-mate examples/order.yaml
```

Run the tests:

```bash
uv run pytest
```

## PlantUML

PlantUML output is intentionally outside this project because Sismic already provides it directly:

```bash
uv run sismic-plantuml examples/order.yaml
```

or programmatically with `sismic.io.export_to_plantuml()`.

## Documentation

The project documentation is organized according to [Diátaxis](https://diataxis.fr/) and built with MkDocs using the built-in Read the Docs theme.

## License

[![Apache License, Version 2.0](https://img.shields.io/badge/license-Apache%20License%202.0-blue)](https://www.apache.org/licenses/LICENSE-2.0)
