Orders move through states (pending → paid → shipped → delivered, with cancellations and refunds). Encoding the allowed transitions explicitly prevents bugs like shipping an unpaid order.
Implement a class StateMachine(initial, transitions, guards=None):
transitions maps (state, event) to the next state. guards optionally maps (state, event) to a function of a context dict that must return True for the transition to be allowed.fire(event, ctx=None): perform the transition and return the new state. If the transition doesn't exist or its guard fails, raise InvalidTransition (a subclass of ValueError) mentioning the state and event, and leave the state unchanged.state, history (a list of (from_state, event, to_state)), can_fire(event, ctx=None) and available_events() (sorted events with a transition from the current state, ignoring guards)