Metadata-Version: 2.1
Name: Fineas
Version: 0.1.0
Summary: Annotation-driven, Thread-safe, transition-focused Finite State Machines.
Home-page: https://github.com/cblades/fineas
Author: Chris Blades
Author-email: me@chrisdblades.com
License: MIT License
Description: # Fineas
        
        State machine implementations that are:
        - Simple
        - Decorator-Based
        - Transition-Focused
        - Thread-Safe
        
        ```python
        import fineas
        
        
        @fineas.state_machine(initial_state='new', store_history=True)
        class TestMachine:
           def __init__(self):
              self.config = None
        
           @fineas.transition(
              source=['new', 'invalid_configuration'],
              dest='configured',
              error_state='invalid_configuration')
           def got_config(self, config):
              # validate config
              self.config = config
        
           @fineas.transition(source='configured', dest='scheduled')
           def ready(self):
              pass
        
           @fineas.transition(
              source='scheduled',
              dest='scheduled',
              error_state='canceled',
              failed_state='retry')
           def run(self, fail_transition):
              # do work
              status = self._do_work()
        
              if not status:
                 fail_transition()
        
           @fineas.transition(
              source='retry',
              dest='run',
              error_state='canceled',
              failed_state='too_many_failures'
           )
           def try_again(self, times, fail_transition):
              for i in range(times):
                 if self._do_work():
                    return
              fail_transition()
        
           @fineas.transition(
              source=['retry', 'too_many_failures'],
              dest='cancelled'
           )
           def abandon(self):
              pass
        
           @fineas.transition(
              source='too_many_failures',
              dest='configured'
           )
           def reconfigure(self, config):
              self.config = config
        
           def _do_work(self):
              pass
        
        
        t = TestMachine()
        t.got_config(None)
        t.ready()
        try:
           t.run()
        except fineas.TransitionException as t:
           # handle trying to transition from an invalid state
           pass
        t.try_again(3)
        t.abandon()
        
        
        print(t.history)
        
        print(t.state)
        ```
        
        ## Quickstart
        1) Decorate a class with `@fineas.state_machine(initial_state='new')`.  You must pass a value for 
           `initial_state`.
        2) Define a method that implements the work required to transition form one or more source states
           to a single destination state.  Decorate that method with 
           `@fineas.transition(source='new', dest='ready')`.
        3)  That's it!  Each instance of your decorated class is its own state machine.  You may check its
        current state with its `state` attribute, and, if you've enabled `record_history`, you can access
            its transition history with its `history` attribute.
        
        ## Overview
        To turn each instance of a class into a state machine, simply decorate it with 
        `@fineas.state_machine()`.  You must pass an `initial_state` value to `@fineas.state_machine()`.
        This will be the state every instance of your type starts in.  You can also enable recording state
        transitions with the `record_history` flag; this is useful while developing finite state machines.
        
        Every transition in your state machine is represented by a method inside the class you decorated 
        with `@fineas.state_machihe()`.  To turn a method into a transition, decorate it with 
        `@fineas.transition()` and supply one or more source states for the transition, and exactly one
        destination state.  You can also define a state to transition to if an exception is raised inside 
        your method (there is also a flag to enable or disable re-raising that exception).  If your method
        accepts a parameter named `fail_transition`, its value will be a callable your method can invoke to
        cause the transition to fail while still allowing your method to return a value to its caller.  You
        may also pass a `fail_state` parameter to the decorator, and when `fail_transition` is invoked, your
        instance will be transitioned to the given state.
        
        When any method decorated with `@fineas.transistion()` is called, the following steps happen:
        
        1) Acquire a lock over the receiving instance.
        1) Fineas validates that the receiving instance's state is in the sources passed to 
           `@fineas.transition()`
           - If it is not, a TransitionException is raised.
        1) The decorated method is invoked, passing `fail_transistion` if able.
        1) If the decorated method raises an exception:
           - If `error_state` was passed, immediately transition to that state.
           - If `reraise_error` is True, re-raise the exception.
           - Return.
        1) If `fail_transition` was called:
           - If 'fail_state' was passed, immediately transition to that state.
        1) If no exception was raised and `fail_transition` was not called, transition to the destination
           state and return the value returned by the decorated method.
           
        ## Requirements
        
        Python 3.6 or higher
        
        wrapt 1.12.x
        
        ## Release Notes
        
        0.9 (07 March, 2021):
        - Initial Release
        
Platform: UNKNOWN
Description-Content-Type: text/markdown
