jtushman / state_machine

Python State Machine for humans
MIT License
400 stars 31 forks source link

Methods to return all possible events, as well as valid next events given current state #22

Open julianpistorius opened 9 years ago

julianpistorius commented 9 years ago

Something like this:

(Note get_events and get_next_event_names)

def test_events_and_next_event_names():
    @acts_as_state_machine
    class Robot():
        name = 'R2-D2'

        sleeping = State(initial=True)
        running = State()
        cleaning = State()

        run = Event(from_states=sleeping, to_state=running)
        cleanup = Event(from_states=running, to_state=cleaning)
        sleep = Event(from_states=(running, cleaning), to_state=sleeping)

        @before('sleep')
        def do_one_thing(self):
            print("{} is sleepy".format(self.name))

        @before('sleep')
        def do_another_thing(self):
            print("{} is REALLY sleepy".format(self.name))

        @after('sleep')
        def snore(self):
            print("Zzzzzzzzzzzz")

        @after('sleep')
        def snore(self):
            print("Zzzzzzzzzzzzzzzzzzzzzz")

    robot = Robot()
    eq_(robot.current_state, 'sleeping')
    assert robot.is_sleeping
    assert not robot.is_running
    events = robot.get_events()
    event_names = events.keys()
    eq_(event_names, ['sleep', 'cleanup', 'run'])
    next_event_names = robot.get_next_event_names()
    eq_(next_event_names, ['run'])
    dynamic_event_name = next_event_names[0]
    dynamic_event = getattr(robot, dynamic_event_name)
    dynamic_event()
    assert robot.is_running

    next_event_names = robot.get_next_event_names()
    eq_(next_event_names, ['cleanup', 'sleep'])
    dynamic_event_name = next_event_names[1]
    dynamic_event = getattr(robot, dynamic_event_name)
    dynamic_event()
    assert robot.is_sleeping

The rationale for this feature: We found that we often need to display the possible actions (events) that a user can perform on an object given its current state.