Skip to content

Commit 31706ec

Browse files
committed
refactor languages <> scripts
1 parent 0c93222 commit 31706ec

22 files changed

Lines changed: 255 additions & 61 deletions

src/main/scala/io/viash/config/Config.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,8 @@ object Config extends Logging {
612612
val yaml = header.map(s => s.drop(3)).mkString("\n")
613613
val code = body.mkString("\n")
614614

615-
val script = Script(dest = Some(basename), text = Some(code), `type` = scriptObj.`type`)
615+
val scriptType = s"${scriptObj.id}_script"
616+
val script = Script(dest = Some(basename), text = Some(code), `type` = scriptType)
616617

617618
(yaml, Some(script))
618619
} else {

src/main/scala/io/viash/config/resources/BashScript.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import io.viash.schemas._
2424
import java.net.URI
2525
import io.viash.helpers.Bash
2626
import io.viash.config.Config
27+
import io.viash.languages.{Bash => BashLang}
2728

2829
@description("""An executable Bash script.
2930
|When defined in resources, only the first entry will be executed when running the built component or when running `viash run`.
@@ -37,19 +38,20 @@ case class BashScript(
3738
parent: Option[URI] = None,
3839

3940
@description("Specifies the resource as a Bash script.")
40-
`type`: String = BashScript.`type`
41+
`type`: String = "bash_script"
4142
) extends Script {
42-
val companion = BashScript
43+
val language = BashLang
4344
def copyResource(path: Option[String], text: Option[String], dest: Option[String], is_executable: Option[Boolean], parent: Option[URI]): Resource = {
4445
copy(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
4546
}
4647

4748
def generateInjectionMods(argsMetaAndDeps: Map[String, List[Argument[_]]], config: Config): ScriptInjectionMods = {
4849

49-
val fullCode = s"""${language.viashParseYamlCode}
50+
val fullCode = s"""${language.viashParseJsonCode}
5051

51-
_viash_yaml_content=$$(cat)
52-
ViashParseYamlBash <<< "$$_viash_yaml_content"
52+
# Parse JSON parameters
53+
_viash_json_content=$$(cat "$$VIASH_WORK_PARAMS")
54+
ViashParseJsonBash <<< "$$_viash_json_content"
5355

5456
"""
5557
ScriptInjectionMods(params = fullCode)

src/main/scala/io/viash/config/resources/CSharpScript.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import io.viash.schemas._
2424
import java.net.URI
2525
import io.viash.helpers.Bash
2626
import io.viash.config.Config
27+
import io.viash.languages.CSharp
2728

2829
@description("""An executable C# script.
2930
|When defined in resources, only the first entry will be executed when running the built component or when running `viash run`.
@@ -37,26 +38,25 @@ case class CSharpScript(
3738
parent: Option[URI] = None,
3839

3940
@description("Specifies the resource as a C# script.")
40-
`type`: String = CSharpScript.`type`
41+
`type`: String = "csharp_script"
4142
) extends Script {
42-
val companion = CSharpScript
43+
val language = CSharp
4344
def copyResource(path: Option[String], text: Option[String], dest: Option[String], is_executable: Option[Boolean], parent: Option[URI]): Resource = {
4445
copy(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
4546
}
4647

4748
def generateInjectionMods(argsMetaAndDeps: Map[String, List[Argument[_]]], config: Config): ScriptInjectionMods = {
4849
// Extract only the class and functions, not the main execution part
49-
// TODO: remove takewhile
50-
val helperFunctions = language.viashParseYamlCode
50+
val helperFunctions = language.viashParseJsonCode
5151
.split("\n")
5252
.takeWhile(line => !line.contains("if (Args.Length == 0)"))
5353
.mkString("\n")
5454

5555
val paramsCode = if (argsMetaAndDeps.nonEmpty) {
56-
// Parse YAML once and extract all sections
57-
val parseOnce = "// Parse YAML parameters once and extract all sections\nvar _viashYamlData = ViashYamlParser.ParseYaml();\n"
56+
// Parse JSON once and extract all sections
57+
val parseOnce = "// Parse JSON parameters once and extract all sections\nvar _viashJsonData = ViashJsonParser.ParseJson();\n"
5858
val extractSections = argsMetaAndDeps.map { case (dest, _) =>
59-
s"var $dest = _viashYamlData.ContainsKey(\"$dest\") ? (Dictionary<string, object>)_viashYamlData[\"$dest\"] : new Dictionary<string, object>();"
59+
s"var $dest = _viashJsonData.ContainsKey(\"$dest\") ? (Dictionary<string, object>)_viashJsonData[\"$dest\"] : new Dictionary<string, object>();"
6060
}.mkString("\n")
6161

6262
parseOnce + extractSections

src/main/scala/io/viash/config/resources/Executable.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import java.nio.file.Path
2222
import io.viash.config.arguments.Argument
2323
import io.viash.schemas._
2424
import io.viash.config.Config
25+
import io.viash.languages.Language
2526

2627
@description("An executable file.")
2728
@subclass("executable")
@@ -35,7 +36,7 @@ case class Executable(
3536
@description("Specifies the resource as an executable.")
3637
`type`: String = "executable"
3738
) extends Script {
38-
val companion = Executable
39+
val language: Language = null // todo: deprecate executable
3940
def copyResource(path: Option[String], text: Option[String], dest: Option[String], is_executable: Option[Boolean], parent: Option[URI]): Resource = {
4041
copy(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
4142
}

src/main/scala/io/viash/config/resources/JavaScriptScript.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import java.net.URI
2424
import io.viash.helpers.Bash
2525
import io.viash.config.Config
2626
import io.viash.config.arguments.{Argument, StringArgument, IntegerArgument, BooleanArgumentBase, LongArgument, DoubleArgument, FileArgument}
27+
import io.viash.languages.JavaScript
2728

2829
@description("""An executable JavaScript script.
2930
|When defined in resources, only the first entry will be executed when running the built component or when running `viash run`.
@@ -37,27 +38,26 @@ case class JavaScriptScript(
3738
parent: Option[URI] = None,
3839

3940
@description("Specifies the resource as a JavaScript script.")
40-
`type`: String = JavaScriptScript.`type`
41+
`type`: String = "javascript_script"
4142
) extends Script {
42-
val companion = JavaScriptScript
43+
val language = JavaScript
4344
def copyResource(path: Option[String], text: Option[String], dest: Option[String], is_executable: Option[Boolean], parent: Option[URI]): Resource = {
4445
copy(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
4546
}
4647

4748
def generateInjectionMods(argsMetaAndDeps: Map[String, List[Argument[_]]], config: Config): ScriptInjectionMods = {
4849
// Extract only the functions, not the main execution part or module exports
49-
// TODO: remove this part
50-
val helperFunctions = language.viashParseYamlCode
50+
val helperFunctions = language.viashParseJsonCode
5151
.split("\n")
5252
.takeWhile(line => !line.contains("if (require.main === module)"))
53-
.filterNot(line => line.contains("if (typeof module !== 'undefined' && module.exports)"))
53+
.filterNot(line => line.contains("module.exports"))
5454
.mkString("\n")
5555

5656
val paramsCode = if (argsMetaAndDeps.nonEmpty) {
57-
// Parse YAML once and extract all sections
58-
val parseOnce = "// Parse YAML parameters once and extract all sections\nlet _viashYamlData = viashParseYaml();\n"
57+
// Parse JSON once and extract all sections
58+
val parseOnce = "// Parse JSON parameters once and extract all sections\nconst _viashJsonData = viashParseJson();\n"
5959
val extractSections = argsMetaAndDeps.map { case (dest, _) =>
60-
s"let $dest = _viashYamlData['$dest'] || {};"
60+
s"const $dest = _viashJsonData['$dest'] || {};"
6161
}.mkString("\n")
6262

6363
parseOnce + extractSections

src/main/scala/io/viash/config/resources/NextflowScript.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import io.circe.syntax._
2929
import io.viash.helpers.circe._
3030
import io.viash.ViashNamespace
3131
import io.viash.config.dependencies.Dependency
32+
import io.viash.languages.Nextflow
3233

3334
@description("""A Nextflow script. Work in progress; added mainly for annotation at the moment.""")
3435
@subclass("nextflow_script")
@@ -43,10 +44,10 @@ case class NextflowScript(
4344
entrypoint: String,
4445

4546
@description("Specifies the resource as a Nextflow script.")
46-
`type`: String = NextflowScript.`type`
47+
`type`: String = "nextflow_script"
4748
) extends Script {
4849

49-
val companion = NextflowScript
50+
val language = Nextflow
5051

5152
def copyResource(path: Option[String], text: Option[String], dest: Option[String], is_executable: Option[Boolean], parent: Option[URI]): Resource = {
5253
copy(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)

src/main/scala/io/viash/config/resources/PythonScript.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import java.net.URI
2424
import _root_.io.viash.helpers.Bash
2525
import io.viash.schemas._
2626
import io.viash.config.Config
27+
import io.viash.languages.Python
2728

2829
@description("""An executable Python script.
2930
|When defined in resources, only the first entry will be executed when running the built component or when running `viash run`.
@@ -37,25 +38,25 @@ case class PythonScript(
3738
parent: Option[URI] = None,
3839

3940
@description("Specifies the resource as a Python script.")
40-
`type`: String = PythonScript.`type`
41+
`type`: String = "python_script"
4142
) extends Script {
42-
val companion = PythonScript
43+
val language = Python
4344
def copyResource(path: Option[String], text: Option[String], dest: Option[String], is_executable: Option[Boolean], parent: Option[URI]): Resource = {
4445
copy(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
4546
}
4647

4748
def generateInjectionMods(argsMetaAndDeps: Map[String, List[Argument[_]]], config: Config): ScriptInjectionMods = {
4849
// Extract only the functions, not the main execution part
49-
val helperFunctions = language.viashParseYamlCode
50+
val helperFunctions = language.viashParseJsonCode
5051
.split("\n")
5152
.takeWhile(line => !line.startsWith("if __name__ == \"__main__\":"))
5253
.mkString("\n")
5354

5455
val paramsCode = if (argsMetaAndDeps.nonEmpty) {
55-
// Parse YAML once and extract all sections
56-
val parseOnce = "# Parse YAML parameters once and extract all sections\n_viash_yaml_data = viash_parse_yaml()\n"
56+
// Parse JSON once and extract all sections
57+
val parseOnce = "# Parse JSON parameters once and extract all sections\n_viash_json_data = viash_parse_json()\n"
5758
val extractSections = argsMetaAndDeps.map { case (dest, _) =>
58-
s"$dest = _viash_yaml_data.get('$dest', {})"
59+
s"$dest = _viash_json_data.get('$dest', {})"
5960
}.mkString("\n")
6061

6162
parseOnce + extractSections

src/main/scala/io/viash/config/resources/RScript.scala

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import io.viash.schemas._
2424

2525
import java.net.URI
2626
import io.viash.config.Config
27+
import io.viash.languages.R
2728

2829
@description("""An executable R script.
2930
|When defined in resources, only the first entry will be executed when running the built component or when running `viash run`.
@@ -37,25 +38,25 @@ case class RScript(
3738
parent: Option[URI] = None,
3839

3940
@description("Specifies the resource as a R script.")
40-
`type`: String = RScript.`type`
41+
`type`: String = "r_script"
4142
) extends Script {
42-
val companion = RScript
43+
val language = R
4344
def copyResource(path: Option[String], text: Option[String], dest: Option[String], is_executable: Option[Boolean], parent: Option[URI]): Resource = {
4445
copy(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
4546
}
4647

4748
def generateInjectionMods(argsMetaAndDeps: Map[String, List[Argument[_]]], config: Config): ScriptInjectionMods = {
4849
// Extract only the functions, not the main execution part
49-
val helperFunctions = language.viashParseYamlCode
50+
val helperFunctions = language.viashParseJsonCode
5051
.split("\n")
5152
.takeWhile(line => !line.contains("if (!interactive() && identical(environment(), globalenv()))"))
5253
.mkString("\n")
5354

5455
val paramsCode = if (argsMetaAndDeps.nonEmpty) {
55-
// Parse YAML once and extract all sections
56-
val parseOnce = "# Parse YAML parameters once and extract all sections\n.viash_yaml_data <- viash_parse_yaml()\n"
56+
// Parse JSON once and extract all sections
57+
val parseOnce = "# Parse JSON parameters once and extract all sections\n.viash_json_data <- viash_parse_json()\n"
5758
val extractSections = argsMetaAndDeps.map { case (dest, _) =>
58-
s"$dest <- if (is.null(.viash_yaml_data[['$dest']])) list() else .viash_yaml_data[['$dest']]"
59+
s"$dest <- if (is.null(.viash_json_data[['$dest']])) list() else .viash_json_data[['$dest']]"
5960
}.mkString("\n")
6061

6162
parseOnce + extractSections
@@ -73,7 +74,7 @@ case class RScript(
7374
|# restore original warn setting
7475
|options(.viash_orig_warn)
7576
|rm(.viash_orig_warn)
76-
|rm(.viash_yaml_data)
77+
|rm(.viash_json_data)
7778
|""".stripMargin
7879
ScriptInjectionMods(params = outCode)
7980
}

src/main/scala/io/viash/config/resources/ScalaScript.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import io.viash.schemas._
2424
import java.net.URI
2525
import io.viash.helpers.Bash
2626
import io.viash.config.Config
27+
import io.viash.languages.{Scala => ScalaLang}
2728

2829
@description("""An executable Scala script.
2930
|When defined in resources, only the first entry will be executed when running the built component or when running `viash run`.
@@ -37,25 +38,25 @@ case class ScalaScript(
3738
parent: Option[URI] = None,
3839

3940
@description("Specifies the resource as a Scala script.")
40-
`type`: String = ScalaScript.`type`
41+
`type`: String = "scala_script"
4142
) extends Script {
42-
val companion = ScalaScript
43+
val language = ScalaLang
4344
def copyResource(path: Option[String], text: Option[String], dest: Option[String], is_executable: Option[Boolean], parent: Option[URI]): Resource = {
4445
copy(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
4546
}
4647

4748
def generateInjectionMods(argsMetaAndDeps: Map[String, List[Argument[_]]], config: Config): ScriptInjectionMods = {
4849
// Extract only the object and functions, not the main execution part
49-
val helperFunctions = language.viashParseYamlCode
50+
val helperFunctions = language.viashParseJsonCode
5051
.split("\n")
5152
.takeWhile(line => !line.contains("if (sys.props.get(\"viash.run.main\").contains(\"true\")"))
5253
.mkString("\n")
5354

5455
val paramsCode = if (argsMetaAndDeps.nonEmpty) {
55-
// Parse YAML once and extract all sections
56-
val parseOnce = "// Parse YAML parameters once and extract all sections\nval _viashYamlData = ViashYamlParser.parseYaml()\n"
56+
// Parse JSON once and extract all sections
57+
val parseOnce = "// Parse JSON parameters once and extract all sections\nval _viashJsonData = ViashJsonParser.parseJson()\n"
5758
val extractSections = argsMetaAndDeps.map { case (dest, _) =>
58-
s"val $dest = _viashYamlData.getOrElse(\"$dest\", Map.empty[String, Any])"
59+
s"val $dest = _viashJsonData.getOrElse(\"$dest\", Map.empty[String, Any])"
5960
}.mkString("\n")
6061

6162
parseOnce + extractSections

src/main/scala/io/viash/config/resources/Script.scala

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ package io.viash.config.resources
2020
import java.net.URI
2121
import io.viash.config.arguments.Argument
2222
import io.viash.config.Config
23-
import io.viash.language.Language
23+
import io.viash.languages.Language
24+
import io.viash.languages.{Bash, Python, R, JavaScript, Nextflow, Scala, CSharp}
2425

2526
trait Script extends Resource {
2627
val language: Language
@@ -37,7 +38,7 @@ trait Script extends Resource {
3738
val mods = generateInjectionMods(argsMetaAndDeps, config)
3839

3940
val viashLines = Array(
40-
companion.commentStr + " The following code has been auto-generated by Viash.",
41+
language.commentStr + " The following code has been auto-generated by Viash.",
4142
mods.params
4243
)
4344

@@ -55,9 +56,9 @@ trait Script extends Resource {
5556
viashLinesWDelimiter ++
5657
lines.slice(endIndex, lines.length)
5758
} else {
58-
Array(companion.commentStr + companion.commentStr + " VIASH START") ++
59+
Array(language.commentStr + language.commentStr + " VIASH START") ++
5960
viashLines ++
60-
Array(companion.commentStr + companion.commentStr + " VIASH END") ++
61+
Array(language.commentStr + language.commentStr + " VIASH END") ++
6162
lines
6263
}
6364
val li2 =
@@ -82,15 +83,15 @@ trait Script extends Resource {
8283
li.mkString("\n")
8384
}
8485

85-
def command(script: String): String = (companion.executor :+ s"\"$script\"").mkString(" ")
86-
def commandSeq(script: String): Seq[String] = companion.executor ++ Seq(script)
86+
def command(script: String): String = (language.executor :+ s"\"$script\"").mkString(" ")
87+
def commandSeq(script: String): Seq[String] = language.executor ++ Seq(script)
8788
}
8889

8990
object Script {
9091
val languages = List(Bash, Python, R, JavaScript, Nextflow, Scala, CSharp)
9192
val extensions =
9293
languages
93-
.map(x => (x.extension.toLowerCase, x))
94+
.flatMap(lang => lang.extensions.map(ext => (ext.toLowerCase, lang)))
9495
.toMap
9596

9697
def fromExt(extension: String): Language = {
@@ -106,25 +107,26 @@ object Script {
106107
entrypoint: Option[String] = None,
107108
`type`: String
108109
): Script = {
110+
val languageId = `type`.replaceAll("_script$", "")
109111

110-
if (`type` != NextflowScript.`type`)
112+
if (languageId != Nextflow.id)
111113
assert(entrypoint.isEmpty, message = s"Entrypoints are not (yet) supported for resources of type ${`type`}.")
112114

113-
`type` match {
114-
case BashScript.`type` =>
115+
languageId match {
116+
case Bash.id =>
115117
BashScript(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
116-
case CSharpScript.`type` =>
118+
case CSharp.id =>
117119
CSharpScript(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
118-
case JavaScriptScript.`type` =>
120+
case JavaScript.id =>
119121
JavaScriptScript(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
120-
case NextflowScript.`type` =>
122+
case Nextflow.id =>
121123
assert(entrypoint.isDefined, "In a Nextflow script, the 'entrypoint' argument needs to be specified.")
122124
NextflowScript(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent, entrypoint = entrypoint.get)
123-
case PythonScript.`type` =>
125+
case Python.id =>
124126
PythonScript(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
125-
case RScript.`type` =>
127+
case R.id =>
126128
RScript(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
127-
case ScalaScript.`type` =>
129+
case Scala.id =>
128130
ScalaScript(path = path, text = text, dest = dest, is_executable = is_executable, parent = parent)
129131
}
130132
}

0 commit comments

Comments
 (0)