Source code for app.state_machine

from abc import ABC, abstractmethod


[docs] class StateMachine: """ Implements a simple state machine for order processing. The states are: - created - paid - packed - shipped - delivered - cancelled The valid transitions are: - created -> paid - paid -> packed - packed -> shipped - shipped -> delivered - paid -> cancelled - packed -> cancelled Once an order is delivered or cancelled, no further transitions are allowed. """ def __init__(self): """ Initializes the state machine with the initial state of 'created'. """ self._state: State = StateCreated() def _change_state(self, new_state): """ Changes the current state of the machine to the new state. Args: new_state: The new state to transition to. """ self._state = new_state
[docs] def update(self, new_status: str): """ Updates the state machine based on the new status. This method should be called whenever the order status changes. Args: new_status: The new status that triggers the state transition. """ self._state.update(self, new_status)
[docs] class State(ABC): """ Abstract base class for all states in the state machine. Each state must implement the update method to handle transitions to other states. """
[docs] @abstractmethod def update(self, machine: StateMachine, status: str): """ Handles the transition to the next state based on the new status. Args: machine: The state machine instance to update. status: The new status that triggers the state transition. """ ...
[docs] class StateCreated(State): """ Represents the 'created' state of an order. In this state, the order has been created but not yet paid for. The valid transition from this state is to 'paid'. """
[docs] def update(self, machine: StateMachine, status: str): if status == "paid": machine._change_state(StatePaid()) else: raise ValueError("Invalid status. Next step is to pay the order")
[docs] class StatePaid(State): """ Represents the 'paid' state of an order. In this state, the order has been paid for but not yet packed. The valid transitions from this state are to 'packed' or 'cancelled'. """
[docs] def update(self, machine: StateMachine, status: str): if status == "packed": machine._change_state(StatePacked()) elif status == "cancelled": machine._change_state(StateCancelled()) else: raise ValueError("Invalid status. Next step is to pack the order")
[docs] class StatePacked(State): """ Represents the 'packed' state of an order. In this state, the order has been packed but not yet shipped. The valid transitions from this state are to 'shipped' or 'cancelled'. """
[docs] def update(self, machine: StateMachine, status: str): if status == "shipped": machine._change_state(StateShipped()) elif status == "cancelled": machine._change_state(StateCancelled()) else: raise ValueError("Invalid status. Next step is to ship the order")
[docs] class StateShipped(State): """ Represents the 'shipped' state of an order. In this state, the order has been shipped but not yet delivered. The valid transition from this state is to 'delivered'. """
[docs] def update(self, machine: StateMachine, status: str): if status == "delivered": machine._change_state(StateDelivered()) elif status == "cancelled": raise ValueError("Order is already shipped") else: raise ValueError("Invalid status. Next step is to deliver the order")
[docs] class StateDelivered(State): """ Represents the 'delivered' state of an order. In this state, the order has been delivered to the customer. No further transitions are allowed from this state. """
[docs] def update(self, machine: StateMachine, status: str): raise ValueError("Order is already delivered")
[docs] class StateCancelled(State): """ Represents the 'cancelled' state of an order. In this state, the order has been cancelled and cannot be processed further. No further transitions are allowed from this state. """
[docs] def update(self, machine: StateMachine, status: str): raise ValueError("Order was cancelled")