Esempio n. 1
0
    def exec(self, step: CodeStep, context: Dict,
             store: FileSystemStorage) -> ExecResult:
        """Execute a workflow step of type :class:`flowserv.model.workflow.step.CodeStep`
        in a given context.

        Captures output to STDOUT and STDERR and includes them in the returned
        execution result.

        Note that the code worker expects a file system storage volume.

        Parameters
        ----------
        step: flowserv.model.workflow.step.CodeStep
            Code step in a serial workflow.
        context: dict
            Context for the executed code.
        store: flowserv.volume.fs.FileSystemStorage
            Storage volume that contains the workflow run files.

        Returns
        -------
        flowserv.controller.serial.workflow.result.ExecResult
        """
        result = ExecResult(step=step)
        out = sys.stdout
        err = sys.stderr
        sys.stdout = OutputStream(stream=result.stdout)
        sys.stderr = OutputStream(stream=result.stderr)
        # Change working directory temporarily.
        cwd = os.getcwd()
        os.chdir(store.basedir)
        try:
            step.exec(context=context)
        except Exception as ex:
            logging.error(ex, exc_info=True)
            strace = '\n'.join(util.stacktrace(ex))
            logging.debug(strace)
            result.stderr.append(strace)
            result.exception = ex
            result.returncode = 1
        finally:
            # Make sure to reverse redirection of output streams
            sys.stdout = out
            sys.stderr = err
            # Reset working directory.
            os.chdir(cwd)
        return result
def test_exec_func_step():
    """Test executing a Python function as a step in a serial workflow."""
    args = {'x': 1, 'y': 2}
    step = CodeStep(identifier='test', func=my_add, arg='z')
    step.exec(context=args)
    assert args == {'x': 1, 'y': 2, 'z': 3}
    # Test renaming arguments.
    step = CodeStep(identifier='test',
                    func=my_add,
                    varnames={'x': 'z'},
                    arg='x')
    step.exec(context=args)
    assert args == {'x': 5, 'y': 2, 'z': 3}
    # Execute function but ignore output.
    step = CodeStep(identifier='test', func=my_add)
    step.exec(context=args)
    assert args == {'x': 5, 'y': 2, 'z': 3}