I'm using conditional transitioning in the nested machine. Unfortunately, the condition method has no access to the class attribute self._error. So I have to pass the attribute to the triggering method. This solution work, but I have to take care to pass the correct attribute to the triggering method.
I would like to use another solution, where it works without the passing parameter, but I don't know if it is possible with pytransitions to implement it.
GenericMachine is an abstract class defining basic states and configuration.
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 defines the highest machine in the hierarchy and instantiates 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)
The magic happens here in NestedMachine. Condition is resolved in the error method. But the method can see only the initial value of the self._error attribute, so the change in the initial state is not reflected.
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()
Test case expects to finish in nested_error, but it ends in nested_initial as the "go" event is not executed
def main():
    machine = MainMachine()
    machine.go()
    assert machine.state == "nested_error"
if __name__ == "__main__":
    main()
The workaround is to pass the attribute to the triggering function, then it works as expected.
   
    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)
And probably the best solution would be to use a property decorator than I can use the error property not only for transitions.
    @property
    def error(self):
        return self._error
    def entry_initial(self, event_data):
        self._error = True
        event_data.model.go()