def spec():
    """Workflow specification dictionary for test purposes."""
    return {
        'name':
        'myname',
        'var1':
        tp.VARIABLE('A'),
        'var2':
        tp.VARIABLE('A'),
        'var3':
        tp.VARIABLE('E? e1'),
        'values': [{
            'name': 'name',
            'el1': tp.VARIABLE('B'),
            'el2': tp.VARIABLE('G?Z'),
            'el3': tp.VARIABLE('F'),
            'nest': {
                'var': tp.VARIABLE('D')
            }
        },
                   tp.VARIABLE('C'),
                   tp.VARIABLE('B'), 3, 'E'],
        'count':
        2
    }
def test_parameter_references(spec):
    """Test getting parameter references for a workflow specification."""
    params = tp.get_parameter_references(spec)
    assert params == set({'A', 'B', 'C', 'D', 'E', 'F', 'G'})
    # Error for nested lists.
    spec = {
        'values': [{
            'name': 'name',
            'el': tp.VARIABLE('B'),
            'nest': {
                'var': tp.VARIABLE('D')
            }
        }, [tp.VARIABLE('C'), tp.VARIABLE('B')]],
        'count':
        2
    }
    with pytest.raises(err.InvalidTemplateError):
        tp.get_parameter_references(spec)
Example #3
0
    def modify_template(self, template, parameters):
        """Modify a the workflow specification in a given template by adding
        the a set of parameters. If a parameter in the added parameters set
        already exists in the template the name, index, default value, the
        value list and the required flag of the existing parameter are replaced
        by the values of the given parameter.

        Returns a modified workflow template. Raises an error if the parameter
        identifier in the resulting template are no longer unique.

        Note that this currently will only work for serial REANA workflow
        specifications. Will raise an InvalidTemplateError otherwise.

        Parameters
        ----------
        template: flowserv.model.template.base.WorkflowTemplate
            Workflow template handle.
        parameters: dict(flowserv.model.parameter.base.TemplateParameter)
            Additional template parameters

        Returns
        -------
        flowserv.model.template.base.WorkflowTemplate

        Raises
        ------
        flowserv.core.error.InvalidTemplateError
        """
        workflow_spec = template.workflow_spec
        # Raise an invalid template error if the workflow specification is not
        # a REANA serial workflow.
        workflow_type = workflow_spec.get('workflow', {}).get('type', 'null')
        if workflow_type != 'serial':
            msg = "invalid workflow type '{}'".format(workflow_type)
            raise err.InvalidTemplateError(msg)
        # Get a copy of the files and parameters sections of the inputs
        # declaration
        inputs = workflow_spec.get('inputs', dict())
        in_files = list(inputs.get('files', list()))
        in_params = dict(inputs.get('parameters', dict()))
        # Ensure that the identifier for all parameters are unique
        para_merge = dict(template.parameters)
        for para in parameters.values():
            if para.identifier in para_merge:
                para = para_merge[para.identifier].merge(para)
            para_merge[para.identifier] = para
            # Depending on whether the type of the parameter is a file or not we
            # add a parameter reference to the respective input section
            if para.is_file():
                in_files.append(tp.VARIABLE(para.identifier))
            else:
                if para.identifier not in in_params:
                    in_params[para.identifier] = tp.VARIABLE(para.identifier)
        spec = dict(workflow_spec)
        spec['inputs'] = {'files': in_files, 'parameters': in_params}
        return WorkflowTemplate(workflow_spec=spec,
                                sourcedir=template.sourcedir,
                                parameters=para_merge,
                                modules=template.modules,
                                postproc_spec=template.postproc_spec,
                                result_schema=template.result_schema)
def test_extract_parameter_name(variable, name):
    """Test function to extract the parameter name from a template parameter
    string.
    """
    assert tp.get_name(tp.VARIABLE(variable)) == name
            'name': 'name',
            'el1': tp.VARIABLE('B'),
            'el2': tp.VARIABLE('G?Z'),
            'el3': tp.VARIABLE('F'),
            'nest': {
                'var': tp.VARIABLE('D')
            }
        },
                   tp.VARIABLE('C'),
                   tp.VARIABLE('B'), 3, 'E'],
        'count':
        2
    }


@pytest.mark.parametrize('value,args,result', [(tp.VARIABLE('A'), {
    'A': 1
}, 1), (tp.VARIABLE('A ? xyz : abc'), {
    'A': True
}, 'xyz'), (tp.VARIABLE('A ? xyz : abc'), {
    'A': 'true'
}, 'xyz'), (tp.VARIABLE('A ? xyz : abc'), {
    'A': False
}, 'abc'), (tp.VARIABLE('C'), {
    'A': 1
}, 'default')])
def test_expand_parameter_value(value, args, result):
    """Test expand parameter reference function."""
    parameters = ParameterIndex()
    parameters['A'] = String(name='A', label='P1', index=0)
    parameters['B'] = String(name='B', label='P2', index=0)
Example #6
0
def test_template_serialization():
    """Test creating template instances from serializations."""
    # Minimal template specification.
    doc = {'workflow': dict()}
    doc = WorkflowTemplate.from_dict(doc).to_dict()
    template = WorkflowTemplate.from_dict(doc)
    assert template.workflow_spec == dict()
    assert template.parameters == ParameterIndex()
    # Maximal template specification.
    doc = {
        'workflow': {
            'inputs': [tp.VARIABLE('A'), 'B', 'C']
        },
        'parameters': [String(name='A', label='P1', index=0).to_dict()],
        'parameterGroups': [{
            'name': '0',
            'title': 'G1',
            'index': 0
        }, {
            'name': '1',
            'title': 'G2',
            'index': 1
        }],
        'postproc': {
            'workflow': dict(),
            'inputs': {
                'files': ['D', 'E']
            }
        },
        'results': {
            'file': 'results/analytics.json',
            'schema': [{
                'name': '0',
                'label': 'col0',
                'dtype': PARA_STRING
            }]
        }
    }
    doc = WorkflowTemplate.from_dict(doc).to_dict()
    template = WorkflowTemplate.from_dict(doc)
    assert template.workflow_spec == {'inputs': [tp.VARIABLE('A'), 'B', 'C']}
    assert len(template.parameters) == 1
    assert len(template.parameter_groups) == 2
    assert template.postproc_spec['workflow'] == dict()
    # No error for invalid document only if validate is not set to False.
    para = String(name='0', label='P1', index=0).to_dict()
    para['addOn'] = 1
    doc = {
        'workflow': {
            'inputs': ['A', 'B', 'C']
        },
        'parameters': [para],
        'parameterGroups': [{
            'name': '0',
            'title': 'G1',
            'index': 0,
            'sortDesc': True
        }, {
            'name': '1',
            'title': 'G2',
            'index': 1
        }],
        'postproc': {
            'inputs': {
                'files': ['D', 'E']
            }
        }
    }
    WorkflowTemplate.from_dict(doc, validate=False)
    with pytest.raises(err.InvalidParameterError):
        WorkflowTemplate.from_dict(doc)
    # Error for missing workflow specification.
    with pytest.raises(err.InvalidTemplateError):
        WorkflowTemplate.from_dict(dict())
    # Error for unknown parameter.
    with pytest.raises(err.UnknownParameterError):
        doc = {
            'workflow': {
                'inputs': [tp.VARIABLE('0'), 'B', 'C']
            },
            'parameters': [String(name='A', label='P1', index=0).to_dict()]
        }
        WorkflowTemplate.from_dict(doc)
            'el1': tp.VARIABLE('B'),
            'el2': '{}{}'.format(tp.VARIABLE('G?Z'), tp.VARIABLE('F')),
            'nest': {
                'var': tp.VARIABLE('D')
            }
        },
                   tp.VARIABLE('C'),
                   tp.VARIABLE('B'), 3, 'E'],
        'count':
        2
    }


@pytest.mark.parametrize(
    'value,args,result',
    [(tp.VARIABLE('A'), {
        'A': 1
    }, '1'), (tp.VARIABLE('A ? xyz : abc'), {
        'A': True
    }, 'xyz'), (tp.VARIABLE('A ? xyz : abc'), {
        'A': 'true'
    }, 'xyz'), (tp.VARIABLE('A ? xyz : abc'), {
        'A': False
    }, 'abc'),
     (tp.VARIABLE('C'), {
         'A': 1
     }, 'default'),
     ('{} : {} = {}{}'.format(tp.VARIABLE('A'), tp.VARIABLE('B ? y'),
                              tp.VARIABLE('C'), tp.VARIABLE('A ? t')), {
                                  'A': 'x',
                                  'B': 'True'