Skip to main content

Damn simple finite state machine

Project description

dsm

Damn simple finite state machine

Build Status

About

DSM is a observable simple finite state machine implementation for Python. Transitions may be programmed declaratively or imperatively. Inputs and state changes are emitting observable events.

Requirements

  • Python 2.7, 3.5, 3.6
  • observable
  • six for compatibility between Python 2 and Python 3

Installation

pip install dsm

Usage

Django integration

It is possible to integrate dsm with Django models by declaring a StateMachineField.

from django.db import models
from dsm.fields import StateMachineField


class Order(models.Model):
    status = StateMachineField(
        transitions=(
            ('new', ['confirmed'], 'processing'),
            ('processing', ['cancel'], 'cancelled'),
            ('processing', ['send'], 'sending'),
            ('sending', ['deliver'], 'finished'),
        ),
        max_length=16,
        choices=(
            ('new', _('New')),
            ('processing', _('Processing')),
            ('sending', _('Sending')),
            ('finished', _('Finished')),
            ('canceled', _('Cancelled')),
        ),
        db_index=True,
        default='new'
    )

Now you can create an Order and check it's status:

>>> order = Order.objects.create()
>>> order.status
new
>>> type(order.status)
dsm.fields.MachineState

The string representation of status field is same as state name provided in transitions declaration, but internally there is always dsm.fields.MachineState instance.

Declarative

FSM declaration:

import string
import dsm

class SumatorMachine(dsm.StateMachine):
    class Meta:
        initial = 'init'
        transitions = (
            ('init', list(string.digits), 'digit_enter'),
            ('digit_enter', list(string.digits), 'digit_enter'),
            ('digit_enter', '=', 'summarize'),
        )

Usage:

Initialization:

fsm = SumatorMachine()

Processing one value:

fsm.process(value)

Processing multiple values:

fsm.process_many(iterable)

Gathering the current state:

>>> fsm.state
'summarize'

Resetting to the intial state:

fsm.reset()

Listening on events:

fsm.when('state', func)

Events example:

>>> the_sum = 0

>>> def add_digit(x): global the_sum; the_sum += int(x)
>>> def reset(x): global the_sum; the_sum = 0

>>> fsm = SumatorMachine()
>>> fsm.when('digit_enter', add_digit)
>>> fsm.when('init', reset)

>>> fsm.process_many('666=')
'summarize'

>>> the_sum
18

Events example (class based):

>>> class Sumator(object):
...     def __init__(self):
...         self.total = 0
...         self.fsm = SumatorMachine()
...         self.fsm.when('digit_enter', self.add)
...         self.fsm.when('init', self.reset)
...
...     def add(self, x):
...         self.total += int(x)
...
...     def reset(self, x):
...         self.total = 0
...
...     def summarize(self, values):
...         self.fsm.reset()
...         self.fsm.process_many(values+'=')
...         return self.total

>>> s = Sumator()
>>> s.summarize('666')
18

Imperative

import string
import dsm

fsm = dsm.StateMachine(
        initial='init',
        transitions=dsm.Transitions((
                ('init', list(string.digits), 'digit_enter'),
                ('digit_enter', list(string.digits), 'digit_enter'),
                ('digit_enter', '=', 'summarize'),
            ))
        )

License

BSD

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dsm-0.5.2.tar.gz (5.4 kB view hashes)

Uploaded Source

Built Distribution

dsm-0.5.2-py3-none-any.whl (8.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page