Пример #1
0
    def next_task(self):
        """Returns the next task that should be completed
        even if there are parallel tasks and multiple options are
        available.
        If the workflow is complete
        it will return the final end task.
        """

        # If the whole blessed mess is done, return the end_event task in the tree
        if self.bpmn_workflow.is_completed():
            for task in SpiffTask.Iterator(self.bpmn_workflow.task_tree,
                                           SpiffTask.ANY_MASK):
                if isinstance(task.task_spec, EndEvent):
                    return task

        # If there are ready tasks to complete, return the next ready task, but return the one
        # in the active parallel path if possible.
        ready_tasks = self.bpmn_workflow.get_tasks(SpiffTask.READY)
        if len(ready_tasks) > 0:
            for task in ready_tasks:
                if task.parent == self.bpmn_workflow.last_task:
                    return task
            return ready_tasks[0]

        # If there are no ready tasks, but the thing isn't complete yet, find the first non-complete task
        # and return that
        next_task = None
        for task in SpiffTask.Iterator(self.bpmn_workflow.task_tree,
                                       SpiffTask.NOT_FINISHED_MASK):
            next_task = task
        return next_task
Пример #2
0
    def runWorkflow(self, wf_spec, xml_filename):
        taken_path = []
        for name in wf_spec.task_specs:
            wf_spec.task_specs[name].reached_event.connect(on_reached_cb, taken_path)
            wf_spec.task_specs[name].completed_event.connect(on_complete_cb, taken_path)

        # Execute all tasks within the Workflow
        workflow = Workflow(wf_spec)
        self.assert_(not workflow.is_completed(), 'Workflow is complete before start')
        try:
            workflow.complete_all(False)
        except:
            workflow.task_tree.dump()
            raise

        #workflow.task_tree.dump()
        self.assert_(workflow.is_completed(),
                     'complete_all() returned, but workflow is not complete\n'
                   + workflow.task_tree.get_dump())

        # Make sure that there are no waiting tasks left in the tree.
        for thetask in Task.Iterator(workflow.task_tree, Task.READY):
            workflow.task_tree.dump()
            raise Exception('Task with state READY: %s' % thetask.name)

        # Check whether the correct route was taken.
        filename = xml_filename + '.path'
        if os.path.exists(filename):
            file     = open(filename, 'r')
            expected = file.read()
            file.close()
            taken_path = '\n'.join(taken_path) + '\n'
            error      = '%s:\n'       % name
            error     += 'Expected:\n'
            error     += '%s\n'        % expected
            error     += 'but got:\n'
            error     += '%s\n'        % taken_path
            self.assert_(taken_path == expected, error)

        # Check attribute availibility.
        filename = xml_filename + '.data'
        if os.path.exists(filename):
            file     = open(filename, 'r')
            expected = file.read()
            file.close()
            result   = workflow.get_attribute('data', '')
            error    = '%s:\n'       % name
            error   += 'Expected:\n'
            error   += '%s\n'        % expected
            error   += 'but got:\n'
            error   += '%s\n'        % result
            self.assert_(result == expected, error)
Пример #3
0
def run_workflow(test, wf_spec, expected_path, expected_data, max_tries=1):
    # Execute all tasks within the Workflow.
    taken_path = track_workflow(wf_spec)
    workflow = Workflow(wf_spec)
    test.assert_(not workflow.is_completed(),
                 'Workflow is complete before start')
    try:
        # We allow the workflow to require a maximum of 5 seconds to
        # complete, to allow for testing long running tasks.
        for i in range(10):
            workflow.complete_all(False)
            if workflow.is_completed():
                break
            time.sleep(0.5)
    except:
        workflow.task_tree.dump()
        raise

    #workflow.task_tree.dump()
    complete = False
    while max_tries > 0 and complete is False:
        max_tries -= 1
        complete = workflow.is_completed()
    test.assert_(
        complete, 'complete_all() returned, but workflow is not complete\n' +
        workflow.task_tree.get_dump())

    # Make sure that there are no waiting tasks left in the tree.
    for thetask in Task.Iterator(workflow.task_tree, Task.READY):
        workflow.task_tree.dump()
        raise Exception('Task with state READY: %s' % thetask.name)

    # Check whether the correct route was taken.
    if expected_path is not None:
        taken_path = '\n'.join(taken_path) + '\n'
        error = 'Expected:\n'
        error += '%s\n' % expected_path
        error += 'but got:\n'
        error += '%s\n' % taken_path
        test.assert_(taken_path == expected_path, error)

    # Check attribute availibility.
    if expected_data is not None:
        result = workflow.get_attribute('data', '')
        error = 'Expected:\n'
        error += '%s\n' % expected_data
        error += 'but got:\n'
        error += '%s\n' % result
        test.assert_(result == expected_data, error)

    return workflow
Пример #4
0
    def testTree(self):
        # Build a tree.
        spec     = WorkflowSpec()
        workflow = MockWorkflow()
        task1    = Simple(spec, 'Simple 1')
        task2    = Simple(spec, 'Simple 2')
        task3    = Simple(spec, 'Simple 3')
        task4    = Simple(spec, 'Simple 4')
        task5    = Simple(spec, 'Simple 5')
        task6    = Simple(spec, 'Simple 6')
        task7    = Simple(spec, 'Simple 7')
        task8    = Simple(spec, 'Simple 8')
        task9    = Simple(spec, 'Simple 9')
        root     = Task(workflow, task1)
        c1       = root._add_child(task2)
        c11      = c1._add_child(task3)
        c111     = c11._add_child(task4)
        c1111    = Task(workflow, task5, c111)
        c112     = Task(workflow, task6, c11)
        c12      = Task(workflow, task7, c1)
        c2       = Task(workflow, task8, root)
        c3       = Task(workflow, task9, root)
        c3.state = Task.COMPLETED

        # Check whether the tree is built properly.
        expected = """!/0: Task of Simple 1 State: MAYBE Children: 3
  !/0: Task of Simple 2 State: MAYBE Children: 2
    !/0: Task of Simple 3 State: MAYBE Children: 2
      !/0: Task of Simple 4 State: MAYBE Children: 1
        !/0: Task of Simple 5 State: MAYBE Children: 0
      !/0: Task of Simple 6 State: MAYBE Children: 0
    !/0: Task of Simple 7 State: MAYBE Children: 0
  !/0: Task of Simple 8 State: MAYBE Children: 0
  !/0: Task of Simple 9 State: COMPLETED Children: 0"""
        expected = re.compile(expected.replace('!', r'([0-9a-f\-]+)'))
        self.assert_(expected.match(root.get_dump()),
                     'Expected:\n' + repr(expected.pattern) + '\n' + \
                     'but got:\n'  + repr(root.get_dump()))

        # Now remove one line from the expected output for testing the
        # filtered iterator.
        expected2 = ''
        for line in expected.pattern.split('\n'):
            if line.find('Simple 9') >= 0:
                continue
            expected2 += line.lstrip() + '\n'
        expected2 = re.compile(expected2)

        # Run the iterator test.
        result = ''
        for thetask in Task.Iterator(root, Task.MAYBE):
            result += thetask.get_dump(0, False) + '\n'
        self.assert_(expected2.match(result),
                     'Expected:\n' + repr(expected2.pattern) + '\n' + \
                     'but got:\n'  + repr(result))
Пример #5
0
    def testTree(self):
        # Build a tree.
        spec     = WorkflowSpec()
        workflow = MockWorkflow()
        task1    = Simple(spec, 'Simple 1')
        task2    = Simple(spec, 'Simple 2')
        task3    = Simple(spec, 'Simple 3')
        task4    = Simple(spec, 'Simple 4')
        task5    = Simple(spec, 'Simple 5')
        task6    = Simple(spec, 'Simple 6')
        task7    = Simple(spec, 'Simple 7')
        task8    = Simple(spec, 'Simple 8')
        task9    = Simple(spec, 'Simple 9')
        root     = Task(workflow, task1)
        c1       = root._add_child(task2)
        c11      = c1._add_child(task3)
        c111     = c11._add_child(task4)
        c1111    = Task(workflow, task5, c111)
        c112     = Task(workflow, task6, c11)
        c12      = Task(workflow, task7, c1)
        c2       = Task(workflow, task8, root)
        c3       = Task(workflow, task9, root)
        c3.state = Task.COMPLETED

        # Check whether the tree is built properly.
        expected = """1/0: Task of Simple 1 State: FUTURE Children: 3
  2/0: Task of Simple 2 State: FUTURE Children: 2
    3/0: Task of Simple 3 State: FUTURE Children: 2
      4/0: Task of Simple 4 State: FUTURE Children: 1
        5/0: Task of Simple 5 State: FUTURE Children: 0
      6/0: Task of Simple 6 State: FUTURE Children: 0
    7/0: Task of Simple 7 State: FUTURE Children: 0
  8/0: Task of Simple 8 State: FUTURE Children: 0
  9/0: Task of Simple 9 State: COMPLETED Children: 0"""
        self.assert_(expected == root.get_dump(),
                     'Expected:\n' + repr(expected) + '\n' + \
                     'but got:\n'  + repr(root.get_dump()))

        # Now remove one line from the expected output for testing the
        # filtered iterator.
        expected2 = ''
        for line in expected.split('\n'):
            if line.find('Simple 9') >= 0:
                continue
            expected2 += line.lstrip() + '\n'

        # Run the iterator test.
        result = ''
        for thetask in Task.Iterator(root, Task.FUTURE):
            result += thetask.get_dump(0, False) + '\n'
        self.assert_(expected2 == result,
                     'Expected:\n' + expected2 + '\n' + \
                     'but got:\n'  + result)
Пример #6
0
def run_workflow(test, wf_spec, expected_path, expected_data, workflow=None):
    # Execute all tasks within the Workflow.
    if workflow is None:
        taken_path = track_workflow(wf_spec)
        workflow = Workflow(wf_spec)
    else:
        taken_path = track_workflow(workflow.spec)

    test.assertFalse(workflow.is_completed())
    try:
        # We allow the workflow to require a maximum of 5 seconds to
        # complete, to allow for testing long running tasks.
        for i in range(10):
            workflow.complete_all(False)
            if workflow.is_completed():
                break
            time.sleep(0.5)
    except:
        workflow.task_tree.dump()
        raise

    # workflow.task_tree.dump()
    test.assertTrue(workflow.is_completed(), workflow.task_tree.get_dump())

    # Make sure that there are no waiting tasks left in the tree.
    for thetask in Task.Iterator(workflow.task_tree, Task.READY):
        workflow.task_tree.dump()
        raise Exception('Task with state READY: %s' % thetask.name)

    # Check whether the correct route was taken.
    if expected_path is not None:
        taken_path = '\n'.join(taken_path) + '\n'
        test.assertEqual(taken_path, expected_path)

    # Check data availibility.
    if expected_data is not None:
        result = workflow.get_data('data', '')
        test.assertIn(result, expected_data)

    return workflow
Пример #7
0
    def testTree(self):
        # Build a tree.
        spec = WorkflowSpec()
        workflow = MockWorkflow()
        task1 = Simple(spec, 'Simple 1')
        task2 = Simple(spec, 'Simple 2')
        task3 = Simple(spec, 'Simple 3')
        task4 = Simple(spec, 'Simple 4')
        task5 = Simple(spec, 'Simple 5')
        task6 = Simple(spec, 'Simple 6')
        task7 = Simple(spec, 'Simple 7')
        task8 = Simple(spec, 'Simple 8')
        task9 = Simple(spec, 'Simple 9')
        root = Task(workflow, task1)
        c1 = root._add_child(task2)
        c11 = c1._add_child(task3)
        c111 = c11._add_child(task4)
        c1111 = Task(workflow, task5, c111)
        c112 = Task(workflow, task6, c11)
        c12 = Task(workflow, task7, c1)
        c2 = Task(workflow, task8, root)
        c3 = Task(workflow, task9, root)
        c3.state = Task.COMPLETED

        # Check whether the tree is built properly.
        expected = """1/0: Task of Simple 1 State: FUTURE Children: 3
  2/0: Task of Simple 2 State: FUTURE Children: 2
    3/0: Task of Simple 3 State: FUTURE Children: 2
      4/0: Task of Simple 4 State: FUTURE Children: 1
        5/0: Task of Simple 5 State: FUTURE Children: 0
      6/0: Task of Simple 6 State: FUTURE Children: 0
    7/0: Task of Simple 7 State: FUTURE Children: 0
  8/0: Task of Simple 8 State: FUTURE Children: 0
  9/0: Task of Simple 9 State: COMPLETED Children: 0"""
        self.assert_(expected == root.get_dump(),
                     'Expected:\n' + repr(expected) + '\n' + \
                     'but got:\n'  + repr(root.get_dump()))

        # Now remove one line from the expected output for testing the
        # filtered iterator.
        expected2 = ''
        for line in expected.split('\n'):
            if line.find('Simple 9') >= 0:
                continue
            expected2 += line.lstrip() + '\n'

        # Run the iterator test.
        result = ''
        for thetask in Task.Iterator(root, Task.FUTURE):
            result += thetask.get_dump(0, False) + '\n'
        self.assert_(expected2 == result,
                     'Expected:\n' + expected2 + '\n' + \
                     'but got:\n'  + result)
Пример #8
0
    def testTree(self):
        # Build a tree.
        spec     = WorkflowSpec()
        workflow = MockWorkflow()
        task1    = Simple(spec, 'Simple 1')
        task2    = Simple(spec, 'Simple 2')
        task3    = Simple(spec, 'Simple 3')
        task4    = Simple(spec, 'Simple 4')
        task5    = Simple(spec, 'Simple 5')
        task6    = Simple(spec, 'Simple 6')
        task7    = Simple(spec, 'Simple 7')
        task8    = Simple(spec, 'Simple 8')
        task9    = Simple(spec, 'Simple 9')
        root     = Task(workflow, task1)
        c1       = root._add_child(task2)
        c11      = c1._add_child(task3)
        c111     = c11._add_child(task4)
        c1111    = Task(workflow, task5, c111)
        c112     = Task(workflow, task6, c11)
        c12      = Task(workflow, task7, c1)
        c2       = Task(workflow, task8, root)
        c3       = Task(workflow, task9, root)
        c3.state = Task.COMPLETED

        # Check whether the tree is built properly.
        expected = """!/0: Task of Simple 1 State: MAYBE Children: 3
  !/0: Task of Simple 2 State: MAYBE Children: 2
    !/0: Task of Simple 3 State: MAYBE Children: 2
      !/0: Task of Simple 4 State: MAYBE Children: 1
        !/0: Task of Simple 5 State: MAYBE Children: 0
      !/0: Task of Simple 6 State: MAYBE Children: 0
    !/0: Task of Simple 7 State: MAYBE Children: 0
  !/0: Task of Simple 8 State: MAYBE Children: 0
  !/0: Task of Simple 9 State: COMPLETED Children: 0"""
        expected = re.compile(expected.replace('!', r'([0-9a-f\-]+)'))
        self.assert_(expected.match(root.get_dump()),
                     'Expected:\n' + repr(expected.pattern) + '\n' + \
                     'but got:\n'  + repr(root.get_dump()))

        # Now remove one line from the expected output for testing the
        # filtered iterator.
        expected2 = ''
        for line in expected.pattern.split('\n'):
            if line.find('Simple 9') >= 0:
                continue
            expected2 += line.lstrip() + '\n'
        expected2 = re.compile(expected2)

        # Run the iterator test.
        result = ''
        for thetask in Task.Iterator(root, Task.MAYBE):
            result += thetask.get_dump(0, False) + '\n'
        self.assert_(expected2.match(result),
                     'Expected:\n' + repr(expected2.pattern) + '\n' + \
                     'but got:\n'  + repr(result))
    def next_task(self):
        """Returns the next task that should be completed
        even if there are parallel tasks and multiple options are
        available.
        If the workflow is complete
        it will return the final end task.
        """

        # If the whole blessed mess is done, return the end_event task in the tree
        # This was failing in the case of a call activity where we have an intermediate EndEvent
        # what we really want is the LAST EndEvent

        endtasks = []
        if self.bpmn_workflow.is_completed():
            for task in SpiffTask.Iterator(self.bpmn_workflow.task_tree,
                                           SpiffTask.ANY_MASK):
                # Assure that we find the end event for this workflow, and not for any sub-workflows.
                if isinstance(
                        task.task_spec,
                        EndEvent) and task.workflow == self.bpmn_workflow:
                    endtasks.append(task)
            return endtasks[-1]

        # If there are ready tasks to complete, return the next ready task, but return the one
        # in the active parallel path if possible.  In some cases the active parallel path may itself be
        # a parallel gateway with multiple tasks, so prefer ones that share a parent.

        # Get a list of all ready tasks
        ready_tasks = self.bpmn_workflow.get_tasks(SpiffTask.READY)

        if len(ready_tasks) == 0:
            # If no ready tasks exist, check for a waiting task.
            waiting_tasks = self.bpmn_workflow.get_tasks(SpiffTask.WAITING)
            if len(waiting_tasks) > 0:
                return waiting_tasks[0]
            else:
                return  # We have not tasks to return.

        # Get a list of all completed user tasks (Non engine tasks)
        completed_user_tasks = self.completed_user_tasks()

        # If there are no completed user tasks, return the first ready task
        if len(completed_user_tasks) == 0:
            return ready_tasks[0]

        # Take the last completed task, find a child of it, and return that task
        last_user_task = completed_user_tasks[0]
        if len(ready_tasks) > 0:
            for task in ready_tasks:
                if task._is_descendant_of(last_user_task):
                    return task
            for task in ready_tasks:
                if self.bpmn_workflow.last_task and task.parent == last_user_task.parent:
                    return task

            return ready_tasks[0]

        # If there are no ready tasks, but the thing isn't complete yet, find the first non-complete task
        # and return that
        next_task = None
        for task in SpiffTask.Iterator(self.bpmn_workflow.task_tree,
                                       SpiffTask.NOT_FINISHED_MASK):
            next_task = task
        return next_task