Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ There's a lot more to cover, please take a look at our docs:
https://python-statemachine.readthedocs.io.


## Contributing
## Contributing to the project

* <a class="github-button" href="https://github.com/fgmacedo/python-statemachine" data-icon="octicon-star" aria-label="Star fgmacedo/python-statemachine on GitHub">Star this project</a>
* <a class="github-button" href="https://github.com/fgmacedo/python-statemachine/issues" data-icon="octicon-issue-opened" aria-label="Issue fgmacedo/python-statemachine on GitHub">Open an Issue</a>
Expand Down
14 changes: 7 additions & 7 deletions docs/actions.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Actions

Action is the way a StateMachine can cause things to happen in the
Action is the way a {ref}`StateMachine` can cause things to happen in the
outside world, and indeed they are the main reason why they exist at all.

The main point of introducing a state machine is for the
Expand All @@ -26,7 +26,7 @@ when something changes and are not bounded to a specific state or event:

- `after_transition()`

The follow example can get you an overview of the "generic" callbacks available:
The following example can get you an overview of the "generic" callbacks available:

```py
>>> from statemachine import StateMachine, State
Expand Down Expand Up @@ -162,14 +162,14 @@ It's also possible to use an event name as action.

## Transition actions

For each {ref}`event`, you can register `before`, `on` and `after` callbacks.
For each {ref}`event`, you can register `before`, `on`, and `after` callbacks.

### Declare transition actions by naming convention

The action will be registered for every {ref}`transition` associated with the event.

Callbacks by naming convention will be searched on the StateMachine and on the
model, using the patterns:
Callbacks by naming convention will be searched on the StateMachine and the model,
using the patterns:

- `before_<event>()`

Expand Down Expand Up @@ -337,7 +337,7 @@ Actions and Guards will be executed in the following order:
(dynamic-dispatch)=
## Dynamic dispatch

`python-statemachine` implements a custom dispatch mechanism on all those available Actions and
{ref}`statemachine` implements a custom dispatch mechanism on all those available Actions and
Guards. This means that you can declare an arbitrary number of `*args` and `**kwargs`, and the
library will match your method signature of what's expected to receive with the provided arguments.

Expand All @@ -359,7 +359,7 @@ For your convenience, all these parameters are available for you on any Action o
: All keyword arguments provided on the {ref}`Event`.

`event_data`
: A reference to `EventData` instance.
: A reference to {ref}`EventData` instance.

`event`
: The {ref}`Event` that was triggered.
Expand Down
66 changes: 66 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# API

## StateMachine

```{eval-rst}
.. autoclass:: statemachine.statemachine.StateMachine
:members:
:undoc-members:
```

## State

```{seealso}
{ref}`States` reference.
```


```{eval-rst}
.. autoclass:: statemachine.state.State
:members:
```

## Transition

```{seealso}
{ref}`Transitions` reference.
```

```{eval-rst}
.. autoclass:: statemachine.transition.Transition
:members:
```

## TransitionList

```{eval-rst}
.. autoclass:: statemachine.transition_list.TransitionList
:members:
```

## Model

```{seealso}
{ref}`Domain models` reference.
```


```{eval-rst}
.. autoclass:: statemachine.model.Model
:members:
```

## TriggerData


```{eval-rst}
.. autoclass:: statemachine.event_data.TriggerData
:members:
```

## EventData

```{eval-rst}
.. autoclass:: statemachine.event_data.EventData
:members:
```
6 changes: 3 additions & 3 deletions docs/diagram.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Diagrams

You can generate diagrams from your state machine.
You can generate diagrams from your {ref}`StateMachine`.

```{note}
This functionality depends on [pydot](https://github.com/pydot/pydot), it means that you need to
have pydot installed on your system. pydot is a Python library that allows you to create and
have `pydot` installed on your system. pydot is a Python library that allows you to create and
manipulate graphs in [Graphviz](https://graphviz.org/)'s
[dot language](https://graphviz.org/doc/info/lang.html).

Expand Down Expand Up @@ -59,7 +59,7 @@ As this one:
![OrderControl](images/order_control_machine_initial.png)


The current state is also highlighted:
The current {ref}`state` is also highlighted:

``` py

Expand Down
16 changes: 8 additions & 8 deletions docs/guards.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
(validators-and-guards)=
# Validators and guards

Validations and Guards are checked before an transition is started. They are meant to stop a
Validations and Guards are checked before a transition is started. They are meant to stop a
transition to occur.

The main difference, is that {ref}`validators` raise exceptions to stop the flow, and {ref}`guards`
The main difference is that {ref}`validators` raise exceptions to stop the flow, and {ref}`guards`
act like predicates that shall resolve to a ``boolean`` value.

```{seealso}
Expand All @@ -16,16 +16,16 @@ for all the available callbacks, being validators and guards or {ref}`actions`.

Also known as **Conditional transition**.

A guard is a condition that may be checked when a statemachine wants to handle
an {ref}`event`. A guard is declared on the {ref}`transition`, and when that transition
A guard is a condition that may be checked when a {ref}`statemachine` wants to handle
an {ref}`event`. A guard is declared on the {ref}`transition`, and when that {ref}`transition`
would trigger, then the guard (if any) is checked. If the guard is `True`
then the transition does happen. If the guard is `False`, the transition
is ignored.

When transitions have guards, then it's possible to define two or more
transitions for the same event from the same {ref}`state`. When the event happens, then
When {ref}`transitions` have guards, then it's possible to define two or more
transitions for the same {ref}`event` from the same {ref}`state`. When the {ref}`event` happens, then
the guarded transitions are checked, one by one, and the first transition
whose guard is true will be used, the others will be ignored.
whose guard is true will be used, and the others will be ignored.

A guard is generally a boolean function or boolean variable and must not have any side effects.
Side effects are reserved for {ref}`actions`.
Expand Down Expand Up @@ -66,7 +66,7 @@ So, a condition `s1.to(s2, cond=lambda: [])` will evaluate as `False`, as an emp


Are like {ref}`guards`, but instead of evaluating to boolean, they are expected to raise an
exception to stop the flow. It may be useful for imperative style programming when you don't
exception to stop the flow. It may be useful for imperative-style programming when you don't
want to continue evaluating other possible transitions and exit immediately.

* Single validator: `validators="validator"`
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mixins
integrations
diagram
processing_model
api
auto_examples/index
contributing
authors
Expand Down
8 changes: 5 additions & 3 deletions docs/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@

## Django integration

When used in a Django App, this library implements an auto-discovery hook similar to how Django's built-in **admin** [autodiscover](https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.autodiscover).
When used in a Django App, this library implements an auto-discovery hook similar to how Django's
built-in **admin** [autodiscover](https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.autodiscover).

> This library attempts to import an **statemachine** or **statemachines** module in each installed
> application. Such modules are expected to register `StateMachine` classes to be used with
> the {ref}`MachineMixin`.


```{hint}
When using `python-statemachine` to control the state of a Django model, we advise keeping the ``StateMachine`` definitions on their modules.
When using `python-statemachine` to control the state of a Django model, we advise keeping the
{ref}`StateMachine` definitions on their own modules.

So as circular references may occur, and as a way to help you organize your
code, if you put state machines on modules named as mentioned above inside installed
Django Apps, these `StateMachine` classes will be automatically
Django Apps, these {ref}`StateMachine` classes will be automatically
imported and registered.

This is only an advice, nothing stops you do declare your state machine alongside your models.
Expand Down
2 changes: 1 addition & 1 deletion docs/mixins.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# Mixins

Your model can be inherited from a custom mixin to auto-instantiate a state machine.
Your {ref}`domain models` can be inherited from a custom mixin to auto-instantiate a {ref}`statemachine`.

## MachineMixin

Expand Down
13 changes: 6 additions & 7 deletions docs/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@ If you don't pass an explicit model instance, this simple `Model` will be used:
:linenos:
```

```{eval-rst}
.. autoclass:: statemachine.model.Model
:members:
```

```{seealso}
See the {ref}`sphx_glr_auto_examples_order_control_rich_model_machine.py` as example of using a domain object to hold attributes and methods to be used on the `StateMachine` definition.
See the {ref}`sphx_glr_auto_examples_order_control_rich_model_machine.py` as example of using a
domain object to hold attributes and methods to be used on the `StateMachine` definition.
```

```{hint}
Domain models are registered as {ref}`observers`, so you can have the same level of functionalities provided to the built-in `StateMachine`, such as implementing all callbacks and guards on your domain model and keeping only the definition of states and transitions on
the `StateMachine`.
Domain models are registered as {ref}`observers`, so you can have the same level of functionalities
provided to the built-in {ref}`StateMachine`, such as implementing all {ref}`actions` and
{ref}`guards` on your domain model and keeping only the definition of {ref}`states` and
{ref}`transitions` on the {ref}`StateMachine`.
```
2 changes: 1 addition & 1 deletion docs/releases/1.0.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This is the last release to support Python 2.7, 3.5, and 3.6.
## What's new in 1.0


### Validators and Guards
### Added validators and Guards

Transitions now support `cond` and `unless` parameters, to restrict
the execution.
Expand Down
2 changes: 1 addition & 1 deletion docs/releases/1.0.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ references of callbacks when there were multiple concurrent instances of the sam
class.


## Bugfixes
## Bugfixes in 1.0.3

- [#334](https://github.com/fgmacedo/python-statemachine/issues/334): Fixed a shared reference
of callbacks when there were multiple concurrent instances of the same `StateMachine` class.
49 changes: 39 additions & 10 deletions docs/releases/2.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,6 @@ Even if you trigger an event inside an action.
See {ref}`processing model` for more details.
```

### Added support for translations (i18n)

Now the library messages can be translated into any language.

See {ref}`Add a translation` on how to contribute with translations.

### State names are now optional

{ref}`State` names are now by default derived from the class variable that they are assigned to.
Expand All @@ -47,7 +41,7 @@ when it is different than the one derived from its id.
```py
>>> from statemachine import StateMachine, State

>>> class SM(StateMachine):
>>> class ApprovalMachine(StateMachine):
... pending = State(initial=True)
... waiting_approval = State()
... approved = State(final=True)
Expand All @@ -56,13 +50,13 @@ when it is different than the one derived from its id.
... approve = waiting_approval.to(approved)
...

>>> SM.pending.name
>>> ApprovalMachine.pending.name
'Pending'

>>> SM.waiting_approval.name
>>> ApprovalMachine.waiting_approval.name
'Waiting approval'

>>> SM.approved.name
>>> ApprovalMachine.approved.name
'Approved'

```
Expand All @@ -86,6 +80,41 @@ are ever executed as a result of an internal transition.
See {ref}`internal transition` for more details.
```

### Added option to ignore unknown events

You can now instantiate a {ref}`StateMachine` with `allow_event_without_transition=True`,
so the state machine will allow triggering events that may not lead to a state {ref}`transition`,
including tolerance to unknown {ref}`event` triggers.

The default value is ``False``, that keeps the backward compatible behavior of when an
event does not result in a {ref}`transition`, an exception ``TransitionNotAllowed`` will be raised.

```py
>>> sm = ApprovalMachine(allow_event_without_transition=True)

>>> sm.send("unknow_event_name")

>>> sm.pending.is_active
True

>>> sm.send("approve")

>>> sm.pending.is_active
True

>>> sm.send("start")

>>> sm.waiting_approval.is_active
True

```

### Added support for translations (i18n)

Now the library messages can be translated into any language.

See {ref}`Add a translation` on how to contribute with translations.


## Minor features in 2.0

Expand Down
15 changes: 4 additions & 11 deletions docs/states.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@

# States

State, as the name says, holds the representation of a state in a statemachine.
{ref}`State`, as the name says, holds the representation of a state in a {ref}`StateMachine`.


## State
## Initial state

```{eval-rst}
.. autoclass:: statemachine.state.State
:members:
```

### Initial state

A StateMachine should have one and only one `initial` state.
A {ref}`StateMachine` should have one and only one `initial` {ref}`state`.


The initial {ref}`state` is entered when the machine starts and the corresponding entering
state {ref}`actions` are called if defined.


(final-state)=
### Final state
## Final state


You can explicitly set final states.
Expand Down
Loading