Skip to content
This repository was archived by the owner on Jun 9, 2020. It is now read-only.

Commit af2d7d1

Browse files
authored
Merge pull request #46 from illusional/little-fixes
Add various fixes to cwlgen
2 parents de17bc8 + 5f911af commit af2d7d1

File tree

7 files changed

+77
-22
lines changed

7 files changed

+77
-22
lines changed

cwlgen/commandlinetool.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from cwlgen.commandlinebinding import CommandLineBinding
77
from .common import CWL_VERSIONS, DEF_VERSION, CWL_SHEBANG, Namespaces, Parameter
88
from .requirements import *
9-
from .utils import literal, literal_presenter, Serializable
9+
from .utils import literal, literal_presenter, Serializable, value_or_default
1010

1111
logging.basicConfig(level=logging.INFO)
1212
_LOGGER = logging.getLogger(__name__)
@@ -149,6 +149,7 @@ class CommandLineTool(Serializable):
149149

150150
__CLASS__ = "CommandLineTool"
151151

152+
required_fields = ["inputs", "outputs"]
152153
parse_types = {'inputs': [[CommandInputParameter]], "outputs": [[CommandOutputParameter]]}
153154
ignore_fields_on_parse = ["namespaces", "class", "requirements"]
154155
ignore_fields_on_convert = ["namespaces", "class", "metadata", "requirements"]
@@ -159,11 +160,16 @@ def __init__(
159160
base_command=None,
160161
label=None,
161162
doc=None,
162-
cwl_version=None,
163+
cwl_version="v1.0",
163164
stdin=None,
164165
stderr=None,
165166
stdout=None,
166-
path=None
167+
path=None,
168+
requirements=None,
169+
hints=None,
170+
inputs=None,
171+
outputs=None,
172+
arguments=None,
167173
):
168174
"""
169175
:param tool_id: Unique identifier for this tool
@@ -201,12 +207,12 @@ def __init__(
201207
self.cwlVersion = cwl_version
202208
self.id = tool_id
203209
self.label = label
204-
self.requirements = [] # List of objects inheriting from [Requirement]
205-
self.hints = [] # List of objects inheriting from [Requirement]
206-
self.inputs = [] # List of [CommandInputParameter] objects
207-
self.outputs = [] # List of [CommandOutputParameter] objects
210+
self.requirements = value_or_default(requirements, []) # List of objects inheriting from [Requirement]
211+
self.hints = value_or_default(hints, []) # List of objects inheriting from [Requirement]
212+
self.inputs = value_or_default(inputs, []) # List of [CommandInputParameter] objects
213+
self.outputs = value_or_default(outputs, []) # List of [CommandOutputParameter] objects
208214
self.baseCommand = base_command
209-
self.arguments = [] # List of [CommandLineBinding] objects
215+
self.arguments = value_or_default(arguments, []) # List of [CommandLineBinding] objects
210216
self.doc = doc
211217
self.stdin = stdin
212218
self.stderr = stderr
@@ -235,7 +241,9 @@ def get_dict(self):
235241

236242
if "inputs" not in d:
237243
# Tool can have no inputs but still needs to be bound
238-
d["inputs"] = []
244+
d["inputs"] = {}
245+
if "outputs" not in d:
246+
d["outputs"] = {}
239247

240248
if self.requirements:
241249
d["requirements"] = {r.get_class(): r.get_dict() for r in self.requirements}

cwlgen/utils.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,23 @@ def should_exclude_object(value):
6060
def get_dict(self):
6161
d = {}
6262
ignore_attributes = set()
63+
req_fields = set(self.required_fields or [])
64+
6365
if hasattr(self, "ignore_attributes") and self.ignore_attributes:
6466
ignore_attributes = set(self.ignore_attributes)
6567

6668
if self.ignore_fields_on_convert:
6769
ignore_attributes = ignore_attributes.union(self.ignore_fields_on_convert)
6870

6971
for k, v in vars(self).items():
70-
if self.should_exclude_object(v) or k.startswith("_") or k in ignore_attributes or k == "ignore_attributes":
72+
is_required = k in req_fields
73+
should_skip = (
74+
self.should_exclude_object(v)
75+
or k.startswith("_")
76+
or k in ignore_attributes
77+
or k == "ignore_attributes"
78+
)
79+
if not is_required and should_skip:
7180
continue
7281
s = self.serialize(v)
7382
if self.should_exclude_object(s):
@@ -115,7 +124,7 @@ def parse_dict_generic(T, d, parse_types=None, required_fields=None, ignore_fiel
115124
req_fields = ", ".join(r for r in req if not req[r])
116125
clsname = T.__name__
117126

118-
raise Exception("The fields %s were not found when parsing type '%", format(req_fields, clsname))
127+
raise Exception("The fields %s were not found when parsing type '%s'" % (req_fields, clsname))
119128

120129
return self
121130

@@ -159,7 +168,8 @@ def get_required_input_params_for_cls(cls, valuesdict):
159168

160169
@staticmethod
161170
def try_parse(value, types):
162-
if not types: return value
171+
if types is None: return value
172+
if isinstance(value, (dict, list)) and len(value) == 0: return []
163173

164174
# If it's an array, we should call try_parse (recursively)
165175

@@ -177,6 +187,8 @@ def try_parse(value, types):
177187
if retval:
178188
return retval
179189

190+
return
191+
180192

181193
@staticmethod
182194
def try_parse_type(value, T):
@@ -225,3 +237,7 @@ def get_indices_of_element_in_list(searchable, element):
225237
if element == searchable[i]:
226238
indices.append(i)
227239
return indices
240+
241+
242+
def value_or_default(value, default):
243+
return value if value is not None else default

cwlgen/workflow.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# Internal libraries
1111

1212
from .requirements import Requirement
13-
from .utils import literal, literal_presenter, Serializable
13+
from .utils import literal, literal_presenter, Serializable, value_or_default
1414
from .common import Parameter, CWL_SHEBANG
1515
from .workflowdeps import InputParameter, WorkflowOutputParameter, WorkflowStep
1616

@@ -35,6 +35,7 @@ class Workflow(Serializable):
3535
Documentation: https://www.commonwl.org/v1.0/Workflow.html#Workflow
3636
"""
3737
__CLASS__ = 'Workflow'
38+
required_fields = ["inputs", "outputs", "steps"]
3839
ignore_fields_on_parse = ["class", "requirements"]
3940
ignore_fields_on_convert = ["inputs", "outputs", "requirements"]
4041
parse_types = {
@@ -43,7 +44,7 @@ class Workflow(Serializable):
4344
"steps": [[WorkflowStep]],
4445
}
4546

46-
def __init__(self, workflow_id=None, label=None, doc=None, cwl_version='v1.0'):
47+
def __init__(self, workflow_id=None, label=None, doc=None, cwl_version='v1.0', inputs=None, outputs=None, steps=None, requirements=None, hints=None):
4748
"""
4849
:param workflow_id: The unique identifier for this process object.
4950
:type workflow_id: STRING
@@ -59,11 +60,11 @@ def __init__(self, workflow_id=None, label=None, doc=None, cwl_version='v1.0'):
5960
self.doc = doc
6061
self.cwlVersion = cwl_version
6162

62-
self.inputs = [] # list[InputParameter]
63-
self.outputs = [] # list[WorkflowOutputParameter]
64-
self.steps = [] # list[WorkflowStep]
65-
self.requirements = [] # list[Requirement]
66-
self.hints = [] # list[Requirement]
63+
self.inputs = value_or_default(inputs, []) # list[InputParameter]
64+
self.outputs = value_or_default(outputs, []) # list[WorkflowOutputParameter]
65+
self.steps = value_or_default(steps, []) # list[WorkflowStep]
66+
self.requirements = value_or_default(requirements, []) # list[Requirement]
67+
self.hints = value_or_default(hints, []) # list[Requirement]
6768
self._path = None
6869

6970
def get_dict(self):

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
long_description_content_type="text/markdown",
1313
license="MIT",
1414
keywords=["cwl"],
15-
install_requires=["ruamel.yaml >= 0.12.4, < 0.16.6"],
15+
install_requires=["ruamel.yaml >= 0.12.4, <= 0.16.5"],
1616
packages=["cwlgen"],
1717
classifiers=[
1818
"Development Status :: 4 - Beta",

test/test_export.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,26 @@ class TestExport(unittest.TestCase):
66
def test_workflow_export(self):
77
import cwlgen
88
w = cwlgen.Workflow("identifier")
9-
w.export()
9+
expected = """\
10+
class: Workflow
11+
cwlVersion: v1.0
12+
id: identifier
13+
inputs: {}
14+
outputs: {}
15+
steps: {}
16+
"""
17+
self.assertEqual(expected, w.export_string())
1018

1119
def test_commandlinetool_export(self):
1220
import cwlgen
1321

1422
c = cwlgen.CommandLineTool("identifier", "echo")
15-
c.export()
23+
expected = """\
24+
baseCommand: echo
25+
class: CommandLineTool
26+
cwlVersion: v1.0
27+
id: identifier
28+
inputs: {}
29+
outputs: {}
30+
"""
31+
self.assertEqual(expected, c.export_string())

test/test_unit_import_tool.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ def test_issue_25_requirements(self):
153153
class: CommandLineTool
154154
cwlVersion: v1.0
155155
156+
inputs: {}
157+
outputs: {}
158+
156159
requirements:
157160
- class: MultipleInputFeatureRequirement
158161
- class: StepInputExpressionRequirement
@@ -176,6 +179,9 @@ def test_issue_25_requirements_dict(self):
176179
class: CommandLineTool
177180
cwlVersion: v1.0
178181
182+
inputs: {}
183+
outputs: {}
184+
179185
requirements:
180186
MultipleInputFeatureRequirement: {}
181187
StepInputExpressionRequirement: {}

test/test_unit_import_workflow.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ def test_issue_25_requirements(self):
120120
label: joint calling workflow
121121
doc: Perform joint calling on multiple sets aligned reads from the same family.
122122
123+
inputs: {}
124+
steps: {}
125+
outputs: {}
126+
123127
requirements:
124128
- class: MultipleInputFeatureRequirement
125129
- class: StepInputExpressionRequirement
@@ -146,6 +150,10 @@ def test_issue_25_requirements_dict(self):
146150
label: joint calling workflow
147151
doc: Perform joint calling on multiple sets aligned reads from the same family.
148152
153+
inputs: {}
154+
outputs: {}
155+
steps: {}
156+
149157
requirements:
150158
MultipleInputFeatureRequirement: {}
151159
StepInputExpressionRequirement: {}

0 commit comments

Comments
 (0)