def parse_input_data(self, node): data = DotDict() try: for nod in self._get_input_nodes(node): data.update(self._parse_input_node(nod)) except Exception as e: LOG.exception("Error while processing node: %s" % node) return data
def test_simple(): wfc = workflow_connector() session = MockSessionStore() req = make_request(session) resp = DotDict() wfc.on_post(req, resp=resp, wf_name='simple_login') assert req['context']['result']['forms'] == get_form('student_login_form') req= make_request(session, cmd='do', login_crd={'username':'******', 'password':'******'}) pprint(session) wfc.on_post(req, resp=DotDict(), wf_name='simple_login') # print(session) # print(req) assert session['user']['username'] == 'user' assert req['context']['result']['dashboard'] == 'Dashboard'
def __init__(self): self.use_compact_serializer = True if self.use_compact_serializer: self.serialize_workflow = self.compact_serialize_workflow self.deserialize_workflow = self.compact_deserialize_workflow self.current = DotDict({'request':{}, 'task_data': {}}) self.activities = {} self.workflow = BpmnWorkflow self.workflow_spec = WorkflowSpec
class ZEngine(object): """ """ WORKFLOW_DIRECTORY = '' # relative or absolute directory path ACTIVITY_MODULES_PATH = '' # python import path def __init__(self): self.use_compact_serializer = True if self.use_compact_serializer: self.serialize_workflow = self.compact_serialize_workflow self.deserialize_workflow = self.compact_deserialize_workflow self.current = DotDict({'request':{}, 'task_data': {}}) self.activities = {} self.workflow = BpmnWorkflow self.workflow_spec = WorkflowSpec def _load_workflow(self): serialized_wf = self.load_workflow(self.current.workflow_name) if serialized_wf: return self.deserialize_workflow(serialized_wf) def deserialize_workflow(self, serialized_wf): return BpmnWorkflow.deserialize(DictionarySerializer(), serialized_wf) def compact_deserialize_workflow(self, serialized_wf): return CompactWorkflowSerializer().deserialize_workflow(serialized_wf, workflow_spec=self.workflow.spec) def serialize_workflow(self): return self.workflow.serialize(serializer=DictionarySerializer()) def compact_serialize_workflow(self): self.workflow.refresh_waiting_tasks() return CompactWorkflowSerializer().serialize_workflow(self.workflow, include_spec=False) def create_workflow(self): # wf_pkg_file = self.get_worfklow_spec() # self.workflow_spec = BpmnSerializer().deserialize_workflow_spec(wf_pkg_file) self.workflow_spec = self.get_worfklow_spec() return BpmnWorkflow(self.workflow_spec) def load_or_create_workflow(self): """ Tries to load the previously serialized (and saved) workflow Creates a new one if it can't """ self.workflow = self._load_workflow() or self.create_workflow() def get_worfklow_spec(self): """ :return: workflow spec package """ # FIXME: this is a very ugly workaround if isinstance(self.WORKFLOW_DIRECTORY, (str, unicode)): wfdir = self.WORKFLOW_DIRECTORY else: wfdir = self.WORKFLOW_DIRECTORY[0] # path = "{}/{}.zip".format(wfdir, self.current.workflow_name) # return open(path) path = "{}/{}.bpmn".format(wfdir, self.current.workflow_name) return BpmnSerializer().deserialize_workflow_spec( InMemoryPackager.package_in_memory(self.current.workflow_name, path)) def _save_workflow(self): self.save_workflow(self.current.workflow_name, self.serialize_workflow()) def save_workflow(self, workflow_name, serilized_workflow_instance): """ override this with your own persisntence method. :return: """ def load_workflow(self, workflow_name): """ override this method to load the previously saved workflow instance :return: serialized workflow instance """ return '' def set_current(self, **kwargs): """ workflow_name should be given in kwargs :param kwargs: :return: """ self.current.update(kwargs) if 'task' in kwargs: task = kwargs['task'] self.current.task_type = task.task_spec.__class__.__name__ self.current.spec = task.task_spec self.current.name = task.get_name() def complete_current_task(self): self.workflow.complete_task_from_id(self.current.task.id) def run(self): while 1: for task in self.workflow.get_tasks(state=Task.READY): self.set_current(task=task) self.current['task'].data.update(self.current['task_data']) print("TASK >> %s" % self.current.name, self.current.task.data, "TYPE", self.current.task_type) if hasattr(self.current['spec'], 'service_class'): print("RUN ACTIVITY: %s, %s" % (self.current['spec'].service_class, self.current)) self.run_activity(self.current['spec'].service_class) else: print('NO ACTIVITY!!') self.complete_current_task() if not self.current.task_type.startswith('Start'): self._save_workflow() self.cleanup() if self.current.task_type == 'UserTask' or self.current.task_type.startswith('End'): break def run_activity(self, activity): """ :param activity: :return: """ if activity not in self.activities: mod_parts = activity.split('.') module = ".".join([self.ACTIVITY_MODULES_PATH] + mod_parts[:-1]) method = mod_parts[-1] self.activities[activity] = getattr(import_module(module), method) self.activities[activity](self.current) # def process_activities(self): # if 'activities' in self.current.spec.data: # for cb in self.current.spec.data.activities: # self.run_activity(cb) def cleanup(self): """ this method will be called after each run cycle override this if you need some codes to be called after WF engine finished it's tasks and activities :return: None """ pass
def make_request(session_obj, **kwargs): req_dict = DotDict({'context': {'data': {}, 'result': {}}, 'session': session_obj}) req_dict['context']['data'].update(kwargs) return DotDict(req_dict)