コード例 #1
0
    def test_composite_statechart_finished(self):
        statechart = Statechart(name='statechart')
        init = InitialState(statechart)
        final = FinalState(statechart)

        composite = CompositeState(name='composite', context=statechart)
        composite_init = InitialState(composite)
        composite_default = State(name='composite_default', context=composite)
        composite_final = FinalState(composite)

        finish = Event('finish')

        Transition(start=init, end=composite)
        Transition(start=composite_init, end=composite_default)
        Transition(start=composite_default, end=composite_final, event=finish)
        Transition(start=composite, end=final)

        statechart.start()

        assert statechart.is_active('composite')
        assert statechart.is_active('composite_default')
        assert not statechart.is_finished()

        statechart.dispatch(finish)

        assert statechart.is_finished()
コード例 #2
0
ファイル: test_runtime.py プロジェクト: leighmck/statechart
def state():
    statechart = Statechart(name="statechart")
    initial_state = InitialState(statechart)
    next_state = State(name="next", context=statechart)
    Transition(initial_state, next_state)
    statechart.start()
    return next_state
コード例 #3
0
    def test_choice_state_transitions(self, choice, expected_state_name):
        class MyMetadata(Metadata):
            def __init__(self):
                super().__init__()
                self.value = None

        class IsA(Guard):
            def check(self, metadata, event):
                return metadata.value == 'a'

        myMetadata = MyMetadata()
        myMetadata.value = choice
        statechart = Statechart(name='statechart', metadata=myMetadata)
        init = InitialState(statechart)

        state_a = State(name='a', context=statechart)
        state_b = State(name='b', context=statechart)

        choice = ChoiceState(context=statechart)

        Transition(start=init, end=choice)

        Transition(start=choice, end=state_a, event=None, guard=IsA())
        Transition(start=choice, end=state_b, event=None, guard=ElseGuard())

        statechart.start()

        assert statechart.is_active(expected_state_name)
コード例 #4
0
def concurrent_statechart():
    def composite(name, context):
        composite = CompositeState(name=name, context=context)
        composite.init = InitialState(composite)
        composite.state = State(name='state', context=composite)
        composite.final = FinalState(composite)

        Transition(start=composite.init, end=composite.state)
        Transition(start=composite.state,
                   end=composite.final,
                   event=Event('finish'))

        return composite

    sc = Statechart('simple')
    sc.init = InitialState(sc)

    sc.concurrent = ConcurrentState(name='compound', context=sc)

    sc.concurrent.composite_a = composite(name='a', context=sc.concurrent)
    sc.concurrent.composite_b = composite(name='b', context=sc.concurrent)
    sc.concurrent.composite_c = composite(name='c', context=sc.concurrent)

    sc.final = FinalState(sc)

    Transition(start=sc.init, end=sc.concurrent)
    Transition(start=sc.concurrent, end=sc.final, event=Event('finish'))

    return sc
コード例 #5
0
def state():
    statechart = Statechart(name='statechart')
    initial_state = InitialState(statechart)
    next_state = State(name='next', context=statechart)
    Transition(initial_state, next_state)
    statechart.start()
    return next_state
コード例 #6
0
    def test_activate_initial_state(self):
        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)
        Transition(start=initial_state, end=default_state)
        startchart.start()

        initial_state.activate(metadata=startchart._metadata, event=None)
        assert startchart.is_active('default')
コード例 #7
0
    def test_activate_initial_state(self):
        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)
        Transition(start=initial_state, end=default_state)
        startchart.start()

        initial_state.activate(metadata=startchart.metadata, event=None)
        assert startchart.is_active('default')
コード例 #8
0
def simple_statechart():
    sc = Statechart('simple')
    sc.init = InitialState(sc)
    sc.state = State(name='state', context=sc)
    sc.final = FinalState(sc)

    Transition(start=sc.init, end=sc.state)
    Transition(start=sc.state, end=sc.final, event=Event('finish'))

    return sc
コード例 #9
0
ファイル: test_states.py プロジェクト: leighmck/statechart
    def test_composite_statechart_finished(self):
        statechart = Statechart(name="statechart")
        init = InitialState(statechart)
        final = FinalState(statechart)

        composite = CompositeState(name="composite", context=statechart)
        composite_init = InitialState(composite)
        composite_default = State(name="composite_default", context=composite)
        composite_final = FinalState(composite)

        finish = Event("finish")

        Transition(start=init, end=composite)
        Transition(start=composite_init, end=composite_default)
        Transition(start=composite_default, end=composite_final, event=finish)
        Transition(start=composite, end=final)

        statechart.start()

        assert statechart.is_active("composite")
        assert statechart.is_active("composite_default")
        assert not statechart.is_finished()

        statechart.dispatch(finish)

        assert statechart.is_finished()
コード例 #10
0
    def test_default_transition_from_finished_composite_state(self):
        statechart = Statechart(name='statechart')
        statechart_init = InitialState(statechart)

        composite_state = CompositeState(name='composite', context=statechart)
        comp_init = InitialState(composite_state)
        a = State(name='a', context=composite_state)
        comp_final = FinalState(composite_state)

        Transition(start=statechart_init, end=composite_state)
        Transition(start=comp_init, end=a)
        Transition(start=a, end=comp_final, event=Event('e'))

        b = State(name='b', context=statechart)
        c = State(name='c', context=statechart)
        d = State(name='d', context=statechart)

        Transition(start=composite_state, end=c, event=Event('f'))
        Transition(start=composite_state, end=b, event=Event('e'))
        Transition(start=composite_state, end=d)

        statechart.start()

        assert statechart.is_active('a')

        statechart.dispatch(Event('e'))

        assert statechart.is_active('d')
コード例 #11
0
    def test_transition_from_initial_state_with_event_trigger(self):
        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)

        with pytest.raises(RuntimeError):
            Transition(start=initial_state, end=default_state, event=Event('event'))
コード例 #12
0
    def test_multiple_transitions_from_initial_state(self):
        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)

        Transition(start=initial_state, end=default_state)
        with pytest.raises(RuntimeError):
            Transition(start=initial_state, end=default_state)
コード例 #13
0
    def test_cannot_create_multiple_shallow_history_states(self):
        startchart = Statechart(name='statechart')
        composite_state = CompositeState(name='composite', context=startchart)

        ShallowHistoryState(composite_state)

        with pytest.raises(RuntimeError):
            ShallowHistoryState(composite_state)
コード例 #14
0
    def test_add_transition(self):
        statechart = Statechart(name='statechart')
        initial_state = InitialState(statechart)
        default_state = State(name='default', context=statechart)

        default_transition = Transition(start=initial_state, end=default_state)

        assert default_transition in initial_state._transitions
コード例 #15
0
ファイル: test_states.py プロジェクト: leighmck/statechart
    def test_default_transition_from_finished_composite_state(self):
        statechart = Statechart(name="statechart")
        statechart_init = InitialState(statechart)

        composite_state = CompositeState(name="composite", context=statechart)
        comp_init = InitialState(composite_state)
        a = State(name="a", context=composite_state)
        comp_final = FinalState(composite_state)

        Transition(start=statechart_init, end=composite_state)
        Transition(start=comp_init, end=a)
        Transition(start=a, end=comp_final, event=Event("e"))

        b = State(name="b", context=statechart)
        c = State(name="c", context=statechart)
        d = State(name="d", context=statechart)

        Transition(start=composite_state, end=c, event=Event("f"))
        Transition(start=composite_state, end=b, event=Event("e"))
        Transition(start=composite_state, end=d)

        statechart.start()

        assert statechart.is_active("a")

        statechart.dispatch(Event("e"))

        assert statechart.is_active("d")
コード例 #16
0
    def test_active_states(self):
        statechart = Statechart(name='a')
        statechart_init = InitialState(statechart)

        b = CompositeState(name='b', context=statechart)
        b_init = InitialState(b)

        c = CompositeState(name='c', context=b)
        c_init = InitialState(c)

        d = State(name='d', context=c)

        Transition(start=statechart_init, end=b)
        Transition(start=b_init, end=c)
        Transition(start=c_init, end=d)

        statechart.start()
        assert statechart.active_states() == [statechart, b, c, d]
コード例 #17
0
    def test_light_switch(self):
        """
                      --Flick-->
        init ---> Off            On
                      <--Flick--   Entry: Light = ON
                                   Exit: Light = OFF
                                   Internal:
                                     Flick: Count++
        """
        class On(State):
            def __init__(self, name, context, data):
                State.__init__(self, name=name, context=context)
                self.data = data

            def entry(self, event):
                self.data['light'] = 'on'

            def exit(self, event):
                self.data['light'] = 'off'

            def handle_internal(self, event):
                if event.name == 'flick':
                    self.data['on_count'] += 1

        sm = Statechart(name='sm')
        data = dict(light='off', on_count=0)
        sm.initial_state = InitialState(context=sm)
        off = State(name='off', context=sm)
        on = On(name='on', context=sm, data=data)

        Transition(start=sm.initial_state, end=off)
        Transition(start=off, end=on, event=Event('flick'))
        Transition(start=on, end=off, event=Event('flick'))

        sm.start()

        assert data['light'] == 'off'

        sm.dispatch(Event('flick'))
        assert data['light'] == 'on'

        assert data['on_count'] == 0

        sm.dispatch(Event('flick'))
        assert data['light'] == 'off'

        assert data['on_count'] == 1
コード例 #18
0
    def test_transition_from_initial_state_with_guard_condition(self):
        class MyGuard(Guard):
            def check(self, metadata, event):
                return False

        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)

        with pytest.raises(RuntimeError):
            Transition(start=initial_state, end=default_state, event=None, guard=MyGuard())
コード例 #19
0
    def test_choice_state_transitions(self, state_name, expected_state_name):
        def is_a(**kwargs):
            return state_name == 'a'

        statechart = Statechart(name='statechart')
        init = InitialState(statechart)

        state_a = State(name='a', context=statechart)
        state_b = State(name='b', context=statechart)

        choice = ChoiceState(context=statechart)

        Transition(start=init, end=choice)

        Transition(start=choice, end=state_a, event=None, guard=is_a)
        Transition(start=choice, end=state_b, event=None, guard=None)  # else

        statechart.start()

        assert statechart.is_active(expected_state_name)
コード例 #20
0
def main() -> None:
    """Code here shows how everything is wired together.

    The following lines are the expected output:

        state 'state-a' got event 'None'
        state 'state-b' got event 'Event(name="to-state-b", data={})'
    """
    # Create the state machine -- the root context of every workflow.
    state_machine = Statechart("state-machine")

    # Create the workflow metadata with all the data accessible to all states and workflows.
    metadata = WorkflowMetadata(a=10, b="foo", c="bar")

    # Create the workflow factory backed by the workflow metadata.
    factory = WorkflowFactory(metadata)

    # Create the main workflow using the workflow factory.
    main_workflow = factory.create_workflow("main-workflow", state_machine, MainWorkflow)

    # Set up the main transitions.
    init = InitialState(state_machine)
    final = FinalState(state_machine)
    Transition(init, main_workflow)
    Transition(main_workflow, final, event=Event("final"))

    # Run the state machine.
    state_machine.start()
    state_machine.dispatch(Event("to-state-b"))
コード例 #21
0
    def test_simple_statechart_finished(self):
        statechart = Statechart(name='statechart')
        init = InitialState(statechart)
        default = State(name='default', context=statechart)
        final = FinalState(statechart)

        finish = Event('finish')

        Transition(start=init, end=default)
        Transition(start=default, end=final, event=finish)
        statechart.start()

        assert statechart.is_active('default')
        assert not statechart.is_finished()

        statechart.dispatch(finish)

        assert statechart.is_finished()
コード例 #22
0
    def test_transition_from_initial_state_with_guard_condition(self):
        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)

        def my_guard(**kwargs):
            return False

        with pytest.raises(RuntimeError):
            Transition(start=initial_state,
                       end=default_state,
                       event=None,
                       guard=my_guard)
コード例 #23
0
ファイル: test_states.py プロジェクト: leighmck/statechart
    def test_simple_statechart_finished(self):
        statechart = Statechart(name="statechart")
        init = InitialState(statechart)
        default = State(name="default", context=statechart)
        final = FinalState(statechart)

        finish = Event("finish")

        Transition(start=init, end=default)
        Transition(start=default, end=final, event=finish)
        statechart.start()

        assert statechart.is_active("default")
        assert not statechart.is_finished()

        statechart.dispatch(finish)

        assert statechart.is_finished()
コード例 #24
0
    def test_default_transition_isnt_executed_from_unfinished_composite_state(
            self):
        statechart = Statechart(name='statechart')
        statechart_init = InitialState(statechart)

        composite_state = CompositeState(name='composite', context=statechart)
        comp_init = InitialState(composite_state)
        a = State(name='a', context=composite_state)

        Transition(start=statechart_init, end=composite_state)
        Transition(start=comp_init, end=a)

        b = State(name='b', context=statechart)

        Transition(start=composite_state, end=b)

        statechart.start()

        assert statechart.is_active('a')

        statechart.dispatch(Event('e'))

        assert statechart.is_active('a')
コード例 #25
0
ファイル: test_states.py プロジェクト: leighmck/statechart
    def test_default_transition_isnt_executed_from_unfinished_composite_state(self):
        statechart = Statechart(name="statechart")
        statechart_init = InitialState(statechart)

        composite_state = CompositeState(name="composite", context=statechart)
        comp_init = InitialState(composite_state)
        a = State(name="a", context=composite_state)

        Transition(start=statechart_init, end=composite_state)
        Transition(start=comp_init, end=a)

        b = State(name="b", context=statechart)

        Transition(start=composite_state, end=b)

        statechart.start()

        assert statechart.is_active("a")

        statechart.dispatch(Event("e"))

        assert statechart.is_active("a")
コード例 #26
0
class Main:
    def __init__(self):
        self.sm = Statechart()
        self.ti = TimerService()
        self.cb = Callback(self.sm)

    def setup(self):
        self.sm.timer_service = self.ti
        self.sm.operation_callback = self.cb
        self.sm.enter()

    def run(self):
        try:
            while True:
                self.sm.user.raise_clock()
                time.sleep(1)
                self.sm.run_cycle()
        except KeyboardInterrupt:
            self.shutdown()

    def shutdown(self):
        print('State machine shuts down.')
        self.sm.exit()
        print('Bye!')
コード例 #27
0
    def test_activate_shallow_history_state(self):
        """
        statechart:

        statechart_init
                  |
        *** csa **********************          *** csb *************
        *                            *          *                   *
        *  csa_init-csa_hist         *          *  csb_init         *
        *              |             *  --J-->  *     |             *
        *              A  --I-->  B  *  <--K--  *     C  --L-->  D  *
        *                            *          *                   *
        ******************************          *********************
        """

        # Top level states
        statechart = Statechart(name='statechart')
        csa = CompositeState(name='csa', context=statechart)
        csb = CompositeState(name='csb', context=statechart)

        # Child states
        # statechart
        statechart_init = InitialState(statechart)
        # csa
        csa_init = InitialState(csa)
        csa_hist = ShallowHistoryState(context=csa)
        A = State(name='A', context=csa)
        B = State(name='B', context=csa)
        # csb
        csb_init = InitialState(csb)
        C = State(name='C', context=csb)
        D = State(name='D', context=csb)

        # Events
        I = Event(name='I')
        J = Event(name='J')
        K = Event(name='K')
        L = Event(name='L')

        # Transitions between states & event triggers
        Transition(start=statechart_init, end=csa)
        Transition(start=csa_init, end=csa_hist)
        Transition(start=csa_hist, end=A)
        Transition(start=A, end=B, event=I)
        Transition(start=csa, end=csb, event=J)
        Transition(start=csb, end=csa, event=K)
        Transition(start=csb_init, end=C)
        Transition(start=C, end=D, event=L)

        # Execute statechart
        statechart.start()
        statechart.dispatch(I)

        # Assert we have reached state B, history should restore this state
        assert statechart.is_active('B')

        statechart.dispatch(J)

        # Assert we have reached state C
        assert statechart.is_active('C')

        statechart.dispatch(K)

        # Assert the history state has restored state B
        assert statechart.is_active('B')
コード例 #28
0
    def test_activate_shallow_history_state(self):
        """
        statechart:

        statechart_init
                  |
        *** csa **********************          *** csb *************
        *                            *          *                   *
        *  csa_init-csa_hist         *          *  csb_init         *
        *              |             *  --J-->  *     |             *
        *              A  --I-->  B  *  <--K--  *     C  --L-->  D  *
        *                            *          *                   *
        ******************************          *********************
        """

        # Top level states
        statechart = Statechart(name='statechart')
        csa = CompositeState(name='csa', context=statechart)
        csb = CompositeState(name='csb', context=statechart)

        # Child states
        # statechart
        statechart_init = InitialState(statechart)
        # csa
        csa_init = InitialState(csa)
        csa_hist = ShallowHistoryState(context=csa)
        A = State(name='A', context=csa)
        B = State(name='B', context=csa)
        # csb
        csb_init = InitialState(csb)
        C = State(name='C', context=csb)
        D = State(name='D', context=csb)

        # Events
        I = Event(name='I')
        J = Event(name='J')
        K = Event(name='K')
        L = Event(name='L')

        # Transitions between states & event triggers
        Transition(start=statechart_init, end=csa)
        Transition(start=csa_init, end=csa_hist)
        Transition(start=csa_hist, end=A)
        Transition(start=A, end=B, event=I)
        Transition(start=csa, end=csb, event=J)
        Transition(start=csb, end=csa, event=K)
        Transition(start=csb_init, end=C)
        Transition(start=C, end=D, event=L)

        # Execute statechart
        statechart.start()
        statechart.dispatch(I)

        # Assert we have reached state B, history should restore this state
        assert statechart.is_active('B')

        statechart.dispatch(J)

        # Assert we have reached state C
        assert statechart.is_active('C')

        statechart.dispatch(K)

        # Assert the history state has restored state B
        assert statechart.is_active('B')
コード例 #29
0
ファイル: test_states.py プロジェクト: leighmck/statechart
    def test_keyboard_example(self):
        """
        Test classic concurrent state keyboard example with concurrent states
        for caps, num and scroll lock.

        init - -
               |
               v
        -- keyboard --------------------------------------
        |                                                |
        |  init ---> --caps lock off --                  |
        |        --- |                | <--              |
        |        |   -----------------|   |              |
        |  caps lock pressed       caps lock pressed     |
        |        |   -- caps lock on --   |              |
        |        --> |                | ---              |
        |            ------------------                  |
        |                                                |
        --------------------------------------------------
        |                                                |
        |  init ---> --num lock off ---                  |
        |        --- |                | <--              |
        |        |   -----------------|   |              |
        |  num lock pressed      num lock pressed        |
        |        |   -- num lock on ---   |              |
        |        --> |                | ---              |
        |            ------------------                  |
        |                                                |
        --------------------------------------------------
        |                                                |
        |  init ---> -- scroll lock off --               |
        |        --- |                    | <--          |
        |        |   ---------------------|   |          |
        |  scroll lock pressed      scroll lock pressed  |
        |        |   -- scroll lock on ---|   |          |
        |        --> |                    | ---          |
        |            ----------------------              |
        |                                                |
        --------------------------------------------------
        """
        statechart = Statechart(name="statechart")

        start_state = InitialState(statechart)
        keyboard = ConcurrentState(name="keyboard", context=statechart)
        Transition(start=start_state, end=keyboard)

        caps_lock = CompositeState(name="caps_lock", context=keyboard)
        caps_lock_initial = InitialState(caps_lock)
        caps_lock_on = State(name="caps_lock_on", context=caps_lock)
        caps_lock_off = State(name="caps_lock_off", context=caps_lock)
        caps_lock_pressed = Event(name="caps_lock_pressed")
        Transition(start=caps_lock_initial, end=caps_lock_off)
        Transition(start=caps_lock_on, end=caps_lock_off, event=caps_lock_pressed)
        Transition(start=caps_lock_off, end=caps_lock_on, event=caps_lock_pressed)

        num_lock = CompositeState(name="num_lock", context=keyboard)
        num_lock_initial = InitialState(num_lock)
        num_lock_on = State(name="num_lock_on", context=num_lock)
        num_lock_off = State(name="num_lock_off", context=num_lock)
        num_lock_pressed = Event(name="num_lock_pressed")
        Transition(start=num_lock_initial, end=num_lock_off)
        Transition(start=num_lock_on, end=num_lock_off, event=num_lock_pressed)
        Transition(start=num_lock_off, end=num_lock_on, event=num_lock_pressed)

        scroll_lock = CompositeState(name="scroll_lock", context=keyboard)
        scroll_lock_initial = InitialState(scroll_lock)
        scroll_lock_on = State(name="scroll_lock_on", context=scroll_lock)
        scroll_lock_off = State(name="scroll_lock_off", context=scroll_lock)
        scroll_lock_pressed = Event(name="scroll_lock_pressed")
        Transition(start=scroll_lock_initial, end=scroll_lock_off)
        Transition(start=scroll_lock_on, end=scroll_lock_off, event=scroll_lock_pressed)
        Transition(start=scroll_lock_off, end=scroll_lock_on, event=scroll_lock_pressed)

        statechart.start()

        assert statechart.is_active("keyboard")
        assert statechart.is_active("caps_lock_off")
        assert statechart.is_active("num_lock_off")
        assert statechart.is_active("scroll_lock_off")

        statechart.dispatch(event=caps_lock_pressed)
        assert statechart.is_active("caps_lock_on")

        statechart.dispatch(event=num_lock_pressed)
        assert statechart.is_active("num_lock_on")

        statechart.dispatch(event=scroll_lock_pressed)
        assert statechart.is_active("scroll_lock_on")

        statechart.dispatch(event=caps_lock_pressed)
        assert statechart.is_active("caps_lock_off")

        statechart.dispatch(event=num_lock_pressed)
        assert statechart.is_active("num_lock_off")

        statechart.dispatch(event=scroll_lock_pressed)
        assert statechart.is_active("scroll_lock_off")
コード例 #30
0
 def test_create_shallow_history_state(self):
     startchart = Statechart(name='statechart')
     composite_state = CompositeState(name='composite', context=startchart)
     ShallowHistoryState(composite_state)
コード例 #31
0
ファイル: test_states.py プロジェクト: leighmck/statechart
    def test_submachines(self):
        statechart = Statechart(name="statechart")

        init = InitialState(statechart)
        top_a = self.Submachine("top a", statechart)
        top_b = self.Submachine("top b", statechart)

        top_a_to_b = Event("top ab")
        Transition(start=init, end=top_a)
        Transition(start=top_a, end=top_b, event=top_a_to_b)

        statechart.start()

        assert statechart.is_active("top a")
        assert statechart.is_active("sub state a")

        statechart.dispatch(top_a.sub_a_to_b)

        assert statechart.is_active("top a")
        assert statechart.is_active("sub state b")

        statechart.dispatch(top_a_to_b)

        assert statechart.is_active("top b")
        assert statechart.is_active("sub state a")

        statechart.dispatch(top_a.sub_a_to_b)

        assert statechart.is_active("top b")
        assert statechart.is_active("sub state b")
コード例 #32
0
    def test_submachines(self):
        statechart = Statechart(name='statechart')

        init = InitialState(statechart)
        top_a = self.Submachine('top a', statechart)
        top_b = self.Submachine('top b', statechart)

        top_a_to_b = Event('top ab')
        Transition(start=init, end=top_a)
        Transition(start=top_a, end=top_b, event=top_a_to_b)

        statechart.start()

        assert statechart.is_active('top a')
        assert statechart.is_active('sub state a')

        statechart.dispatch(top_a.sub_a_to_b)

        assert statechart.is_active('top a')
        assert statechart.is_active('sub state b')

        statechart.dispatch(top_a_to_b)

        assert statechart.is_active('top b')
        assert statechart.is_active('sub state a')

        statechart.dispatch(top_a.sub_a_to_b)

        assert statechart.is_active('top b')
        assert statechart.is_active('sub state b')
コード例 #33
0
    def test_missing_transition_from_initial_state(self):
        startchart = Statechart(name='statechart')
        InitialState(startchart)

        with pytest.raises(RuntimeError):
            startchart.start()
コード例 #34
0
    def test_activate_multiple_shallow_history_states(self):
        """
        statechart:

        statechart_init
               |
        *** csa *****************************************************          *** csc *************
        *                                                           *          *                   *
        *  csa_init--csa_hist                                       *          *  csc_init         *
        *               |                                           *  --K-->  *     |             *
        *               A  --I-->  *** csb ***********************  *  <--L--  *     D  --M-->  E  *
        *                          *                             *  *          *                   *
        *                          *  csb_init--csb_hist         *  *          *********************
        *                          *               |             *  *
        *                          *               B  --J-->  C  *  *
        *                          *                             *  *
        *                          *******************************  *
        *                                                           *
        *************************************************************
        """
        # Top level states
        statechart = Statechart(name='statechart')
        csa = CompositeState(name='csa', context=statechart)
        csb = CompositeState(name='csb', context=csa)
        csc = CompositeState(name='csc', context=statechart)

        # Child states
        # statechart
        statechart_init = InitialState(statechart)

        # csa
        csa_init = InitialState(csa)
        csa_hist = ShallowHistoryState(context=csa)
        A = State(name='A', context=csa)
        # csb
        csb_init = InitialState(csb)
        csb_hist = ShallowHistoryState(context=csb)
        B = State(name='B', context=csb)
        C = State(name='C', context=csb)
        # csc
        csc_init = InitialState(csc)
        D = State(name='D', context=csc)
        E = State(name='E', context=csc)

        # Events
        I = Event(name='I')
        J = Event(name='J')
        K = Event(name='K')
        L = Event(name='L')
        M = Event(name='M')

        # Transitions between states & event triggers
        Transition(start=statechart_init, end=csa)
        Transition(start=csa_init, end=csa_hist)
        Transition(start=csa_hist, end=A)
        Transition(start=A, end=csb, event=I)
        Transition(start=csb_init, end=csb_hist)
        Transition(start=csb_hist, end=B)
        Transition(start=B, end=C, event=J)
        Transition(start=csa, end=csc, event=K)
        Transition(start=csc, end=csa, event=L)
        Transition(start=csc_init, end=D)
        Transition(start=D, end=E, event=M)

        # Execute statechart
        statechart.start()
        statechart.dispatch(I)

        assert statechart.is_active('B')

        statechart.dispatch(J)

        # Assert we have reached state C, csb's history state should restore
        # this state
        assert statechart.is_active('C')

        statechart.dispatch(K)

        # Assert we have reached state D
        assert statechart.is_active('D')

        statechart.dispatch(L)

        # Assert the history state has restored state C
        assert statechart.is_active('C')
コード例 #35
0
    def test_keyboard_example(self):
        """
        Test classic concurrent state keyboard example with concurrent states
        for caps, num and scroll lock.

        init - -
               |
               v
        -- keyboard --------------------------------------
        |                                                |
        |  init ---> --caps lock off --                  |
        |        --- |                | <--              |
        |        |   -----------------|   |              |
        |  caps lock pressed       caps lock pressed     |
        |        |   -- caps lock on --   |              |
        |        --> |                | ---              |
        |            ------------------                  |
        |                                                |
        --------------------------------------------------
        |                                                |
        |  init ---> --num lock off ---                  |
        |        --- |                | <--              |
        |        |   -----------------|   |              |
        |  num lock pressed      num lock pressed        |
        |        |   -- num lock on ---   |              |
        |        --> |                | ---              |
        |            ------------------                  |
        |                                                |
        --------------------------------------------------
        |                                                |
        |  init ---> -- scroll lock off --               |
        |        --- |                    | <--          |
        |        |   ---------------------|   |          |
        |  scroll lock pressed      scroll lock pressed  |
        |        |   -- scroll lock on ---|   |          |
        |        --> |                    | ---          |
        |            ----------------------              |
        |                                                |
        --------------------------------------------------
        """
        statechart = Statechart(name='statechart')

        start_state = InitialState(statechart)
        keyboard = ConcurrentState(name='keyboard', context=statechart)
        Transition(start=start_state, end=keyboard)

        caps_lock = CompositeState(name='caps_lock', context=keyboard)
        caps_lock_initial = InitialState(caps_lock)
        caps_lock_on = State(name='caps_lock_on', context=caps_lock)
        caps_lock_off = State(name='caps_lock_off', context=caps_lock)
        caps_lock_pressed = Event(name='caps_lock_pressed')
        Transition(start=caps_lock_initial, end=caps_lock_off)
        Transition(start=caps_lock_on,
                   end=caps_lock_off,
                   event=caps_lock_pressed)
        Transition(start=caps_lock_off,
                   end=caps_lock_on,
                   event=caps_lock_pressed)

        num_lock = CompositeState(name='num_lock', context=keyboard)
        num_lock_initial = InitialState(num_lock)
        num_lock_on = State(name='num_lock_on', context=num_lock)
        num_lock_off = State(name='num_lock_off', context=num_lock)
        num_lock_pressed = Event(name='num_lock_pressed')
        Transition(start=num_lock_initial, end=num_lock_off)
        Transition(start=num_lock_on, end=num_lock_off, event=num_lock_pressed)
        Transition(start=num_lock_off, end=num_lock_on, event=num_lock_pressed)

        scroll_lock = CompositeState(name='scroll_lock', context=keyboard)
        scroll_lock_initial = InitialState(scroll_lock)
        scroll_lock_on = State(name='scroll_lock_on', context=scroll_lock)
        scroll_lock_off = State(name='scroll_lock_off', context=scroll_lock)
        scroll_lock_pressed = Event(name='scroll_lock_pressed')
        Transition(start=scroll_lock_initial, end=scroll_lock_off)
        Transition(start=scroll_lock_on,
                   end=scroll_lock_off,
                   event=scroll_lock_pressed)
        Transition(start=scroll_lock_off,
                   end=scroll_lock_on,
                   event=scroll_lock_pressed)

        statechart.start()

        assert statechart.is_active('keyboard')
        assert statechart.is_active('caps_lock_off')
        assert statechart.is_active('num_lock_off')
        assert statechart.is_active('scroll_lock_off')

        statechart.dispatch(event=caps_lock_pressed)
        assert statechart.is_active('caps_lock_on')

        statechart.dispatch(event=num_lock_pressed)
        assert statechart.is_active('num_lock_on')

        statechart.dispatch(event=scroll_lock_pressed)
        assert statechart.is_active('scroll_lock_on')

        statechart.dispatch(event=caps_lock_pressed)
        assert statechart.is_active('caps_lock_off')

        statechart.dispatch(event=num_lock_pressed)
        assert statechart.is_active('num_lock_off')

        statechart.dispatch(event=scroll_lock_pressed)
        assert statechart.is_active('scroll_lock_off')
コード例 #36
0
    def test_activate_multiple_shallow_history_states(self):
        """
        statechart:

        statechart_init
               |
        *** csa *****************************************************          *** csc *************
        *                                                           *          *                   *
        *  csa_init--csa_hist                                       *          *  csc_init         *
        *               |                                           *  --K-->  *     |             *
        *               A  --I-->  *** csb ***********************  *  <--L--  *     D  --M-->  E  *
        *                          *                             *  *          *                   *
        *                          *  csb_init--csb_hist         *  *          *********************
        *                          *               |             *  *
        *                          *               B  --J-->  C  *  *
        *                          *                             *  *
        *                          *******************************  *
        *                                                           *
        *************************************************************
        """
        # Top level states
        statechart = Statechart(name='statechart')
        csa = CompositeState(name='csa', context=statechart)
        csb = CompositeState(name='csb', context=csa)
        csc = CompositeState(name='csc', context=statechart)

        # Child states
        # statechart
        statechart_init = InitialState(statechart)

        # csa
        csa_init = InitialState(csa)
        csa_hist = ShallowHistoryState(context=csa)
        A = State(name='A', context=csa)
        # csb
        csb_init = InitialState(csb)
        csb_hist = ShallowHistoryState(context=csb)
        B = State(name='B', context=csb)
        C = State(name='C', context=csb)
        # csc
        csc_init = InitialState(csc)
        D = State(name='D', context=csc)
        E = State(name='E', context=csc)

        # Events
        I = Event(name='I')
        J = Event(name='J')
        K = Event(name='K')
        L = Event(name='L')
        M = Event(name='M')

        # Transitions between states & event triggers
        Transition(start=statechart_init, end=csa)
        Transition(start=csa_init, end=csa_hist)
        Transition(start=csa_hist, end=A)
        Transition(start=A, end=csb, event=I)
        Transition(start=csb_init, end=csb_hist)
        Transition(start=csb_hist, end=B)
        Transition(start=B, end=C, event=J)
        Transition(start=csa, end=csc, event=K)
        Transition(start=csc, end=csa, event=L)
        Transition(start=csc_init, end=D)
        Transition(start=D, end=E, event=M)

        # Execute statechart
        statechart.start()
        statechart.dispatch(I)

        assert statechart.is_active('B')

        statechart.dispatch(J)

        # Assert we have reached state C, csb's history state should restore
        # this state
        assert statechart.is_active('C')

        statechart.dispatch(K)

        # Assert we have reached state D
        assert statechart.is_active('D')

        statechart.dispatch(L)

        # Assert the history state has restored state C
        assert statechart.is_active('C')
コード例 #37
0
 def test_create_initial_state(self):
     startchart = Statechart(name='statechart')
     InitialState(startchart)
コード例 #38
0
 def test_create_state(self):
     statechart = Statechart(name='statechart')
     State(name='anon', context=statechart)
コード例 #39
0
    def test_missing_transition_from_initial_state(self):
        startchart = Statechart(name='statechart')
        InitialState(startchart)

        with pytest.raises(RuntimeError):
            startchart.start()
コード例 #40
0
    def test_add_transition(self):
        statechart = Statechart(name='statechart')
        final_state = FinalState(statechart)

        with pytest.raises(RuntimeError):
            Transition(start=final_state, end=statechart)
コード例 #41
0
 def test_create_statechart(self):
     Statechart(name='statechart')