Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expressions in Janis #10

Closed
wants to merge 141 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
141 commits
Select commit Hold shift + click to select a range
0395ea5
Add operator class as test
illusional Jan 21, 2020
162afe8
Refactor selectors + add more to allow used as operators
illusional Jan 22, 2020
0442f0a
Add `when` + replace Workflow.step tuple with StepOperator + fix effects
illusional Jan 22, 2020
767ce97
Add basic conditional translation for wdl + remember to bump wglgen vers
illusional Jan 22, 2020
9bd8dc8
Add basic tests for new operators / conditionals functionality
illusional Jan 22, 2020
ad07171
Add specific check for bool in wdl translation
illusional Jan 23, 2020
8d200d3
Quality syntax improvement in data_type isinstance check
illusional Jan 23, 2020
ca5fa4a
Add more true receivedType for stdout + stderr (allow optional cascade)
illusional Jan 23, 2020
de8cce4
Add conditionality => optional chaining to type system: inp/out override
illusional Jan 23, 2020
c62eb92
Add basic "switch" concept for conditionals
illusional Jan 23, 2020
3f022b2
Remove extra translate(wdl) statement
illusional Jan 23, 2020
94118fc
Return InputOperator by default from workflow for input node
illusional Jan 23, 2020
21217e9
Add test + skip for conditionals specific test
illusional Jan 23, 2020
5ddefc5
Move janis_unix import inside class
illusional Jan 23, 2020
5050a3e
Rename "conditional" from "switch"
illusional Jan 24, 2020
31323a7
Merge branch 'master' into expressions
illusional Mar 23, 2020
c9be341
Remove `first_element` legacy arg from WildcardSelector
illusional Mar 23, 2020
91a79ba
Specify a translation should generically unwrap an expression
illusional Mar 26, 2020
4b93477
Add returntype to Selector to prepare for operator typing
illusional Mar 26, 2020
c53b578
Move logical operators to logical file
illusional Mar 26, 2020
500687c
Move stringformatter to operators folder
illusional Mar 26, 2020
a4fd11b
Implement CWL required translation operator unwrap (half implemented)
illusional Mar 26, 2020
05f59ae
Implement WDL required translation operator unwrap (half implemented)
illusional Mar 26, 2020
7ac72f0
Add UnionType to STRICTLY be used in operators (for now)
illusional Mar 26, 2020
9ec9efc
Add type var to 'first_value' to fix type suggestions
illusional Mar 26, 2020
6bb52e1
Fix imports due to recent refactor
illusional Mar 26, 2020
ff3f069
Add _very_ basic tests for unions, many more required
illusional Mar 26, 2020
a81992c
Add standard library + basename operator
illusional Mar 26, 2020
bf11886
Migrate operator overloads to selector
illusional Mar 26, 2020
d61a4a9
Fix type annotation on UnionType + add AllType, NumericType
illusional Mar 26, 2020
84c179b
Migrate SingleValue, TwoValue operators to implement functional reqs
illusional Mar 26, 2020
28e9ffa
Make logical operators implement returntype and args per WDL / CWL rules
illusional Mar 26, 2020
1a53fc4
Migrate basename to use Operator instead of FunctionalOperator
illusional Mar 26, 2020
a232ad6
Simplify workflow rewrap expression to just generic operator
illusional Mar 26, 2020
a264a1d
Simplify WDL operator conversion to generic "Operator"
illusional Mar 26, 2020
a1625d9
Implement unwrap_expression, doesn't translate operators yet
illusional Mar 26, 2020
b5be655
Fix tests
illusional Mar 26, 2020
e8f68c8
Merge branch 'master' into expressions
illusional Mar 27, 2020
2c2bf7f
Modify StepTagInput to use selector instead of step node + string
illusional Mar 27, 2020
4047c73
Add IndexOperator + int indexing by a selector
illusional Mar 27, 2020
1c7ea12
Refactor workflow step to use Selector
illusional Mar 27, 2020
860399e
Fix wdl translation to use returntype instead of stepnode collection
illusional Mar 27, 2020
ec211b8
Basic (broken) WDL translation
illusional Mar 30, 2020
4932e65
Some test fixes (not finished yet)
illusional Mar 30, 2020
4c6443d
Merge branch 'master' into expressions
illusional Mar 30, 2020
e0db160
Start to add rules to WDL translation re secondaries + scatter
illusional Mar 30, 2020
34e0c83
Add cwlformatter to deps
illusional Apr 4, 2020
e73dbb2
Add transform operator
illusional Apr 4, 2020
9d24e6b
Add transform operator
illusional Apr 4, 2020
83bfac2
Merge branch 'master' into expressions
illusional Apr 15, 2020
5f8a30e
Add IfThisOrElse operator
illusional Apr 15, 2020
0d94b6a
Fix bad type on CwlTranslator
illusional Apr 15, 2020
93a37cf
Add more _get_instantiated_type calls
illusional Apr 16, 2020
84e2f22
Cleanup minor log entry
illusional Apr 16, 2020
e2b0bc7
Add echoTestTool for testing (copy of janis_unix)
illusional Apr 16, 2020
c812955
Cleanup add wrt. string formatters
illusional Apr 16, 2020
0872da7
Fix type system when it experiences python literals
illusional Apr 16, 2020
3410b0e
Ensure IfOrElse operator is unwrapping args
illusional Apr 16, 2020
9ebd5c0
Apply similar type system treatment to Add operator
illusional Apr 16, 2020
ccf6627
Add "IsDefined" operator
illusional Apr 16, 2020
f278320
Fix TwoValueOperator translation
illusional Apr 16, 2020
22d5a69
Fix cwl output translation param + add operator test
illusional Apr 16, 2020
e57f3ec
Ensure workflow.input returns an InputNodeSelector for consistency
illusional Apr 16, 2020
9945eac
Begin transition to use expressions on ToolOutput generation
illusional Apr 16, 2020
0937ebc
Merge branch 'master' into expressions
illusional Apr 16, 2020
3c41be6
Adn id() to InputNodeSelector for convenience
illusional Apr 17, 2020
aa7fe2c
Attempt new WDL implementation for output expressions
illusional Apr 17, 2020
5f777dd
Start to fix tests
illusional Apr 17, 2020
b174ee7
Fix test_workflow tests
illusional Apr 17, 2020
1fb5be2
Remove old commented out code
illusional Apr 17, 2020
b8bb37a
Allow the previous commit to function and not except early
illusional Apr 17, 2020
aa91820
Remove default from steptaginput
illusional Apr 17, 2020
20cfe0a
Rewrite WDL's translation of step node (big change)
illusional Apr 17, 2020
f8839a7
Fix test per previous commit
illusional Apr 17, 2020
0f378a9
Ensure WDL secondary inputs are mapped when input type is an array
illusional Apr 20, 2020
e6dae88
Ensure output_name / output_tag works with revised InputNodeSelectors
illusional Apr 20, 2020
aea5e47
Add type annotation to InputNodeSelector (maybe temporarily)
illusional Apr 20, 2020
367362f
Add more test tools with secondary files
illusional Apr 20, 2020
aeedbf5
Feature parity with WDL
illusional Apr 20, 2020
ba43366
Remove optional value in stringformatter test
illusional Apr 20, 2020
29e2fbd
Minor quality refactor of WDL translation
illusional Apr 20, 2020
2a93a5b
Add "get_leaves()" to operator to get options required to alias
illusional Apr 20, 2020
f060d1f
Rewrite CWL step translation to support initial operator aliasing
illusional Apr 20, 2020
8e252c4
Refactor location of StringFormatter
illusional Apr 21, 2020
d97b042
Add basic abstract methods for StringFormatter (even though currently…
illusional Apr 21, 2020
47a4640
Fix tests from stringformatter location refactor
illusional Apr 21, 2020
66c3b4f
Add StepInput expression test for CWL
illusional Apr 21, 2020
d63deb3
Refactor CWL stepinput expressions
illusional Apr 21, 2020
27759f1
Fix CWL array step input expressions
illusional Apr 21, 2020
a1b6e71
Migrate stepinput tests to WDL
illusional Apr 21, 2020
1e9e04f
Refactor IfThisOrElse to just "If" + token null support
illusional Apr 21, 2020
cbe5a4a
Partly introduce JoinOperator
illusional Apr 21, 2020
aab1b02
Add partial validation to Operator args (no typecheck yet)
illusional Apr 21, 2020
b8a82b5
Add WDL test for separator (when sep function is clairifed)
illusional Apr 21, 2020
56cfd48
Fix tests from next commit
illusional Apr 22, 2020
2018d7e
Generalise translate methods to accept a "Tool" (instead of just work…
illusional Apr 22, 2020
495eb47
Merge branch 'master' into expressions
illusional Apr 23, 2020
4c92c01
Add workflow input default expression to WDL
illusional Apr 23, 2020
df66181
Fix tests
illusional Apr 23, 2020
073110b
Add implementation for WDL join operator
illusional Apr 28, 2020
6d0b6ba
Merge branch 'master' into expressions
illusional Apr 28, 2020
d754cbe
Merge branch 'master' into expressions
illusional Apr 28, 2020
6a6f0cf
Add default for sep function call
illusional Apr 28, 2020
53ab9b9
Fix quoting in WDL
illusional Apr 30, 2020
19a1449
Merge branch 'master' into expressions
illusional May 1, 2020
c2aa0f1
Fix extra bracket in WDL commandline formatting
illusional May 1, 2020
ee1d2f4
How about actually generating real CWL kthanks
illusional May 1, 2020
441930c
Try again lol
illusional May 1, 2020
308da54
Fix selectfirst
illusional May 1, 2020
65410ff
Add more checks for WDL
illusional May 1, 2020
d1dfe95
Keep committing until it works
illusional May 1, 2020
755fd7f
Merge branch 'master' into expressions
illusional May 6, 2020
8cb82cc
Merge branch 'master' into expressions
illusional May 6, 2020
67ff1ad
Merge branch 'master' into expressions
illusional May 7, 2020
bea0d46
Allow selector as workflow inpt default for CWL
illusional May 7, 2020
b71d4bc
Remove duplicated code + fix shell quoting flag
illusional May 7, 2020
840b5c5
Pin wdlgen to higher version
illusional May 7, 2020
fd12702
Fix codetool exception handling
illusional May 7, 2020
77d2b8a
Fix WDL command line binding
illusional May 7, 2020
cb1e87a
Fix pythontool test
illusional May 7, 2020
c4d38ee
Merge branch 'master' into expressions
illusional May 7, 2020
0646a06
Add test_string_formatter for stepinput cwl
illusional May 8, 2020
6436995
Introduce more operators
illusional May 8, 2020
690d8e3
Fix a whole bunch of test that started breaking
illusional May 11, 2020
e497f95
Merge branch 'master' into expressions
illusional May 18, 2020
a16abcb
Remove traceback logging
illusional May 19, 2020
9033fee
Add `friendly_signature` to operators
illusional May 19, 2020
bff49ee
Add friendly_signature for stringformatter
illusional May 20, 2020
3d7c621
Fix CWL test because cwlgen changed
illusional May 20, 2020
fb34585
Merge branch 'master' into expressions
illusional May 21, 2020
53b6d49
Merge branch 'master' into expressions
illusional May 26, 2020
5c65ad3
Allow tools to specify operators for cpu/memory
illusional May 26, 2020
872962c
Allow tools to specify operators for cpu/memory
illusional May 26, 2020
6cd0646
Fix CWL output collection with stringformatter
illusional May 28, 2020
0d575d2
Fix secondaryFiles pattern generation (to be an array)
illusional May 28, 2020
188b74f
Merge branch 'master' into expressions
illusional Jun 1, 2020
05edbee
Merge branch 'master' into expressions
illusional Jun 2, 2020
85f04d5
Fix array separation for non-quoted values
illusional Jun 5, 2020
caba870
Merge branch 'master' into expressions
illusional Jun 9, 2020
a8d7a0e
Add ReadContentsOperator for WDL
illusional Jun 10, 2020
4a68d9c
Add requires_contents for CWL
illusional Jun 10, 2020
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
2 changes: 1 addition & 1 deletion janis_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
Stdout,
Stderr,
)
from janis_core.types import (
from janis_core.operators import (
InputSelector,
WildcardSelector,
MemorySelector,
Expand Down
9 changes: 8 additions & 1 deletion janis_core/code/codetool.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ def generate_inputs_override(
hints=None,
include_defaults=True,
):
from janis_core.operators.selectors import Selector

d, ad = {}, additional_inputs or {}
for i in self.inputs():
if (
Expand All @@ -95,8 +97,13 @@ def generate_inputs_override(
d[i] = ad.get(i.id(), i.default)

if with_resource_overrides:
cpus = self.cpus(hints) or 1
cpus = self.cpus(hints)
mem = self.memory(hints)

if isinstance(cpus, Selector):
cpus = None
if isinstance(mem, Selector):
mem = None
d.update(
{
"runtime_memory": mem,
Expand Down
2 changes: 1 addition & 1 deletion janis_core/code/pythontool.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class PythonTool:
args = cli.parse_args()
result = code_block({argkwargs})
print(json.dumps(result))
except e:
except Exception as e:
print(str(e), file=sys.stderr)
raise
"""
Expand Down
133 changes: 42 additions & 91 deletions janis_core/graph/steptaginput.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from typing import Optional, Dict, Any
from typing import Optional, Dict, Any, List

from janis_core.types import get_instantiated_type

from janis_core.operators import Selector
from janis_core.graph.node import Node, NodeType
from janis_core.tool.tool import TInput, TOutput
from janis_core.types.common_data_types import Array
Expand All @@ -21,20 +24,14 @@ def full_dot(node: Node, tag: Optional[str]) -> str:

class Edge:
def __init__(
self,
start: Node,
stag: Optional[str],
finish: Node,
ftag: Optional[str],
should_scatter,
self, source: Selector, finish: Node, ftag: Optional[str], should_scatter
):
Logger.log(
f"Creating edge: ({NodeType.to_str(start.node_type)}) '{start.id()}.{stag}' → "
f"Creating edge: ({source} → "
f"({NodeType.to_str(finish.node_type)}) '{finish.id()}.{ftag}'"
)

self.start: Node = start
self.stag: Optional[str] = stag
self.source = source
self.finish: Node = finish
self.ftag: Optional[str] = ftag
self.compatible_types: Optional[bool] = None
Expand All @@ -43,20 +40,13 @@ def __init__(
self.validate_tags()
self.check_types()

def source_slashed(self):
return full_lbl(self.start, self.stag)

def source_dotted(self):
return full_dot(self.start, self.stag)
# def source_slashed(self):
# return str(self.source)
#
# def source_dotted(self):
# return full_dot(self.start, self.stag)

def validate_tags(self):
if (
self.start.node_type == NodeType.STEP
and self.stag not in self.start.outputs()
):
raise Exception(
f"Could not find the tag '{self.stag}' in the inputs of '{self.start.id()}'"
)
if (
self.finish.node_type == NodeType.STEP
and self.ftag not in self.finish.inputs()
Expand All @@ -68,54 +58,39 @@ def validate_tags(self):
def check_types(self):
from janis_core.workflow.workflow import InputNode, StepNode

stoolin: TOutput = self.start.outputs()[
self.stag
] if self.stag is not None else first_value(self.start.outputs())
# stoolin: TOutput = self.start.outputs()[
# self.stag
# ] if self.stag is not None else first_value(self.start.outputs())
ftoolin: TInput = self.finish.inputs()[
self.ftag
] if self.ftag is not None else first_value(self.finish.inputs())

stype = stoolin.outtype
ftype = ftoolin.intype

start_is_scattered = (
isinstance(self.start, StepNode) and self.start.scatter is not None
)

if start_is_scattered:
Logger.log(
f"This edge merges the inputs from '{full_dot(self.start, self.stag)}' for "
f"'{full_dot(self.finish, self.ftag)}'"
)
stype = Array(stype)
stype = get_instantiated_type(self.source.returntype())
ftype = get_instantiated_type(ftoolin.intype)

if self.scatter:
if not isinstance(stype, Array):
raise Exception(
f"Scatter was required for '{self.start.id()}.{self.stag} → '{self.finish.id()}.{self.ftag}' but "
f"Scatter was required for '{self.source} → '{self.finish.id()}.{self.ftag}' but "
f"the input type was {type(stype).__name__} and not an array"
)
stype = stype.subtype()

source_has_default = (
isinstance(self.start, InputNode) and self.start.default is not None
)

# Scatters are handled automatically by the StepTagInput Array unwrapping
# Merges are handled automatically by the `start_is_scattered` Array wrap

self.compatible_types = ftype.can_receive_from(stype, source_has_default)
self.compatible_types = ftype.can_receive_from(stype, False)
if not self.compatible_types:
if isinstance(ftype, Array) and ftype.subtype().can_receive_from(stype):
self.compatible_types = True

if not self.compatible_types:

s = full_dot(self.start, self.stag)
s = str(self.source)
f = full_dot(self.finish, self.ftag)
message = (
f"Mismatch of types when joining '{s}' to '{f}': "
f"{stoolin.outtype.id()} -/→ {ftoolin.intype.id()}"
f"{stype.id()} -/→ {ftoolin.intype.id()}"
)
if isinstance(stype, Array) and ftype.can_receive_from(stype.subtype()):
message += " (did you forget to SCATTER?)"
Expand All @@ -133,12 +108,11 @@ def __init__(self, finish: Node, finish_tag: str):
self.finish: Node = finish
self.ftag: Optional[str] = finish_tag

self.default = None
self.multiple_inputs = False

self.source_map: Dict[str, Edge] = {}
self.source_map: List[Edge] = []

def add_source(self, start: Node, stag: Optional[str], should_scatter) -> Edge:
def add_source(self, operator: Selector, should_scatter) -> Edge:
"""
Add a connection
:param start:
Expand All @@ -149,33 +123,34 @@ def add_source(self, start: Node, stag: Optional[str], should_scatter) -> Edge:

from janis_core.workflow.workflow import StepNode

stype = (
start.outputs()[stag] if stag is not None else first_value(start.outputs())
).outtype
# start: Node, stag: Optional[str]

# stype = (start.outputs()[stag] if stag is not None else first_value(start.outputs())).outtype
stype = operator.returntype()
ftype = (
self.finish.inputs()[self.ftag]
if self.ftag is not None
else first_value(self.finish.inputs())
).intype

start_is_scattered = isinstance(start, StepNode) and start.scatter is not None

if start_is_scattered:
Logger.log(
f"This edge merges the inputs from '{full_dot(start, stag)}' for "
f"'{full_dot(self.finish, self.ftag)}'"
)
stype = Array(stype)
# start_is_scattered = isinstance(start, StepNode) and start.scatter is not None
#
# if start_is_scattered:
# Logger.log(
# f"This edge merges the inputs from '{full_dot(start, stag)}' for "
# f"'{full_dot(self.finish, self.ftag)}'"
# )
# stype = Array(stype)

if should_scatter:
if not isinstance(stype, Array):
raise Exception(
f"Scatter was required for '{start.id()}.{stag} → '{self.finish.id()}.{self.ftag}' but "
f"Scatter was required for '{operator} → '{self.finish.id()}.{self.ftag}' but "
f"the input type was {type(stype).__name__} and not an array"
)
stype = stype.subtype()

if len(self.source_map) == 1 and start.id() not in self.source_map:
if len(self.source_map) == 1: # and start.id() not in self.source_map:
self.multiple_inputs = True

if not isinstance(ftype, Array):
Expand All @@ -187,40 +162,16 @@ def add_source(self, start: Node, stag: Optional[str], should_scatter) -> Edge:
# https://www.commonwl.org/user_guide/misc/#connect-a-solo-value-to-an-input-that-expects-an-array-of-that-type
self.multiple_inputs = True

e = Edge(start, stag, self.finish, self.ftag, should_scatter=should_scatter)
self.source_map[start.id()] = e
e = Edge(operator, self.finish, self.ftag, should_scatter=should_scatter)
# todo: deal with source_map
self.source_map.append(e)
return e

def set_default(self, default: Any):
Logger.log(
f"Setting the default of '{self.finish.id()}.{self.ftag}' to be '{str(default)}'"
)
self.default = default

def source(self):
n = len(self.source_map)
if n == 0:
return None
elif n == 1:
return first_value(self.source_map)
else:
return list(self.source_map.values())

def dotted_source(self):
n = len(self.source_map)

if n == 0:
return None
elif n == 1:
return first_value(self.source_map).source_dotted()
else:
return [e.source_dotted() for e in self.source_map.values()]

def slashed_source(self):
n = len(self.source_map)
if n == 0:
return None
elif n == 1:
return first_value(self.source_map).source_slashed()
return self.source_map[0]
else:
return [e.source_slashed() for e in self.source_map.values()]
return list(self.source_map)
3 changes: 3 additions & 0 deletions janis_core/operators/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .operator import *
from .selectors import *
from .stringformatter import StringFormatter
Loading