diff --git a/renga/cli/_graph.py b/renga/cli/_graph.py index a906b07cef..88f70f4f07 100644 --- a/renga/cli/_graph.py +++ b/renga/cli/_graph.py @@ -29,6 +29,7 @@ from renga._compat import Path from renga.api import LocalClient from renga.models.cwl.command_line_tool import CommandLineTool +from renga.models.cwl.parameter import InputParameter, WorkflowOutputParameter from renga.models.cwl.workflow import Workflow @@ -297,11 +298,13 @@ def ascwl(self): input_mapping = ins.get(input_.id) if input_mapping is None: input_id = 'input_{0}'.format(input_index) - workflow.inputs.append({ - 'id': input_id, - 'type': input_.type, - 'default': input_.default, - }) + workflow.inputs.append( + InputParameter( + id=input_id, + type=input_.type, + default=input_.default, + ) + ) input_index += 1 ins[input_.id] = input_id @@ -314,10 +317,12 @@ def ascwl(self): for index, key in enumerate(self._output_keys): output_id = 'output_{0}'.format(index) - workflow.outputs.append({ - 'id': output_id, - 'type': 'File', - 'outputSource': self._source_name(key), - }) + workflow.outputs.append( + WorkflowOutputParameter( + id=output_id, + type='File', + outputSource=self._source_name(key), + ) + ) return workflow diff --git a/renga/models/cwl/parameter.py b/renga/models/cwl/parameter.py index 456d8ba8b7..60c54ea4ea 100644 --- a/renga/models/cwl/parameter.py +++ b/renga/models/cwl/parameter.py @@ -22,6 +22,37 @@ from .types import File +def convert_default(value): + """Convert a default value.""" + if isinstance(value, dict): + return File.from_cwl(value) + return value + + +@attr.s +class _IdMixin(object): + """Define id field.""" + + id = attr.ib() + + +@attr.s +class Parameter(object): + """Define an input or output parameter to a process.""" + + streamable = attr.ib(default=None, converter=bool) + + +@attr.s +class InputParameter(_IdMixin, Parameter): + """An input parameter.""" + + type = attr.ib(default='string') + description = attr.ib(default=None) + default = attr.ib(default=None, converter=convert_default) + inputBinding = attr.ib(default=None) + + @attr.s class CommandLineBinding(object): """Define the binding behavior when building the command line.""" @@ -34,28 +65,26 @@ class CommandLineBinding(object): shellQuote = attr.ib(default=True, type=bool) -def convert_default(value): - """Convert a default value.""" - if isinstance(value, dict): - return File.from_cwl(value) - return value - - @attr.s -class CommandInputParameter(object): +class CommandInputParameter(InputParameter): """An input parameter for a CommandLineTool.""" - id = attr.ib() - type = attr.ib(default='string') - description = attr.ib(default=None) - default = attr.ib(default=None, converter=convert_default) inputBinding = attr.ib( default=None, converter=lambda data: CommandLineBinding(**data) if not isinstance( data, CommandLineBinding ) and data is not None else data, ) - streamable = attr.ib(default=None) + + +@attr.s +class OutputParameter(_IdMixin, Parameter): + """An output parameter.""" + + type = attr.ib(default='string') + description = attr.ib(default=None) + format = attr.ib(default=None) + outputBinding = attr.ib(default=None) @attr.s @@ -67,17 +96,19 @@ class CommandOutputBinding(object): @attr.s -class CommandOutputParameter(object): - """An input parameter for a CommandLineTool.""" +class CommandOutputParameter(OutputParameter): + """Define an output parameter for a CommandLineTool.""" - id = attr.ib() - type = attr.ib(default='string') - description = attr.ib(default=None) - format = attr.ib(default=None) outputBinding = attr.ib( default=None, converter=lambda data: CommandOutputBinding(**data) if not isinstance( data, CommandOutputBinding ) and data is not None else data, ) - streamable = attr.ib(default=None) + + +@attr.s +class WorkflowOutputParameter(OutputParameter): + """Define an output parameter for a Workflow.""" + + outputSource = attr.ib(default=None) diff --git a/renga/models/cwl/process.py b/renga/models/cwl/process.py index f67a0d2cb3..98231a444c 100644 --- a/renga/models/cwl/process.py +++ b/renga/models/cwl/process.py @@ -19,27 +19,16 @@ import attr +from ._ascwl import mapped +from .parameter import InputParameter, OutputParameter + @attr.s(init=False) class Process(object): """Represent a process.""" - inputs = attr.ib( - default=attr.Factory(list), - metadata={ - 'jsonldPredicate': { - 'mapSubject': 'id' - }, - } - ) # list InputParameter - outputs = attr.ib( - default=attr.Factory(list), - metadata={ - 'jsonldPredicate': { - 'mapSubject': 'id' - }, - } - ) # list OutputParameter + inputs = mapped(InputParameter) + outputs = mapped(OutputParameter) requirements = attr.ib(default=attr.Factory(list)) # list ProcessRequirement hints = attr.ib(default=attr.Factory(list)) # list Any diff --git a/renga/models/cwl/workflow.py b/renga/models/cwl/workflow.py index 72ab2e8921..6ead9aca32 100644 --- a/renga/models/cwl/workflow.py +++ b/renga/models/cwl/workflow.py @@ -22,6 +22,7 @@ import attr from ._ascwl import CWLClass, mapped +from .parameter import WorkflowOutputParameter from .process import Process @@ -40,6 +41,7 @@ class WorkflowStep(object): class Workflow(Process, CWLClass): """Define a workflow representation.""" + outputs = mapped(WorkflowOutputParameter) steps = mapped(WorkflowStep) def add_step(self, **kwargs):