Ejemplo n.º 1
0
    def evaluate(self, data):
        """Evaluate the code needed to compute a given Data object."""
        try:
            inputs = copy.deepcopy(data.input)
            hydrate_input_references(inputs, data.process.input_schema)
            hydrate_input_uploads(inputs, data.process.input_schema)

            # Include special 'proc' variable in the context.
            inputs["proc"] = {
                "data_id": data.id,
                "data_dir": self.manager.get_executor().resolve_data_path(),
            }

            # Include special 'requirements' variable in the context.
            inputs["requirements"] = data.process.requirements
            # Inject default values and change resources according to
            # the current Django configuration.
            inputs["requirements"]["resources"] = data.process.get_resource_limits()

            script_template = data.process.run.get("program", "")

            # Get the appropriate expression engine. If none is defined, do not evaluate
            # any expressions.
            expression_engine = data.process.requirements.get("expression-engine", None)
            if not expression_engine:
                return script_template

            return self.get_expression_engine(expression_engine).evaluate_block(
                script_template, inputs, escape=self._escape, safe_wrapper=SafeString,
            )
        except EvaluationError as error:
            raise ExecutionError("{}".format(error))
Ejemplo n.º 2
0
    def _evaluate_expressions(self, expression_engine, step_id, values,
                              context):
        """Recursively evaluate expressions in a dictionary of values."""
        if expression_engine is None:
            return values

        processed = {}
        for name, value in values.items():
            if isinstance(value, str):
                value = value.strip()
                try:
                    expression = expression_engine.get_inline_expression(value)
                    if expression is not None:
                        # Inline expression.
                        value = expression_engine.evaluate_inline(
                            expression, context)
                    else:
                        # Block expression.
                        value = expression_engine.evaluate_block(
                            value, context)
                except EvaluationError as error:
                    raise ExecutionError(
                        'Error while evaluating expression for step "{}":\n{}'.
                        format(step_id, error))
            elif isinstance(value, dict):
                value = self._evaluate_expressions(expression_engine, step_id,
                                                   value, context)

            processed[name] = value

        return processed
Ejemplo n.º 3
0
    def evaluate(self, data):
        """Evaluate the code needed to compute a given Data object."""
        try:
            inputs = copy.deepcopy(data.input)
            hydrate_input_references(inputs, data.process.input_schema)
            hydrate_input_uploads(inputs, data.process.input_schema)

            # Include special 'proc' variable in the context.
            inputs['proc'] = {
                'data_id': data.id,
                'data_dir': settings.FLOW_EXECUTOR['DATA_DIR'],
            }

            # Include special 'requirements' variable in the context.
            inputs['requirements'] = data.process.requirements

            script_template = data.process.run.get('program', '')

            # Get the appropriate expression engine. If none is defined, do not evaluate
            # any expressions.
            expression_engine = data.process.requirements.get(
                'expression-engine', None)
            if not expression_engine:
                return script_template

            return self.get_expression_engine(
                expression_engine).evaluate_block(
                    script_template,
                    inputs,
                    escape=self._escape,
                    safe_wrapper=SafeString,
                )
        except EvaluationError as error:
            raise ExecutionError('{}'.format(error))
Ejemplo n.º 4
0
    def evaluate(self, data):
        """Evaluate the code needed to compute a given Data object."""
        expression_engine = data.process.requirements.get(
            'expression-engine', None)
        if expression_engine is not None:
            expression_engine = self.get_expression_engine(expression_engine)

        # Parse steps.
        steps = data.process.run.get('program', None)
        if steps is None:
            return

        if not isinstance(steps, list):
            raise ExecutionError('Workflow program must be a list of steps.')

        # Expression engine evaluation context.
        context = {
            'input': data.input,
            'steps': collections.OrderedDict(),
        }

        for index, step in enumerate(steps):
            try:
                step_id = step['id']
                step_slug = step['run']
            except KeyError as error:
                raise ExecutionError(
                    'Incorrect definition of step "{}", missing property "{}".'
                    .format(step.get('id', index), error))

            # Fetch target process.
            process = Process.objects.filter(
                slug=step_slug).order_by('-version').first()
            if not process:
                raise ExecutionError(
                    'Incorrect definition of step "{}", invalid process "{}".'.
                    format(step_id, step_slug))

            # Process all input variables.
            step_input = step.get('input', {})
            if not isinstance(step_input, dict):
                raise ExecutionError(
                    'Incorrect definition of step "{}", input must be a dictionary.'
                    .format(step_id))

            data_input = self._evaluate_expressions(expression_engine, step_id,
                                                    step_input, context)

            # Create the data object.
            data_object = Data.objects.create(
                process=process,
                contributor=data.contributor,
                tags=data.tags,
                input=data_input,
                collection=data.collection,
                subprocess_parent=data,
            )

            context['steps'][step_id] = data_object.pk

        # Immediately set our status to done and output all data object identifiers.
        data.output = {
            'steps': list(context['steps'].values()),
        }
        data.status = Data.STATUS_DONE