-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #559 from viash-io/develop
Viash 0.8.0-RC4
- Loading branch information
Showing
37 changed files
with
547 additions
and
747 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
name := "viash" | ||
|
||
version := "0.8.0-RC3" | ||
version := "0.8.0-RC4" | ||
|
||
scalaVersion := "2.13.10" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 116 additions & 25 deletions
141
src/main/resources/io/viash/platforms/nextflow/arguments/_checkArgumentType.nf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,155 @@ | ||
class UnexpectedArgumentTypeException extends Exception { | ||
String errorIdentifier | ||
String stage | ||
String plainName | ||
String expectedClass | ||
String foundClass | ||
|
||
// ${key ? " in module '$key'" : ""}${id ? " id '$id'" : ""} | ||
UnexpectedArgumentTypeException(String errorIdentifier, String stage, String plainName, String expectedClass, String foundClass) { | ||
super("Error${errorIdentifier ? " $errorIdentifier" : ""}:${stage ? " $stage" : "" } argument '${plainName}' has the wrong type. " + | ||
"Expected type: ${expectedClass}. Found type: ${foundClass}") | ||
this.errorIdentifier = errorIdentifier | ||
this.stage = stage | ||
this.plainName = plainName | ||
this.expectedClass = expectedClass | ||
this.foundClass = foundClass | ||
} | ||
} | ||
|
||
def _checkArgumentType(String stage, Map par, Object value, String id, String key) { | ||
/** | ||
* Checks if the given value is of the expected type. If not, an exception is thrown. | ||
* | ||
* @param stage The stage of the argument (input or output) | ||
* @param par The parameter definition | ||
* @param value The value to check | ||
* @param errorIdentifier The identifier to use in the error message | ||
* @return The value, if it is of the expected type | ||
* @throws UnexpectedArgumentTypeException If the value is not of the expected type | ||
*/ | ||
def _checkArgumentType(String stage, Map par, Object value, String errorIdentifier) { | ||
// expectedClass will only be != null if value is not of the expected type | ||
def expectedClass = null | ||
def foundClass = null | ||
|
||
// todo: split if need be | ||
|
||
if (!par.required && value == null) { | ||
expectedClass = null | ||
} else if (par.multiple) { | ||
if (value instanceof List) { | ||
try { | ||
value = value.collect { listVal -> | ||
_checkArgumentType(stage, par + [multiple: false], listVal, id, key) | ||
} | ||
} catch (Exception e) { | ||
expectedClass = "List[${par.type}]" | ||
if (value !instanceof Collection) { | ||
value = [value] | ||
} | ||
|
||
// split strings | ||
value = value.collectMany{ val -> | ||
if (val instanceof String) { | ||
// collect() to ensure that the result is a List and not simply an array | ||
val.split(par.multiple_sep).collect() | ||
} else { | ||
[val] | ||
} | ||
} | ||
|
||
// process globs | ||
if (par.type == "file" && par.direction == "input") { | ||
value = value.collect{ it instanceof String ? file(it, hidden: true) : it }.flatten() | ||
} | ||
|
||
// check types of elements in list | ||
try { | ||
value = value.collect { listVal -> | ||
_checkArgumentType(stage, par + [multiple: false], listVal, errorIdentifier) | ||
} | ||
} else { | ||
expectedClass = "List[${par.type}]" | ||
} catch (UnexpectedArgumentTypeException e) { | ||
expectedClass = "List[${e.expectedClass}]" | ||
foundClass = "List[${e.foundClass}]" | ||
} | ||
} else if (par.type == "string") { | ||
// cast to string if need be | ||
if (value instanceof GString) { | ||
value = value.toString() | ||
} | ||
expectedClass = value instanceof String ? null : "String" | ||
} else if (par.type == "integer") { | ||
// cast to integer if need be | ||
if (value instanceof String) { | ||
try { | ||
value = value.toInteger() | ||
} catch (NumberFormatException e) { | ||
// do nothing | ||
} | ||
} | ||
if (value instanceof java.math.BigInteger) { | ||
value = value.intValue() | ||
} | ||
expectedClass = value instanceof Integer ? null : "Integer" | ||
} else if (par.type == "long") { | ||
// cast to long if need be | ||
if (value instanceof String) { | ||
try { | ||
value = value.toLong() | ||
} catch (NumberFormatException e) { | ||
// do nothing | ||
} | ||
} | ||
if (value instanceof Integer) { | ||
value = value.toLong() | ||
} | ||
expectedClass = value instanceof Long ? null : "Long" | ||
} else if (par.type == "double") { | ||
// cast to double if need be | ||
if (value instanceof String) { | ||
try { | ||
value = value.toDouble() | ||
} catch (NumberFormatException e) { | ||
// do nothing | ||
} | ||
} | ||
if (value instanceof java.math.BigDecimal) { | ||
value = value.doubleValue() | ||
} | ||
if (value instanceof Float || value instanceof Integer || value instanceof Long) { | ||
if (value instanceof Float) { | ||
value = value.toDouble() | ||
} | ||
expectedClass = value instanceof Double ? null : "Double" | ||
} else if (par.type == "boolean" | par.type == "boolean_true" | par.type == "boolean_false") { | ||
expectedClass = value instanceof Boolean ? null : "Boolean" | ||
} else if (par.type == "file") { | ||
if (stage == "output" || par.direction == "input") { | ||
if (value instanceof File) { | ||
value = value.toPath() | ||
// cast to boolean if need ben | ||
if (value instanceof String) { | ||
def valueLower = value.toLowerCase() | ||
if (valueLower == "true") { | ||
value = true | ||
} else if (valueLower == "false") { | ||
value = false | ||
} | ||
expectedClass = value instanceof Path ? null : "Path" | ||
} else { // stage == "input" && par.direction == "output" | ||
if (value instanceof GString) { | ||
value = value.toString() | ||
} | ||
expectedClass = value instanceof String ? null : "String" | ||
} | ||
expectedClass = value instanceof Boolean ? null : "Boolean" | ||
} else if (par.type == "file" && (par.direction == "input" || stage == "output")) { | ||
// cast to path if need be | ||
if (value instanceof String) { | ||
value = file(value, hidden: true) | ||
} | ||
if (value instanceof File) { | ||
value = value.toPath() | ||
} | ||
expectedClass = value instanceof Path ? null : "Path" | ||
} else if (par.type == "file" && stage == "input" && par.direction == "output") { | ||
// cast to string if need be | ||
if (value instanceof GString) { | ||
value = value.toString() | ||
} | ||
expectedClass = value instanceof String ? null : "String" | ||
} else { | ||
// didn't find a match for par.type | ||
expectedClass = par.type | ||
} | ||
|
||
if (expectedClass != null) { | ||
error "Error in module '${key}' id '${id}': ${stage} argument '${par.plainName}' has the wrong type. " + | ||
"Expected type: ${expectedClass}. Found type: ${value.getClass()}" | ||
if (foundClass == null) { | ||
foundClass = value.getClass().getName() | ||
} | ||
throw new UnexpectedArgumentTypeException(errorIdentifier, stage, par.plainName, expectedClass, foundClass) | ||
} | ||
|
||
return value | ||
} | ||
} |
25 changes: 0 additions & 25 deletions
25
src/main/resources/io/viash/platforms/nextflow/arguments/_processArgumentGroup.nf
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 0 additions & 20 deletions
20
src/main/resources/io/viash/platforms/nextflow/channel/_guessParamListFormat.nf
This file was deleted.
Oops, something went wrong.
107 changes: 107 additions & 0 deletions
107
src/main/resources/io/viash/platforms/nextflow/channel/_parseParamList.nf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/** | ||
* Figure out the param list format based on the file extension | ||
* | ||
* @param param_list A String containing the path to the parameter list file. | ||
* | ||
* @return A String containing the format of the parameter list file. | ||
*/ | ||
def _paramListGuessFormat(param_list) { | ||
if (param_list !instanceof String) { | ||
"asis" | ||
} else if (param_list.endsWith(".csv")) { | ||
"csv" | ||
} else if (param_list.endsWith(".json") || param_list.endsWith(".jsn")) { | ||
"json" | ||
} else if (param_list.endsWith(".yaml") || param_list.endsWith(".yml")) { | ||
"yaml" | ||
} else { | ||
"yaml_blob" | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Read the param list | ||
* | ||
* @param param_list One of the following: | ||
* - A String containing the path to the parameter list file (csv, json or yaml), | ||
* - A yaml blob of a list of maps (yaml_blob), | ||
* - Or a groovy list of maps (asis). | ||
* @param config A Map of the Viash configuration. | ||
* | ||
* @return A List of Maps containing the parameters. | ||
*/ | ||
def _parseParamList(param_list, Map config) { | ||
// first determine format by extension | ||
def paramListFormat = _paramListGuessFormat(param_list) | ||
|
||
def paramListPath = (paramListFormat != "asis" && paramListFormat != "yaml_blob") ? | ||
file(param_list, hidden: true) : | ||
null | ||
|
||
// get the correct parser function for the detected params_list format | ||
def paramSets = [] | ||
if (paramListFormat == "asis") { | ||
paramSets = param_list | ||
} else if (paramListFormat == "yaml_blob") { | ||
paramSets = readYamlBlob(param_list) | ||
} else if (paramListFormat == "yaml") { | ||
paramSets = readYaml(paramListPath) | ||
} else if (paramListFormat == "json") { | ||
paramSets = readJson(paramListPath) | ||
} else if (paramListFormat == "csv") { | ||
paramSets = readCsv(paramListPath) | ||
} else { | ||
error "Format of provided --param_list not recognised.\n" + | ||
"Found: '$paramListFormat'.\n" + | ||
"Expected: a csv file, a json file, a yaml file,\n" + | ||
"a yaml blob or a groovy list of maps." | ||
} | ||
|
||
// data checks | ||
assert paramSets instanceof List: "--param_list should contain a list of maps" | ||
for (value in paramSets) { | ||
assert value instanceof Map: "--param_list should contain a list of maps" | ||
} | ||
|
||
// id is argument | ||
def idIsArgument = config.functionality.allArguments.any{it.plainName == "id"} | ||
|
||
// Reformat from List<Map> to List<Tuple2<String, Map>> by adding the ID as first element of a Tuple2 | ||
paramSets = paramSets.collect({ data -> | ||
def id = data.id | ||
if (!idIsArgument) { | ||
data = data.findAll{k, v -> k != "id"} | ||
} | ||
[id, data] | ||
}) | ||
|
||
// Split parameters with 'multiple: true' | ||
paramSets = paramSets.collect({ id, data -> | ||
data = _splitParams(data, config) | ||
[id, data] | ||
}) | ||
|
||
// The paths of input files inside a param_list file may have been specified relatively to the | ||
// location of the param_list file. These paths must be made absolute. | ||
if (paramListPath) { | ||
paramSets = paramSets.collect({ id, data -> | ||
def new_data = data.collectEntries{ parName, parValue -> | ||
def par = config.functionality.allArguments.find{it.plainName == parName} | ||
if (par && par.type == "file" && par.direction == "input") { | ||
if (parValue instanceof Collection) { | ||
parValue = parValue.collect{path -> | ||
path instanceof String ? paramListPath.resolveSibling(path) : path | ||
} | ||
} else { | ||
parValue = parValue instanceof String ? paramListPath.resolveSibling(parValue) : parValue | ||
} | ||
} | ||
[parName, parValue] | ||
} | ||
[id, new_data] | ||
}) | ||
} | ||
|
||
return paramSets | ||
} |
Oops, something went wrong.