1

我在嵌套机器中使用条件转换。不幸的是,条件方法无法访问类属性self._error。所以我必须将属性传递给触发方法。该解决方案有效,但我必须注意将正确的属性传递给触发方法。

我想使用另一种解决方案,它在没有传递参数的情况下工作,但我不知道是否可以使用 pytransitions 来实现它。

GenericMachine是定义基本状态和配置的抽象类。

from transitions.extensions import HierarchicalMachine

class GenericMachine(HierarchicalMachine):
    def __init__(self, states, transitions, model=None):
        generic_states = [
            {"name": "initial", "on_enter": self.entry_initial},
            {"name": "done"},
        ]
        states += generic_states
        super().__init__(
            states=states,
            transitions=transitions,
            model=model,
            send_event=True,
            queued=False,
        )

    def entry_initial(self, event_data):
        raise NotImplementedError

MainMachine定义层次结构中的最高机器并实例化NestedMachine

class MainMachine(GenericMachine):
    def __init__(self):
        nested = NestedMachine()
        remap = {"done": "done"}
        states = [
            {"name": "nested", "children": nested, "remap": remap},
        ]
        transitions = [
            ["go", "initial", "nested"],
        ]
        super().__init__(states, transitions, model=self)

魔法发生在这里NestedMachine。条件在error方法中得到解决。但是该方法只能看到self._error属性的初始值,所以initial状态的变化并没有体现出来。

class NestedMachine(GenericMachine):
    def __init__(self):

        self._error = None

        states = [
            {"name": "error"},
        ]

        transitions = [
            {
                "trigger": "go",
                "source": "initial",
                "dest": "error",
                "conditions": self.error,
            },
            {
                "trigger": "go",
                "source": "initial",
                "dest": "done",
                "unless": self.error,
            },
        ]

        super().__init__(states, transitions)

     def error(self, event_data):
        return self._error

     def entry_initial(self, event_data):
        self._error = True
        event_data.model.go()

测试用例预计在 结束nested_error,但nested_initial"go"事件未执行时结束

def main():
    machine = MainMachine()
    machine.go()
    assert machine.state == "nested_error"

if __name__ == "__main__":
    main()

解决方法是将属性传递给触发函数,然后它按预期工作。

   
    def error(self, event_data):
        error = event_data.kwargs["error"]
        return error

    def entry_initial(self, event_data):
        self._error = True
        event_data.model.go(error=self._error)

并且可能最好的解决方案是使用属性装饰器,而我error不仅可以将属性用于转换。

    @property
    def error(self):
        return self._error

    def entry_initial(self, event_data):
        self._error = True
        event_data.model.go()
4

0 回答 0