Beispiel #1
0
 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'
Beispiel #3
0
 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
Beispiel #4
0
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)