Ejemplo n.º 1
0
    def test_asynchronous_finisher(self):
        '''make termination action'''
        termination = NullAction(rspec="kill")
        termination.set_nexus(self.nexus)
        alt = MockAlternative(u"my", u"spoken", u"words")
        sira = StackItemRegisteredAction(termination, {"_node": alt})
        '''setup function for asynchronous finisher'''
        mutable_integer = {"value": 0}

        def increment():
            mutable_integer["value"] += 1

        #
        '''make asynchronous action'''
        asynchronous = AsynchronousAction([L(S(["kill"], lambda: None))],
                                          blocking=False,
                                          finisher=Function(increment))
        asynchronous.set_nexus(self.nexus)
        '''make StackItemAsynchronous'''
        sia1 = StackItemAsynchronous(asynchronous, {"_node": alt})
        '''add it'''
        self.nexus.state.add(sia1)

        #

        self.nexus.state.add(sira)
        '''finisher should be executed when asynchronous finishes'''
        self.assertEqual(mutable_integer["value"], 1)
Ejemplo n.º 2
0
    def test_seeker_defaulting_and_chaining(self):
        '''this action makes the first seeker default'''
        action = NullAction(rspec="clean")
        action.set_nexus(self.nexus)
        alt = MockAlternative(u"my", u"spoken", u"words")
        sira = StackItemRegisteredAction(action, {"_node": alt})
        self.nexus.state.add(sira)

        #

        mutable_integer = {"value": 0}

        def increment():
            mutable_integer["value"] += 1

        '''make backward seekers'''
        back_seeker = ContextSeeker(back=[
            L(S(["def"], Function(lambda: None)),
              S(["abc"], Function(increment)))
        ],
                                    rspec="abc")
        back_seeker.set_nexus(self.nexus)
        '''create backward seeker stack items'''
        stack_seeker1 = StackItemSeeker(back_seeker, {"_node": alt})
        stack_seeker2 = StackItemSeeker(back_seeker, {"_node": alt})
        '''add one'''
        self.nexus.state.add(stack_seeker1)
        '''at this point, the first seeker should have defaulted and done nothing'''
        self.assertEqual(mutable_integer["value"], 0)

        self.nexus.state.add(stack_seeker2)
        '''the second context seeker should have been triggered by the first, incrementing the value'''
        self.assertEqual(mutable_integer["value"], 1)
Ejemplo n.º 3
0
    def test_blocking(self):
        '''
        Tests:
        1 - successful termination (queued actions execute immediately)
        2 - unsuccessful termination (queued actions are dropped)
        3 - cancellation (queued actions are dropped)
        '''

        for i in range(0, 3):
            '''make fake AsynchronousAction'''
            context_set = S(["cancel", "words"], NullAction())
            context_level = L(context_set)
            aa1 = AsynchronousAction([context_level],
                                     blocking=True)  # turn blocking on
            aa1.set_nexus(self.nexus)
            '''make fake StackItemAsynchronous'''
            alt = MockAlternative(u"run", u"blocker")
            sia1 = StackItemAsynchronous(
                aa1, {"_node": alt})  # the dictionary is fake Dragonfly data
            '''add it'''
            self.nexus.state.add(sia1)
            '''blocked function'''
            mutable_integer = {"value": 0}

            def increment():
                mutable_integer["value"] += 1

            '''make fake incrementing RegisteredAction'''
            inc = R(Function(increment), rspec="inc")
            inc.set_nexus(self.nexus)
            '''make fake StackItemRegisteredAction'''
            alt2 = MockAlternative(u"my", u"spoken", u"words")
            sira1 = StackItemRegisteredAction(inc, {"_node": alt2})
            '''add it'''
            self.nexus.state.add(sira1)
            '''incrementing should be blocked at this point'''
            self.assertEqual(mutable_integer["value"], 0)

            if i == 0:
                '''incrementing should happen that moment of unblocking'''
                self.nexus.state.terminate_asynchronous(True)
                self.assertEqual(mutable_integer["value"], 1)
            elif i == 1:
                '''incrementing gets dropped'''
                self.nexus.state.terminate_asynchronous(False)
                self.assertEqual(mutable_integer["value"], 0)
            elif i == 2:
                '''make fake canceling RegisteredAction'''
                cancel = NullAction(rspec="cancel")
                cancel.set_nexus(self.nexus)
                '''make fake StackItemRegisteredAction'''
                alt3 = MockAlternative(u"my", u"cancel", u"words")
                sira2 = StackItemRegisteredAction(cancel, {"_node": alt3})
                '''add it'''
                self.nexus.state.add(sira2)
                '''incrementing gets dropped'''
                self.assertEqual(mutable_integer["value"], 0)
Ejemplo n.º 4
0
    def test_cancel(self):
        mutable_integer = {"value": 0}

        def increment():
            mutable_integer["value"] += 1

        '''make fake AsynchronousAction'''
        context_set = S(["test", "words"], increment)
        unused_context_set = S(["other"], Text, "words")
        context_level = L(context_set, unused_context_set)
        aa1 = AsynchronousAction([context_level],
                                 time_in_seconds=0.2,
                                 repetitions=20,
                                 blocking=False)
        aa1.set_nexus(self.nexus)
        '''make fake StackItemAsynchronous'''
        alt = MockAlternative(u"gray", u"fox")
        sia1 = StackItemAsynchronous(
            aa1, {"_node": alt})  # the dictionary is fake Dragonfly data
        '''add it'''
        self.nexus.state.add(sia1)
        '''make fake canceling RegisteredAction'''
        cancel = R(NullAction(), rspec="test")
        cancel.set_nexus(self.nexus)
        '''make fake StackItemRegisteredAction'''
        alt2 = MockAlternative(u"my", u"spoken", u"words")
        sira1 = StackItemRegisteredAction(cancel, {"_node": alt2})
        '''add it'''
        self.nexus.state.add(sira1)
        '''AsynchronousAction should have executed exactly once, 
        when it was added, then immediately gotten canceled'''
        self.assertEqual(mutable_integer["value"], 1)
Ejemplo n.º 5
0
    def test_seeker_backward(self):
        for i in range(0, 2):
            '''make 2 fake NullActions'''
            trigger1 = NullAction(rspec="bell")
            trigger2 = NullAction(rspec="door")
            trigger1.set_nexus(self.nexus)
            trigger2.set_nexus(self.nexus)
            '''make fake StackItemRegisteredActions'''
            alt2 = MockAlternative(u"my", u"spoken", u"words")
            sira1 = StackItemRegisteredAction(trigger1, {"_node": alt2})
            sira2 = StackItemRegisteredAction(trigger2, {"_node": alt2})
            '''add them'''
            self.nexus.state.add(sira1)
            self.nexus.state.add(sira2)
            '''set up backward looking seeker'''
            mutable_string = {"value": ""}

            def append_a():
                mutable_string["value"] += "a"

            def append_b():
                mutable_string["value"] += "b"

            def append_c():
                mutable_string["value"] += "c"

            def append_d():
                mutable_string["value"] += "d"

            '''create context levels'''
            set_1_1 = S(["arch"], append_a)
            set_1_2 = S(["bell"], append_b)
            level_1 = L(set_1_1, set_1_2)
            set_2_1 = S(["cellar"], append_c)
            set_2_2 = S(["door"], append_d)
            level_2 = L(set_2_1, set_2_2)
            '''create context seeker'''
            levels = [level_1, level_2]
            seeker = ContextSeeker(back=levels)
            if i == 0:
                seeker.reverse = True
            seeker.set_nexus(self.nexus)
            '''create context seeker stack item'''
            alt = MockAlternative(u"my", u"spoken", u"words")
            stack_seeker = StackItemSeeker(seeker, {"_node": alt})
            '''add it'''
            self.nexus.state.add(stack_seeker)

            if i == 0:
                self.assertEqual(mutable_string["value"], "db")
            else:
                self.assertEqual(mutable_string["value"], "bd")
Ejemplo n.º 6
0
 def test_defaulting(self):
     self.assertIn("align", self.noderule.mapping_actual())
     self.noderule.mapping_actual()["align"].execute()
     defaulter = NullAction()
     defaulter.set_nexus(self.nexus)
     ''' the noderule should default here and reset '''
     defaulter.execute()
     self.assertIn("align", self.noderule.mapping_actual())
Ejemplo n.º 7
0
def get_css_node():
    H = hintnode.HintNode
    css_sections = []
    css_sections.append(_get_background())
    css_sections.append(_get_border())
    css_sections.append(_get_box())
    css_sections.append(_get_font())
    css_sections.append(_get_box_model())
    css_sections.append(_get_text())
    css_sections.append(_get_column())
    css_sections.append(_get_speech())
    css_sections += _get_miscellaneous()

    return H("css", NullAction(), css_sections)
Ejemplo n.º 8
0
    def test_preserving_spoken_words(self):
        '''make fake RegisteredAction'''
        action = R(NullAction(), rspec="test")
        action.set_nexus(self.nexus)
        '''make fake StackItemRegisteredAction'''
        spoken = [u"my", u"spoken", u"words"]
        alt = MockAlternative(*spoken)
        sira1 = StackItemRegisteredAction(action, {"_node": alt})
        '''add it'''
        self.nexus.state.add(sira1)

        last_item = self.nexus.state.stack.list[
            len(self.nexus.state.stack.list) - 1]
        self.assertEqual(spoken, last_item.get_preserved())
Ejemplo n.º 9
0
    def test_list_pruning(self):
        '''make fake RegisteredAction'''
        action = R(NullAction(), rspec="test")
        action.set_nexus(self.nexus)

        for i in range(0, self.nexus.state.stack.max_list_size + 5):
            '''make fake StackItemRegisteredAction'''
            alt = MockAlternative(u"my", u"spoken", u"words")
            sira1 = StackItemRegisteredAction(action, {"_node": alt})
            '''add it'''
            self.nexus.state.add(sira1)

        self.assertEqual(len(self.nexus.state.stack.list),
                         self.nexus.state.stack.max_list_size)
Ejemplo n.º 10
0
class HistoryRule(SelfModifyingRule):
    def __init__(self, nexus):
        SelfModifyingRule.__init__(self)
        self.nexus = nexus

    pronunciation = "history"
    mapping = {"default sequence": NullAction()}

    def record_from_history(self):
        # save the list as it was when the command was spoken
        self.nexus.preserved = self.nexus.history[:]

        # format for display
        formatted = ""
        for t in self.nexus.preserved:
            for w in t:
                formatted += w.split("\\")[0] + "[w]"
            formatted += "[s]"

        # use a response window to get a spec and word sequences for the new macro
        h_launch.launch(settings.QTYPE_RECORDING, data=formatted)
        on_complete = AsynchronousAction.hmc_complete(
            lambda data: self.add_recorded_macro(data), self.nexus)
        AsynchronousAction([L(S(["cancel"], on_complete))],
                           time_in_seconds=0.5,
                           repetitions=300,
                           blocking=False).execute()

    def add_recorded_macro(self, data):
        spec = data["word"]

        word_sequences = []  # word_sequences is a list of lists of strings
        for i in data["selected_indices"]:
            # Convert from a tuple to a list because we may need to modify it.
            single_sequence = list(self.nexus.preserved[i])
            # clean the results
            for k in range(0, len(single_sequence)):
                if "\\" in single_sequence[k]:
                    single_sequence[k] = single_sequence[k].split("\\")[0]
            word_sequences.append(single_sequence)

        # clear the dictation cache
        self.nexus.preserved = None

        if spec != "" and len(word_sequences) > 0:
            if data["repeatable"]:
                spec += " [times <n>]"
            self.refresh(spec, word_sequences)

    def refresh(self, *args):
        '''args: spec, list of lists of strings'''

        # get mapping
        recorded_macros = utilities.load_toml_file(
            settings.SETTINGS["paths"]["RECORDED_MACROS_PATH"])
        if len(args) > 0:
            recorded_macros[args[0]] = args[1]
            utilities.save_toml_file(
                recorded_macros,
                settings.SETTINGS["paths"]["RECORDED_MACROS_PATH"])
        mapping = {}
        for spec in recorded_macros:
            # Create a copy of the string without Unicode characters.
            ascii_str = str(spec)
            sequences = recorded_macros[spec]
            delay = settings.SETTINGS["miscellaneous"][
                "history_playback_delay_secs"]
            # It appears that the associative string (ascii_str) must be ascii, but the sequences within Playback must be Unicode.
            mapping[ascii_str] = R(
                Playback([(sequence, delay) for sequence in sequences]),
                rdescript="Recorded Macro: " + ascii_str) * Repeat(extra="n")
        mapping["record from history"] = R(Function(self.record_from_history),
                                           rdescript="Record From History")
        mapping["delete recorded macros"] = R(
            Function(self.delete_recorded_macros),
            rdescript="Delete Recorded Macros")
        # reload with new mapping
        self.reset(mapping)

    def load_recorded_macros(self):
        self.refresh()

    def delete_recorded_macros(self):
        utilities.save_toml_file(
            {}, settings.SETTINGS["paths"]["RECORDED_MACROS_PATH"])
        self.refresh()
Ejemplo n.º 11
0
def _get_speech():
    _volume = [
        H("uri", Text("uri")),
        H("silent", Text("silent")),
        H("extra soft", Text("x-soft")),
        H("soft", Text("soft")),
        H("medium", Text("medium")),
        H("loud", Text("loud")),
        H("extra loud", Text("x-loud")),
        H("none", Text("none")),
        H("inherit", Text("inherit"))
    ]
    _pause_rest = [
        H("none", Text("none")),
        H("extra weak", Text("x-weak")),
        H("weak", Text("weak")),
        H("medium", Text("medium")),
        H("strong", Text("strong")),
        H("extra strong", Text("x-strong")),
        H("inherit", Text("inherit"))
    ]
    _pitch = [
        H("extra low", Text("x-low")),
        H("low", Text("low")),
        H("medium", Text("medium")),
        H("high", Text("high")),
        H("extra high", Text("x-high")),
        H("inherit", Text("inherit"))
    ]
    return H("speech", NullAction(), [
        H("cue", Text("cue"), [
            H("before", Text("-before: "), _volume),
            H("after", Text("-after: "), _volume)
        ]),
        H("mark", Text("mark"),
          [H("before", Text("-before: ")),
           H("after", Text("-after"))]),
        H("pause", Text("pause"), [
            H("before", Text("-before: "), _pause_rest),
            H("after", Text("-after: "), _pause_rest)
        ]),
        H("rest", Text("rest"), [
            H("before", Text("-before: "), _pause_rest),
            H("after", Text("-after: "), _pause_rest)
        ]),
        H("speak", Text("speak: "), [
            H("none", Text("none")),
            H("normal", Text("normal")),
            H("spell out", Text("spell-out")),
            H("digits", Text("digits")),
            H("literal punctuation", Text("literal-punctuation")),
            H("no punctuation", Text("no-punctuation")),
            H("inherit", Text("inherit"))
        ]),
        H("voice", Text("voice"), [
            H("balance", Text("-balance: "), [
                H("left", Text("left")),
                H("center", Text("center")),
                H("right", Text("right")),
                H("leftwards", Text("leftwards")),
                H("rightwards", Text("rightwards")),
                H("inherit", Text("inherit"))
            ]),
            H("duration", Text("-duration: ")),
            H("family", Text("-family: "), [H("inherit", Text("inherit"))]),
            H("rate", Text("-rate: "), [
                H("extra low", Text("x-low")),
                H("low", Text("low")),
                H("medium", Text("medium")),
                H("fast", Text("fast")),
                H("next for fast", Text("x-fast")),
                H("inherit", Text("inherit")),
            ]),
            H("pitch", Text("-pitch: "), _pitch),
            H("pitch range", Text("-pitch-range: "), _pitch),
            H("stress", Text("-stress: "), [
                H("strong", Text("strong")),
                H("moderate", Text("moderate")),
                H("none", Text("none")),
                H("reduced", Text("reduced")),
                H("inherit", Text("inherit"))
            ]),
            H("volume", Text("-volume: "), _volume)
        ]),
    ])
Ejemplo n.º 12
0
def _get_box_model(
):  # display can be optimized by doing more nesting, this whole section is to be moved somewhere else
    H = hintnode.HintNode
    _auto = [H("auto", Text("auto"))]
    _height = H("height", Text("height: "), _auto)
    _width = H("width", Text("width: "), _auto)
    _sides = [
        H("top", Text("-top: "), _auto),
        H("bottom", Text("-bottom: "), _auto),
        H("left", Text("-left: "), _auto),
        H("right", Text("-right: "), _auto)
    ]
    _overflow = [
        H("visible", Text("visible")),
        H("hidden", Text("hidden")),
        H("scroll", Text("scroll")),
        H("auto", Text("auto")),
        H("no display", Text("no-display")),
        H("no content", Text("no-content")),
    ]
    return H("box model", NullAction(), [
        H("clear", Text("clear: "), [
            H("left", Text("left")),
            H("right", Text("right")),
            H("both", Text("both")),
            H("none", Text("none"))
        ]),
        H("display", Text("display: "), [
            H("none", Text("none")),
            H("block", Text("block")),
            H("compact", Text("compact")),
            H("table", Text("table")),
            H("inline", Text("inline"),
              [H("block", Text("-block")),
               H("table", Text("-table"))]),
            H("run in", Text("run-in")),
            H("list item", Text("list-item")),
            H("table", Text("table"), [
                H("row", Text("-row"), [H("group", Text("-group"))]),
                H("footer", Text("-footer"), [H("group", Text("-group"))]),
                H("column", Text("-column"), [H("group", Text("-group"))]),
                H("cell", Text("-cell")),
                H("caption", Text("-caption"))
            ]),
            H("ruby", Text("ruby"), [
                H("base", Text("-base"), [H("group", Text("-group"))]),
                H("text", Text("-text"), [H("group", Text("-group"))])
            ])
        ]),
        H("float", Text("float: "), [
            H("left", Text("left")),
            H("right", Text("right")),
            H("none", Text("none"))
        ]), _height, _width,
        H("max", Text("max-"), [_height, _width]),
        H("min", Text("min-"), [_height, _width]),
        H("margin", Text("margin"), _sides),
        H("padding", Text("padding"), _sides),
        H("marquee", Text("marquee"), [
            H("direction", Text("-direction: "),
              [H("forward", Text("forward")),
               H("reverse", Text("reverse"))]),
            H("loop", Text("-loop: "), [H("infinite", Text("infinite"))]),
            H("play count", Text("-play-count: "),
              [H("infinite", Text("infinite"))]),
            H("speed", Text("-speed: "), [
                H("slow", Text("slow")),
                H("normal", Text("normal")),
                H("fast", Text("fast"))
            ]),
            H("style", Text("-style: "), [
                H("scroll", Text("scroll")),
                H("slide", Text("slide")),
                H("alternate", Text("alternate"))
            ])
        ]),
        H("overflow", Text("overflow: "), _overflow),
        H("overflow X", Text("overflow-x: "), _overflow),
        H("overflow Y", Text("overflow-y: "), _overflow),
        H("overflow style", Text("overflow-style: "), [
            H("auto", Text("auto")),
            H("marquee line", Text("marquee-line")),
            H("marquee block", Text("marquee-block"))
        ]),
        H("rotation", Text("rotation: "), [H("angle", Text("ANGLE"))]),
        H("rotation point", Text("rotation-point: ")),
        H("visibility", Text("visibility: "), [
            H("visible", Text("visible")),
            H("hidden", Text("hidden")),
            H("collapse", Text("collapse"))
        ])
    ])
Ejemplo n.º 13
0
    def test_use_spoken_words_or_rspec(self):
        '''seekers can take the spoken words or rspecs
        of their trigger actions and feed them to the
        function objects of their ContextSets'''
        '''make triggers for context seekers
        (2 forward, 2 backward / 2 spoken, 2 rspec)'''
        action1 = NullAction(rspec="alpha")
        action2 = NullAction(rspec="_")
        action3 = NullAction(rspec="charlie")
        action4 = NullAction(rspec="_")
        action1.set_nexus(self.nexus)
        action2.set_nexus(self.nexus)
        action3.set_nexus(self.nexus)
        action4.set_nexus(self.nexus)
        alt = MockAlternative(u"_")
        spec1 = [u"here", u"are", u"words"]
        spec2 = [u"some", u"more", u"words"]
        sira1 = StackItemRegisteredAction(action1, {"_node": alt})
        sira2 = StackItemRegisteredAction(action2,
                                          {"_node": MockAlternative(*spec1)})
        sira3 = StackItemRegisteredAction(action3, {"_node": alt})
        sira4 = StackItemRegisteredAction(action4,
                                          {"_node": MockAlternative(*spec2)})

        #

        mutable_integer = {"value": 0}

        def increment():
            mutable_integer["value"] += 1

        #
        def _1(params):
            if params == "alpha": increment()

        def _2(params):
            if params == spec1: increment()

        def _3(params):
            if params == "charlie": increment()

        def _4(params):
            if params == spec2: increment()

        '''make seekers'''
        back_seeker1 = ContextSeeker(
            back=[L(S(["alpha"], _1, parameters="_", use_rspec=True))],
            rspec="_")
        back_seeker2 = ContextSeeker(
            back=[L(S(["_"], _2, parameters=["_"], use_spoken=True))],
            rspec="_")
        forward_seeker1 = ContextSeeker(
            forward=[L(S(["_"], _3, parameters="_", use_rspec=True))],
            rspec="_")
        forward_seeker2 = ContextSeeker(
            forward=[L(S(["delta"], _4, parameters=["_"], use_spoken=True))],
            rspec="_")
        back_seeker1.set_nexus(self.nexus)
        back_seeker2.set_nexus(self.nexus)
        forward_seeker1.set_nexus(self.nexus)
        forward_seeker2.set_nexus(self.nexus)
        '''create seeker stack items'''
        stack_seeker_b1 = StackItemSeeker(back_seeker1, {"_node": alt})
        stack_seeker_b2 = StackItemSeeker(back_seeker2, {"_node": alt})
        stack_seeker_f1 = StackItemSeeker(forward_seeker1, {"_node": alt})
        stack_seeker_f2 = StackItemSeeker(forward_seeker2, {"_node": alt})

        #
        '''trigger the first backward seeker; uses rspec ("alpha") '''
        self.nexus.state.add(sira1)
        self.nexus.state.add(stack_seeker_b1)
        self.assertEqual(mutable_integer["value"], 1)
        '''trigger the second backward seeker; uses spoken words (spec1) '''
        self.nexus.state.add(sira2)
        self.nexus.state.add(stack_seeker_b2)
        self.assertEqual(mutable_integer["value"], 2)
        '''trigger the first forward seeker; uses rspec ("charlie") '''
        self.nexus.state.add(stack_seeker_f1)
        self.nexus.state.add(sira3)
        self.assertEqual(mutable_integer["value"], 3)
        '''trigger the first forward seeker; uses spoken words (spec2) '''
        self.nexus.state.add(stack_seeker_f2)
        self.nexus.state.add(sira4)
        self.assertEqual(mutable_integer["value"], 4)
Ejemplo n.º 14
0
    def test_actions_cleaned(self):
        '''these test functions should stay in sync with the clean methods for each stack action'''
        def registered_is_clean(r):
            return r.dragonfly_data is None and r.base is None

        def seeker_is_clean(s):
            result = True
            levels = []
            if s.back is not None: levels += s.back
            if s.forward is not None: levels += s.forward
            for context_level in levels:
                result &= context_level.dragonfly_data is None
            return result

        def asynchronous_is_clean(a):
            return a.closure is None

        '''mock words being the same doesn't matter for this test, or most tests'''
        alt = MockAlternative(u"my", u"spoken", u"words")
        '''make fake NullActions'''
        action1 = NullAction(rspec="barkley")
        action2 = NullAction(rspec="gaiden")
        action3 = NullAction(rspec="is")
        action4 = NullAction(rspec="awesome")
        action1.set_nexus(self.nexus)
        action2.set_nexus(self.nexus)
        action3.set_nexus(self.nexus)
        action4.set_nexus(self.nexus)
        '''make fake StackItemRegisteredActions'''
        sira1 = StackItemRegisteredAction(action1, {"_node": alt})
        sira2 = StackItemRegisteredAction(action2, {"_node": alt})
        sira3 = StackItemRegisteredAction(action3, {"_node": alt})
        sira4 = StackItemRegisteredAction(action4, {"_node": alt})
        '''should not be clean before it's executed'''
        self.assertFalse(registered_is_clean(sira1))
        '''add first one for backward seeker'''
        self.nexus.state.add(sira1)
        '''should be clean as soon as it's executed'''
        self.assertTrue(registered_is_clean(sira1))
        '''make backward seeker'''
        back_seeker = ContextSeeker(
            back=[L(S(["minecraft"], Function(lambda: None)))])
        back_seeker.set_nexus(self.nexus)
        '''create backward seeker stack item'''
        stack_seeker = StackItemSeeker(back_seeker, {"_node": alt})
        '''add it'''
        self.nexus.state.add(stack_seeker)
        '''levels should be clean as soon as it's executed'''
        self.assertTrue(
            registered_is_clean(stack_seeker)
            and seeker_is_clean(stack_seeker))

        #
        '''make forward seeker'''
        forward_seeker = ContextSeeker(forward=[
            L(S(["cave"], Function(lambda: None))),
            L(S(["story"], Function(lambda: None)))
        ])
        forward_seeker.set_nexus(self.nexus)
        '''create context seeker stack item'''
        stack_seeker2 = StackItemSeeker(forward_seeker, {"_node": alt})
        '''add it'''
        self.nexus.state.add(stack_seeker2)

        self.nexus.state.add(sira2)
        '''levels should not be clean before seeker is executed'''
        self.assertFalse(
            registered_is_clean(stack_seeker2)
            or seeker_is_clean(stack_seeker2))

        self.nexus.state.add(sira3)
        '''levels should be clean as soon as it's executed'''
        self.assertTrue(
            registered_is_clean(stack_seeker2)
            and seeker_is_clean(stack_seeker2))

        #
        '''make asynchronous action'''
        asynchronous = AsynchronousAction(
            [L(S(["eternal", "daughter", "awesome"], lambda: None))],
            blocking=False)
        asynchronous.set_nexus(self.nexus)
        '''make StackItemAsynchronous'''
        sia1 = StackItemAsynchronous(asynchronous, {"_node": alt})
        '''add it'''
        self.nexus.state.add(sia1)
        '''closure should not be clean before asynchronous is executed'''
        self.assertFalse(
            registered_is_clean(sia1) or seeker_is_clean(sia1)
            or asynchronous_is_clean(sia1))

        self.nexus.state.add(sira4)
        '''closure should be clean after asynchronous is executed'''
        self.assertTrue(
            registered_is_clean(sia1) and seeker_is_clean(sia1)
            and asynchronous_is_clean(sia1))