from db import fsm, FsmTransition import inspect from handlers.enums import workflow_status_sorting class StateMap(object): def __init__(self): self.states = {} def add_state(self, source, target): if source and target: if self.states.get(source): value = self.states.get(source) value.append(target) self.states[source] = value else: self.states[source] = [target] self.states[source].sort(key=workflow_status_sorting) def get_target(self, source): return self.states.get(source) def get_all_states(self): sources_list = list(self.states.keys()) targets = set([item for sublist in self.states.values() for item in sublist]) for target in targets: if target not in sources_list: sources_list.append(target) sources_list.sort(key=workflow_status_sorting) return sources_list state_map = StateMap() class FSMMetaChild(fsm.meta.FSMMeta): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.state_map = state_map def add_state(self, source, target): self.state_map.add_state(source, target) def get_target(self, source): return self.state_map.get_target(source) def get_map(self): return self.state_map.states def get_sources_list(cls): transitions = [transition for transition in cls.__dict__.values() if isinstance(transition, FsmTransition)] sources = [list(transition.meta.sources)[0] for transition in transitions] return sources def transition(source="*", target=None, conditions=(), manual=True): def inner_transition(func): meta = getattr(func, '_flask_fsm', None) if not meta: if inspect.isfunction(func): meta = FSMMetaChild(source, target, conditions, (), fsm.bound.BoundFSMFunction) setattr(func, '_flask_fsm', meta) if manual: if isinstance(source, (list, tuple, set)): for item in source: func._flask_fsm.add_state(source=item, target=target) else: func._flask_fsm.add_state(source=source, target=target) elif inspect.isclass(func): meta = FSMMetaChild(source, target, conditions, (), fsm.bound.BoundFSMClass) setattr(func, '_flask_fsm', meta) if manual: sources = get_sources_list(func) for item in sources: func._flask_fsm.add_state(source=item, target=target) return FsmTransition(meta, func) return inner_transition