Skip to content

Commit ef1ba7b

Browse files
authored
Merge pull request #69 from PMCC-BioinformaticsCore/add-from-wdl
Add WDL parser to Janis
2 parents e74e6fe + 7d8b7b3 commit ef1ba7b

File tree

15 files changed

+871
-73
lines changed

15 files changed

+871
-73
lines changed

janis_core/ingestion/fromwdl.py

Lines changed: 447 additions & 0 deletions
Large diffs are not rendered by default.

janis_core/operators/logical.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ def __repr__(self):
5353
def evaluate(self, inputs):
5454
return self.evaluate_arg(self.args[0], inputs) is not None
5555

56+
def to_python(self, unwrap_operator, *args):
57+
arg = unwrap_operator(self.args[0])
58+
return f"{arg} is not None"
59+
5660
def to_cwl(self, unwrap_operator, *args):
5761
arg = unwrap_operator(self.args[0])
5862
# 2 equals (!=) in javascript will coerce undefined to equal null
@@ -103,6 +107,10 @@ def to_cwl(self, unwrap_operator, *args):
103107
cond, v1, v2 = [unwrap_operator(a) for a in self.args]
104108
return f"{cond} ? {v1} : {v2}"
105109

110+
def to_python(self, unwrap_operator, *args):
111+
condition, iftrue, iffalse = [unwrap_operator(a) for a in self.args]
112+
return f"({iftrue} if {condition} else {iffalse})"
113+
106114

107115
class AssertNotNull(Operator):
108116
@staticmethod
@@ -117,6 +125,9 @@ def evaluate(self, inputs):
117125
assert result is not None
118126
return result
119127

128+
def to_python(self, unwrap_operator, *args):
129+
return unwrap_operator(unwrap_operator(args[0]))
130+
120131
def to_wdl(self, unwrap_operator, *args):
121132
arg = unwrap_operator(self.args[0])
122133
return f"select_first([{arg}])"
@@ -168,6 +179,10 @@ def returntype(self):
168179
def apply_to(value):
169180
return not value
170181

182+
def to_python(self, unwrap_operator, *args):
183+
arg = unwrap_operator(self.args[0])
184+
return f"not {arg}"
185+
171186
# Two value operators
172187

173188

@@ -178,7 +193,7 @@ def friendly_signature():
178193

179194
@staticmethod
180195
def symbol():
181-
return "&&"
196+
return "and"
182197

183198
@staticmethod
184199
def wdl_symbol():
@@ -206,7 +221,7 @@ def friendly_signature():
206221

207222
@staticmethod
208223
def symbol():
209-
return "||"
224+
return "or"
210225

211226
@staticmethod
212227
def wdl_symbol():
@@ -559,6 +574,10 @@ def __str__(self):
559574
def __repr__(self):
560575
return str(self)
561576

577+
def to_python(self, unwrap_operator, *args):
578+
arg = unwrap_operator(self.args[0])
579+
return f"math.floor({arg})"
580+
562581
def to_wdl(self, unwrap_operator, *args):
563582
arg = unwrap_operator(self.args[0])
564583
return f"floor({arg})"
@@ -577,7 +596,7 @@ def evaluate(self, inputs):
577596
class CeilOperator(Operator):
578597
@staticmethod
579598
def friendly_signature():
580-
return "Numeric, NumericType -> Int"
599+
return "Numeric -> Int"
581600

582601
def argtypes(self) -> List[DataType]:
583602
return [NumericType]
@@ -592,6 +611,10 @@ def __str__(self):
592611
def __repr__(self):
593612
return str(self)
594613

614+
def to_python(self, unwrap_operator, *args):
615+
arg = unwrap_operator(self.args[0])
616+
return f"math.ceil({arg})"
617+
595618
def to_wdl(self, unwrap_operator, *args):
596619
arg = unwrap_operator(self.args[0])
597620
return f"ceil({arg})"
@@ -625,6 +648,10 @@ def __str__(self):
625648
def __repr__(self):
626649
return str(self)
627650

651+
def to_python(self, unwrap_operator, *args):
652+
arg = unwrap_operator(self.args[0])
653+
return f"math.round({arg})"
654+
628655
def to_wdl(self, unwrap_operator, *args):
629656
arg = unwrap_operator(self.args[0])
630657
return f"round({arg})"

janis_core/operators/operator.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ def to_wdl(self, unwrap_operator, *args):
134134
def to_cwl(self, unwrap_operator, *args):
135135
pass
136136

137+
@abstractmethod
138+
def to_python(self, unwrap_operator, *args):
139+
pass
140+
137141
def to_string_formatter(self):
138142
import re
139143
from janis_core.operators.stringformatter import StringFormatter
@@ -158,7 +162,10 @@ def argtypes(self):
158162
return [Array(AnyType), Int]
159163

160164
def returntype(self):
161-
return self.args[0].returntype().subtype()
165+
inner = get_instantiated_type(self.args[0].returntype())
166+
if isinstance(inner, Array):
167+
return inner.subtype()
168+
return inner
162169

163170
def __str__(self):
164171
base, index = self.args
@@ -172,6 +179,10 @@ def evaluate(self, inputs):
172179

173180
return iterable[idx]
174181

182+
def to_python(self, unwrap_operator, *args):
183+
base, index = [unwrap_operator(a) for a in self.args]
184+
return f"{base}[{index}]"
185+
175186
def to_wdl(self, unwrap_operator, *args):
176187
base, index = [unwrap_operator(a) for a in self.args]
177188
return f"{base}[{index}]"
@@ -219,6 +230,9 @@ def to_wdl(self, unwrap_operator, *args):
219230
def to_cwl(self, unwrap_operator, *args):
220231
return f"{self.cwl_symbol()}({unwrap_operator(*args)})"
221232

233+
def to_python(self, unwrap_operator, *args):
234+
return f"{self.symbol()}({unwrap_operator(*args)})"
235+
222236

223237
class TwoValueOperator(Operator, ABC):
224238
@staticmethod
@@ -253,6 +267,10 @@ def to_cwl(self, unwrap_operator, *args):
253267
arg1, arg2 = [unwrap_operator(a) for a in self.args]
254268
return f"({arg1} {self.cwl_symbol()} {arg2})"
255269

270+
def to_python(self, unwrap_operator, *args):
271+
arg1, arg2 = [unwrap_operator(a) for a in self.args]
272+
return f"({arg1} {self.symbol()} {arg2})"
273+
256274
def __str__(self):
257275
args = self.args
258276
return f"({args[0]} {self.symbol()} {args[1]})"

janis_core/operators/selectors.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ def basename(self):
245245

246246
return BasenameOperator(self)
247247

248+
def replace(self, pattern, replacement):
249+
from .standard import ReplaceOperator
250+
return ReplaceOperator(self, pattern, replacement)
251+
248252
def file_size(self):
249253
from .standard import FileSizeOperator
250254

@@ -308,6 +312,14 @@ def to_string_formatter(self):
308312

309313
return StringFormatter(f"{{{self.input_to_select}}}", **kwarg)
310314

315+
def init_dictionary(self):
316+
d = {"input_to_select": self.input_to_select}
317+
if self.remove_file_extension is not None:
318+
d["remove_file_extension"] = self.remove_file_extension
319+
if not isinstance(self.type_hint, File):
320+
d["type_hint"] = self.type_hint
321+
return d
322+
311323
def __str__(self):
312324
return "inputs." + self.input_to_select
313325

@@ -332,7 +344,7 @@ def id(self):
332344
def returntype(self):
333345
out = first_value(self.input_node.outputs()).outtype
334346

335-
if self.input_node is not None:
347+
if self.input_node is not None and self.input_node.default is not None:
336348
import copy
337349

338350
out = copy.copy(out)
@@ -367,8 +379,14 @@ def __init__(self, node, tag):
367379
def returntype(self):
368380
retval = self.node.outputs()[self.tag].outtype
369381

370-
if hasattr(self.node, "scatter") and self.node.scatter:
382+
if self.node.node_type != NodeType.STEP:
383+
return retval
384+
385+
if hasattr(self.node, "scatter") and self.node.scatter is not None:
371386
retval = Array(retval)
387+
elif hasattr(self.node, "foreach") and self.node.foreach is not None:
388+
retval = Array(retval)
389+
372390
return retval
373391

374392
@staticmethod
@@ -412,9 +430,24 @@ def __init__(self, inner: Selector, dt: ParseableType):
412430
def returntype(self) -> DataType:
413431
return self.data_type
414432

415-
def to_string_formatter(self):
433+
def __repr__(self):
416434
return f"({self.inner_selector} as {self.data_type})"
417435

436+
def to_string_formatter(self):
437+
from janis_core.operators.stringformatter import StringFormatter
438+
439+
return StringFormatter("{value}", value=self.inner_selector)
440+
441+
442+
class ForEachSelector(Selector):
443+
def returntype(self) -> DataType:
444+
return File()
445+
446+
def to_string_formatter(self):
447+
from janis_core.operators.stringformatter import StringFormatter
448+
449+
return StringFormatter("{inp}", inp=self)
450+
418451

419452
class ResourceSelector(InputSelector):
420453
def __init__(

0 commit comments

Comments
 (0)