Skip to main content

Chainstate

PyPI version License: MIT Python Versions

Chainstate is a powerful and intuitive Python library for implementing state machines. It provides a flexible and easy-to-use framework for defining, managing, and transitioning between states in your applications, with built-in support for sharing data between states.

Installation

Install Chainstate using pip:

pip install chainstate

Quick Start

Here's a simple example to get you started with Chainstate:

from chainstate import Chain, State, EndState

class GreetingState(State):
    def action(self):
        print("Hello! How can I assist you today?")
        self.context.data['user_name'] = input("Please enter your name: ")
    
    def next_state(self):
        return FarewellState

class FarewellState(EndState):
    def action(self):
        user_name = self.context.data.get('user_name', 'Guest')
        print(f"Thank you for using our service, {user_name}. Goodbye!")

# Create and run the chain
chain = Chain()
chain.add_state(GreetingState)
chain.add_state(FarewellState)
chain.set_initial_state(GreetingState)
chain.run()

This example creates a simple two-state chain that greets the user, asks for their name, and then says farewell using the stored name.

Detailed Usage

Defining States

To create a state, inherit from the State class and implement the action and next_state methods:

class MyState(State):
    def action(self):
        # Perform the state's action
        print("Performing MyState action")
        # Store data in the context
        self.context.data['my_key'] = 'my_value'
    
    def next_state(self):
        # Return the next state class
        return NextState

Creating a Chain

Use the Chain class to manage your states:

chain = Chain()
chain.add_state(MyState)
chain.add_state(NextState)
chain.set_initial_state(MyState)

Running the Chain

Execute the state machine using the run method:

chain.run()

Using the Context

The context attribute allows you to store and retrieve data that can be shared between states:

class StateA(State):
    def action(self):
        self.context.data['shared_value'] = 42
    
    def next_state(self):
        return StateB

class StateB(State):
    def action(self):
        value = self.context.data.get('shared_value')
        print(f"Received value from previous state: {value}")

Advanced Features

Error Handling

Chainstate provides built-in error handling for common issues:

  • InitialStateNotSetError: Raised when trying to run a chain without setting an initial state.
  • StateTransitionError: Raised when a state transition is invalid or when a state's next_state method is not implemented.

Logging

Chainstate uses Python's built-in logging module. You can configure logging to suit your needs:

import logging
logging.basicConfig(level=logging.DEBUG)

Use Case: Customer Support Chatbot

Let's implement a simple customer support chatbot using Chainstate:

from chainstate import Chain, State, EndState

class GreetingState(State):
    def action(self):
        print("Bot: Hello! How can I assist you today?")
        self.context.data['user_input'] = input("You: ")
    
    def next_state(self):
        user_input = self.context.data['user_input'].lower()
        if 'order' in user_input:
            return OrderState
        elif 'refund' in user_input:
            return RefundState
        else:
            return GeneralInfoState

class OrderState(State):
    def action(self):
        print("Bot: I can help you with your order. What's your order number?")
        order_number = input("You: ")
        self.context.data['order_number'] = order_number
        print(f"Bot: I've found your order {order_number}. It will be delivered in 2 days.")
    
    def next_state(self):
        return FarewellState

class RefundState(State):
    def action(self):
        print("Bot: I'm sorry to hear you need a refund. Please provide your order number.")
        order_number = input("You: ")
        self.context.data['refund_order'] = order_number
        print(f"Bot: I've initiated a refund for order {order_number}. It will be processed in 3-5 business days.")
    
    def next_state(self):
        return FarewellState

class GeneralInfoState(State):
    def action(self):
        print("Bot: For general inquiries, please visit our FAQ page at www.example.com/faq")
    
    def next_state(self):
        return FarewellState

class FarewellState(EndState):
    def action(self):
        if 'order_number' in self.context.data:
            print(f"Bot: Is there anything else I can help you with regarding your order {self.context.data['order_number']}? (yes/no)")
        elif 'refund_order' in self.context.data:
            print(f"Bot: Is there anything else I can help you with regarding your refund for order {self.context.data['refund_order']}? (yes/no)")
        else:
            print("Bot: Is there anything else I can help you with? (yes/no)")
        
        response = input("You: ")
        if response.lower() == 'yes':
            return GreetingState
        else:
            print("Bot: Thank you for using our service. Have a great day!")

# Run the chatbot
chain = Chain()
chain.add_state(GreetingState)
chain.add_state(OrderState)
chain.add_state(RefundState)
chain.add_state(GeneralInfoState)
chain.add_state(FarewellState)
chain.set_initial_state(GreetingState)
chain.run()

This chatbot uses Chainstate to manage different conversation flows based on user input, demonstrating how state machines can be used to create interactive and responsive systems. The context is used to store and retrieve information across different states, allowing for a more personalized interaction.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Metadata

Release files for chainstate 0.1.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chainstate 0.1.8
File Size Uploaded
chainstate-0.1.8.tar.gz 4.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for chainstate 0.1.8
File Interpreter ABI Platform
chainstate-0.1.8-py3-none-any.whl Python 3 none any Details

Total release size: 10.5 kB

Release files / chainstate-0.1.8.tar.gz

Download URL chainstate-0.1.8.tar.gz
Size 4.9 kB
Tags Source
SHA-256 checksum
How to use checksums
886cd01f65994e70e5f76fd4406ea87dc569d1e1d70df0507012548f4f6d43c3
BLAKE2b-256 checksum
How to use checksums
b4d80e9e881908a622c5563cd0c6dd911b9596e94a1b1393ab4d6bc421786788
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.8.4 CPython/3.11.10 Darwin/24.1.0

Release files / chainstate-0.1.8-py3-none-any.whl

Download URL chainstate-0.1.8-py3-none-any.whl
Size 5.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
35bb27f1251d116dbf58d0e6797d59c4dfaa12645bbf3e979004b51337e3a3b2
BLAKE2b-256 checksum
How to use checksums
3a16326f82a5cf09b9564e5aa0bc4a1c2f3784f31e922d3be9c8c168fa50af29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.8.4 CPython/3.11.10 Darwin/24.1.0

Release history Release notifications | RSS feed

This release

0.1.8 This release

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page