Metadata-Version: 2.0
Name: states
Version: 0.1.6
Summary: state machine for python classes
Home-page: UNKNOWN
Author: Lars van Gemerden
Author-email: gemerden@gmail.com
License: MIT License
Keywords: access data structure getter setter deleter iterator utility tool
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 2.7

.. figure:: https://travis-ci.org/gemerden/statessvg?branch=master
   :alt: Travis

   Travis

statemachine
============

Easy to use state machine to manage the state of python objects.

Introduction
------------

This state machine implementation is developed with the following goals
in mind:

-  Easy to use API, for configuration of the state machine and
   triggering state transitions,
-  Usable for any (almost, I'm sure) python class with a finite number
   of states,
-  Fully featured, including nested states, conditional transitions,
   shorthand notations, many ways to configure callbacks,
-  Simple state machines do not require advanced knowledge; complexity
   of configuration scales with complexity of requirements,
-  One state machine instance can manage the state of many stateful
   objects; the objects only store their current state string,
-  Reasonably fast.

Code Example
------------

Here is a simple statemachine to give some idea of what the
configuration looks like.

.. code:: python

    class LightSwitch(StatefulObject):

        machine = state_machine(
            states=[
                {"name": "on"},
                {"name": "off"},
            ],
            transitions=[
                {"old_state": "off", "new_state": "on", "triggers": ["flick"]},  
                {"old_state": "on", "new_state": "off", "triggers": ["flick"]},
            ],
        )


    lightswitch = LightSwitch(initial="off") 
    lightswitch.flick()                  

Limitations
-----------

The state machine module has been tested with python 2.7, if requested I
will definitely consider python 3 support, depending on time
constraints.

Documentation
-------------

To learn more check the extensive
`tutorial <https://github.com/gemerden/statemachine/blob/master/statemachine/docs/tutorial.md>`__.

Concepts
--------

The following basic state machine concepts are used

-  *state*: state of an stateful object; objects can be in one state at
   the time,
-  *transition*: transition of the object from one state to another
   resulting,
-  *state machine*: system that manages the states of objects according
   to predefined states and transitions,
-  *trigger*: method called on an object that can result in a state
   transition,
-  *callbacks*: functions called on state transitions by the state
   machine,
-  *condition*: conditions for a specific state transition to take
   place.

Features
--------

The module has the following basic and some more advanced features:

-  trigger state transitions by setting trigger name in machine
   configuration:

   -  same trigger can be set for different transitions,
   -  trigger method can pass arguments to callbacks like ``on_exit``
      and ``on_entry``,

-  conditions (also callbacks) can be set on states and transitions:

   -  if a transition is triggered, but the condition is not met, the
      transition does not take place

-  switched transitions can be used to go from one state to another
   depending on conditions

   -  trigger can be used for conditional (switched) transition,
   -  to do this, create multiple trasnitions from the same state to
      different states and give them different conditions

-  state transitions can be started by explicitly setting the state
   (obj.state = "some\_state"):

   -  if a condition is set and not met on the transition an exception
      is raised, because the callbacks would not be called,
   -  if the callbacks function require extra arguments (apart from the
      state managed object), this method will fail

-  a number of callbacks can be installed for each state and transition,
   with obj the state managed object and **args, **\ \*kwargs the
   arguments passed via the trigger to the callback, in calling order:

   -  StateMachine.prepare(self, obj. **args, **\ \*kwargs),
   -  StateMachine.before\_any\_exit(self, obj. **args, **\ \*kwargs),
   -  State.on\_exit(self, obj. **args, **\ \*kwargs),
   -  Transition.on\_transfer(self, obj. **args, **\ \*kwargs), # after
      this the state is changed on the object
   -  State.on\_entry(self, obj. **args, **\ \*kwargs),
   -  StateMachine.after\_any\_entry(self, obj. **args, **\ \*kwargs)
   -  note that if a condition is present and not met, none of these
      functions are called, apart from prepare

-  callbacks can be methods on the class of which the state is managed
   by the machine:

   -  This is the case when the calback is configured as a string (e.g.
      "on\_entry": "do\_callback"),

-  wildcards and listed states can be used to define multiple
   transitions at once:

   -  e.g. transition {"old\_state": "\*", "new\_state": ["A", "B"]}
      would create transitions from all states to both state A and B

-  nested states can be used to better organize states and transitions,
   states can be nested to any depth,
-  context managers can be used to create a context for all callbacks,
-  custom exceptions:

   -  MachineError: raised in case of a misconfiguration of the state
      machine,
   -  TransitionError: raised in case of e.g. an attempt to trigger a
      non-existing transition,

Rules (for the mathematically minded)
-------------------------------------

The state machine in the module has the following rules for setting up
states and transitions:

-  notation:

   -  A, B, C : states of a state managed object (called 'object' from
      now)
   -  A(B, C) : state A with nested states B, C, with \* indicating that
      B is the default initial state
   -  A.B : sub-state B of A; A.B is called a state path
   -   : transition between state A and state B
   -  : transition from A to B or C, depending on condition functions
      (there is no 'and')
   -  : shorthand for transitions and
   -  : shorthand for all transitions from A to states in the same
      machine

-  an object cannot just be in state A if A has substates; given state
   A(B, C), the object can be in A.B or A.C, not in A
-  allowed transitions, given states A, B, C(E, F) and D(G, H):

   -  : basic transition, configured as {"old\_state": "A",
      "new\_state": "B"}
   -  : transition from a state to itself
   -  <C.E, A>: transition from a specific sub-state of C to A
   -  : transition from any sub-state of C to specific state D.G
   -  : transition from A to C.E, E being the initial state of C because
      it was explicitly set or because it is the first state in E
   -  <C.F, D.H>: transitioning from one sub-state in a state to another
      sub-state in another state. Note that this would call (if present)
      on\_exit on F and C and on\_entry on D and H in that order.

-  non-allowed transitions:

   -  <C.E, C.F>: inner transitions cannot be defined on the top level;
      define in state C

-  adding switched transitions, given transition :

   -  B and C must have conditions attached in the transition, these
      condition will be run though in order
   -  D does not need to have a condition attached meaning it will
      always be the next state if the conditions on the transition to B
      and C fail

Authors
-------

Lars van Gemerden (rational-it) - initial code and documentation.

License
-------

This project is licensed under the license in LICENSE.txt.


