Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
67fec4a
Add fromwdl ingestor
illusional Mar 15, 2021
7a51594
Add ForEachSelector
illusional Mar 15, 2021
ad9762b
Add _foreach to workflow (unimplemented) - required for WDL ingestion
illusional Mar 15, 2021
c61df3f
Add WDL implementation for "foreach"
illusional Mar 15, 2021
260a02c
Add to_python for all operators
illusional Mar 15, 2021
1e3a289
Move node.returntype modifiers to nodes + foreach modifier
illusional Mar 15, 2021
0579c58
Fix minor issue with WDL foreach implementation
illusional Mar 15, 2021
573177d
Don't bind defaults to inputs.json if it's a selector
illusional Mar 15, 2021
53d9246
Format with Black
illusional Mar 15, 2021
54fe032
Implement ForEach on CWL
illusional Mar 15, 2021
3d5bcea
Add tests for ForEach
illusional Mar 15, 2021
b506638
Merge branch 'master' of https://github.com/PMCC-BioinformaticsCore/j…
junyk May 27, 2021
1decd6b
Remove inbuilt string formatting because it's too smart
illusional Mar 18, 2021
d7dbd70
Add replace operator
illusional Apr 28, 2021
c801850
Fix basename + add select_all operators to fromwdl
illusional Apr 28, 2021
8033b01
Improve bracket matching to not include ${*} placeholders
illusional May 30, 2021
911f89b
Improve FilterNullOperator output type detection
illusional May 30, 2021
fa12bd0
Add error boundary to WDL parser
illusional May 30, 2021
e6772fe
WDL parser bug fixes
illusional May 30, 2021
0ee5a82
Fix double unwrapped WDL implementation of basename operator
illusional May 30, 2021
7d8b7b3
Update fromwdl.py to read file path from sys.argv
illusional May 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
402 changes: 402 additions & 0 deletions janis_core/ingestion/fromwdl.py

Large diffs are not rendered by default.

33 changes: 30 additions & 3 deletions janis_core/operators/logical.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ def __repr__(self):
def evaluate(self, inputs):
return self.evaluate_arg(self.args[0], inputs) is not None

def to_python(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"{arg} is not None"

def to_cwl(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
# 2 equals (!=) in javascript will coerce undefined to equal null
Expand Down Expand Up @@ -103,6 +107,10 @@ def to_cwl(self, unwrap_operator, *args):
cond, v1, v2 = [unwrap_operator(a) for a in self.args]
return f"{cond} ? {v1} : {v2}"

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


class AssertNotNull(Operator):
@staticmethod
Expand All @@ -117,6 +125,9 @@ def evaluate(self, inputs):
assert result is not None
return result

def to_python(self, unwrap_operator, *args):
return unwrap_operator(unwrap_operator(args[0]))

def to_wdl(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"select_first([{arg}])"
Expand Down Expand Up @@ -168,6 +179,10 @@ def returntype(self):
def apply_to(value):
return not value

def to_python(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"not {arg}"

# Two value operators


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

@staticmethod
def symbol():
return "&&"
return "and"

@staticmethod
def wdl_symbol():
Expand Down Expand Up @@ -206,7 +221,7 @@ def friendly_signature():

@staticmethod
def symbol():
return "||"
return "or"

@staticmethod
def wdl_symbol():
Expand Down Expand Up @@ -559,6 +574,10 @@ def __str__(self):
def __repr__(self):
return str(self)

def to_python(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"math.floor({arg})"

def to_wdl(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"floor({arg})"
Expand All @@ -577,7 +596,7 @@ def evaluate(self, inputs):
class CeilOperator(Operator):
@staticmethod
def friendly_signature():
return "Numeric, NumericType -> Int"
return "Numeric -> Int"

def argtypes(self) -> List[DataType]:
return [NumericType]
Expand All @@ -592,6 +611,10 @@ def __str__(self):
def __repr__(self):
return str(self)

def to_python(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"math.ceil({arg})"

def to_wdl(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"ceil({arg})"
Expand Down Expand Up @@ -625,6 +648,10 @@ def __str__(self):
def __repr__(self):
return str(self)

def to_python(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"math.round({arg})"

def to_wdl(self, unwrap_operator, *args):
arg = unwrap_operator(self.args[0])
return f"round({arg})"
Expand Down
20 changes: 19 additions & 1 deletion janis_core/operators/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ def to_wdl(self, unwrap_operator, *args):
def to_cwl(self, unwrap_operator, *args):
pass

@abstractmethod
def to_python(self, unwrap_operator, *args):
pass

def to_string_formatter(self):
import re
from janis_core.operators.stringformatter import StringFormatter
Expand All @@ -158,7 +162,10 @@ def argtypes(self):
return [Array(AnyType), Int]

def returntype(self):
return self.args[0].returntype().subtype()
inner = get_instantiated_type(self.args[0].returntype())
if isinstance(inner, Array):
return inner.subtype()
return inner

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

return iterable[idx]

def to_python(self, unwrap_operator, *args):
base, index = [unwrap_operator(a) for a in self.args]
return f"{base}[{index}]"

def to_wdl(self, unwrap_operator, *args):
base, index = [unwrap_operator(a) for a in self.args]
return f"{base}[{index}]"
Expand Down Expand Up @@ -219,6 +230,9 @@ def to_wdl(self, unwrap_operator, *args):
def to_cwl(self, unwrap_operator, *args):
return f"{self.cwl_symbol()}({unwrap_operator(*args)})"

def to_python(self, unwrap_operator, *args):
return f"{self.symbol()}({unwrap_operator(*args)})"


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

def to_python(self, unwrap_operator, *args):
arg1, arg2 = [unwrap_operator(a) for a in self.args]
return f"({arg1} {self.symbol()} {arg2})"

def __str__(self):
args = self.args
return f"({args[0]} {self.symbol()} {args[1]})"
Expand Down
35 changes: 32 additions & 3 deletions janis_core/operators/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,14 @@ def to_string_formatter(self):

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

def init_dictionary(self):
d = {"input_to_select": self.input_to_select}
if self.remove_file_extension is not None:
d["remove_file_extension"] = self.remove_file_extension
if not isinstance(self.type_hint, File):
d["type_hint"] = self.type_hint
return d

def __str__(self):
return "inputs." + self.input_to_select

Expand All @@ -332,7 +340,7 @@ def id(self):
def returntype(self):
out = first_value(self.input_node.outputs()).outtype

if self.input_node is not None:
if self.input_node is not None and self.input_node.default is not None:
import copy

out = copy.copy(out)
Expand Down Expand Up @@ -367,8 +375,14 @@ def __init__(self, node, tag):
def returntype(self):
retval = self.node.outputs()[self.tag].outtype

if hasattr(self.node, "scatter") and self.node.scatter:
if self.node.node_type != NodeType.STEP:
return retval

if hasattr(self.node, "scatter") and self.node.scatter is not None:
retval = Array(retval)
elif hasattr(self.node, "foreach") and self.node.foreach is not None:
retval = Array(retval)

return retval

@staticmethod
Expand Down Expand Up @@ -412,9 +426,24 @@ def __init__(self, inner: Selector, dt: ParseableType):
def returntype(self) -> DataType:
return self.data_type

def to_string_formatter(self):
def __repr__(self):
return f"({self.inner_selector} as {self.data_type})"

def to_string_formatter(self):
from janis_core.operators.stringformatter import StringFormatter

return StringFormatter("{value}", value=self.inner_selector)


class ForEachSelector(Selector):
def returntype(self) -> DataType:
return File()

def to_string_formatter(self):
from janis_core.operators.stringformatter import StringFormatter

return StringFormatter("{inp}", inp=self)


class ResourceSelector(InputSelector):
def __init__(
Expand Down
Loading