Skip to content

Commit

Permalink
Merge pull request #3123 from broadinstitute/cjl_initial_work_dir_req…
Browse files Browse the repository at this point in the history
…uirement_7

Allow ECMA script functions as well as expressions in IWDR fields
  • Loading branch information
cjllanwarne committed Jan 10, 2018
2 parents 1450991 + 4f183b0 commit 140b2f8
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: iwdr_input_string_function
testFormat: workflowsuccess
workflowType: CWL
workflowRoot: iwdr_input_string_function
workflowTypeVersion: v1.0

files {
wdl: InitialWorkDirRequirement/input_string_function.cwl
}

metadata {
"submittedFiles.workflowType": CWL
"submittedFiles.workflowTypeVersion": v1.0
"outputs.iwdr_input_string_function.prime_list": "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Little tool that uses a prime sieve to generate primes up to 100

cwlVersion: v1.0
$graph:
- id: iwdr_input_string_function
class: CommandLineTool
baseCommand: ['python3']
requirements:
- class: DockerRequirement
dockerPull: "python:3.5.0"
- class: InitialWorkDirRequirement
listing:
- entryname: ${var result = inputs.script_name + ".py"; return result;}
entry: ${var scr = inputs.script; return scr + "print(result);"}

stdout: "primes"
inputs:
- id: script
type: string
default: |
import sys
import math

limit = int(sys.argv[1])
sieve = [True for i in range(limit)]
for i in range(2, math.floor(limit / 2)):
if sieve[i]:
for j in range(i * 2, limit, i):
sieve[j] = False

result = "["
for i in range(2, limit):
if sieve[i]:
if result != "[":
result += ", "
result += str(i)
result += "]"

- id: script_name
type: string
default: "prime_sieve.py"
arguments: [ '${var result = inputs.script_name + ".py"; return result;}', '100' ]
outputs:
- id: prime_list
type: string
outputBinding:
glob: primes
loadContents: true
outputEval: $(self[0].contents.trim())
12 changes: 6 additions & 6 deletions cwl/src/main/scala/cwl/CwlWomExpression.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ final case class InitialWorkDirFileGeneratorExpression(entry: IwdrListingArrayEn

def evaluateEntryName(stringOrExpression: StringOrExpression): ErrorOr[String] = stringOrExpression match {
case StringOrExpression.String(s) => s.validNel
case StringOrExpression.ECMAScriptExpression(entrynameExpression) => for {
entryNameExpressionEvaluated <- ExpressionEvaluator.evalExpression(entrynameExpression, ParameterContext(inputValues)).toErrorOr
case StringOrExpression.Expression(entrynameExpression) => for {
entryNameExpressionEvaluated <- ExpressionEvaluator.evalCwlExpression(entrynameExpression, ParameterContext(inputValues)).toErrorOr
entryNameValidated <- mustBeString(entryNameExpressionEvaluated)
} yield entryNameValidated
}
Expand All @@ -70,8 +70,8 @@ final case class InitialWorkDirFileGeneratorExpression(entry: IwdrListingArrayEn
writtenFile <- Try(Await.result(ioFunctionSet.writeFile(entryNameValidated, content), Duration.Inf)).toErrorOr
} yield writtenFile

case IwdrListingArrayEntry.ExpressionDirent(Expression.ECMAScriptExpression(contentExpression), direntEntryName, _) =>
val entryEvaluation: ErrorOr[WomValue] = ExpressionEvaluator.evalExpression(contentExpression, ParameterContext().addInputs(inputValues)).toErrorOr
case IwdrListingArrayEntry.ExpressionDirent(contentExpression, direntEntryName, _) =>
val entryEvaluation: ErrorOr[WomValue] = ExpressionEvaluator.evalCwlExpression(contentExpression, ParameterContext().addInputs(inputValues)).toErrorOr
entryEvaluation flatMap {
case f: WomFile =>
val entryName: ErrorOr[String] = direntEntryName match {
Expand All @@ -88,9 +88,9 @@ final case class InitialWorkDirFileGeneratorExpression(entry: IwdrListingArrayEn
writtenFile <- Try(Await.result(ioFunctionSet.writeFile(entryname, contentString), Duration.Inf)).toErrorOr
} yield writtenFile
}
case IwdrListingArrayEntry.ECMAScriptExpression(expression) =>
case IwdrListingArrayEntry.Expression(expression) =>
// A single expression which must evaluate to an array of Files
val expressionEvaluation: ErrorOr[WomValue] = ExpressionEvaluator.evalExpression(expression, ParameterContext().addInputs(inputValues)).toErrorOr
val expressionEvaluation: ErrorOr[WomValue] = ExpressionEvaluator.evalCwlExpression(expression, ParameterContext().addInputs(inputValues)).toErrorOr

expressionEvaluation flatMap {
case array: WomArray if WomArrayType(WomSingleFileType).coercionDefined(array) =>
Expand Down
4 changes: 4 additions & 0 deletions cwl/src/main/scala/cwl/ExpressionEvaluator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ object ExpressionEvaluator {
type ECMAScriptFunction = String Refined MatchesRegex[ECMAScriptFunctionWitness.T]
type MatchesECMAFunction = MatchesRegex[ECMAScriptFunctionWitness.T]

def evalCwlExpression(expression: Expression, parameterContext: ParameterContext): Try[WomValue] = expression match {
case Expression.ECMAScriptExpression(expr) => evalExpression(expr, parameterContext)
case Expression.ECMAScriptFunction(fun) => evalFunction(fun, parameterContext)
}

def evalExpression(expression: ECMAScriptExpression, parameterContext: ParameterContext): Try[WomValue] = {
val ECMAScriptExpressionRegex = ECMAScriptExpressionWitness.value.r
Expand Down
8 changes: 3 additions & 5 deletions cwl/src/main/scala/cwl/InitialWorkDirRequirement.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package cwl

import cwl.ExpressionEvaluator.ECMAScriptExpression
import cwl.InitialWorkDirRequirement._
import eu.timepit.refined.W
import shapeless.{:+:, CNil, _}
Expand Down Expand Up @@ -65,12 +64,11 @@ object InitialWorkDirRequirement {
object String {
def unapply(e: IwdrListingArrayEntry): Option[String] = e.select[StringOrExpression].flatMap(_.select[String])
}
object ECMAScriptExpression {
def unapply(e: IwdrListingArrayEntry): Option[ECMAScriptExpression] = for {
object Expression {
def unapply(e: IwdrListingArrayEntry): Option[Expression] = for {
soe <- e.select[StringOrExpression]
expr <- soe.select[Expression]
ecmaScriptExpression <- expr.select[ECMAScriptExpression]
} yield ecmaScriptExpression
} yield expr


}
Expand Down

0 comments on commit 140b2f8

Please sign in to comment.