使用 SBT 管理同时包含 Scala 和 Python 的项目

Using SBT to manage projects that contain both Scala and Python

在当前的项目中,我构建了 Python 与特定数据源交互的代码;现在,我正在构建 Scala 版本。

我重新安排了一些东西,以便所有 Python 代码都位于我的 Scala 代码的 SBT 项目中的 src/main/python 中,但这让我开始思考:是否有任何好的集成方式两者之间的项目管理?要设置 SBT 以便我可以 运行 我的 Python distutils installation/sdist 生成或 sphinx 文档生成作为 SBT 任务?

或者,更一般地说:是否有通过 SBT 执行任意系统任务的标准方法?运行

来自文档 (http://www.scala-sbt.org/0.13/docs/Process.html):

sbt includes a process library to simplify working with external processes. The library is available without import in build definitions and at the interpreter started by the consoleProject task.

To run an external command, follow it with an exclamation mark !:

"find project -name *.jar" !

您可以创建一个 python 压缩源文件的任务。本例依赖组装任务:

  lazy val pythonAssembly = TaskKey[Unit]("pythonAssembly", "Zips all files in src/main/python")

  lazy val pythonAssemblyTask = pythonAssembly := {
    val baseDir = sourceDirectory.value
    val targetDir = assembly.value.getParentFile.getParent
    val target = new File(targetDir + s"/python/rfu-api-client-python-${Commons.appVersion}.zip")
    val pythonBaseDir = new File(baseDir + "/main/python")
    val pythonFiles = Path.allSubpaths(pythonBaseDir)

    println("Zipping files in " + pythonBaseDir)
    pythonFiles foreach { case (_, s) => println(s) }
    IO.zip(pythonFiles, target)
    println(s"Created $target")

运行 Python python 代码的单元测试 with SBT 测试任务 I在 build.sbt:

中做了这个
//define task that should be run with tests.
val testPythonTask = TaskKey[Unit]("testPython", "Run python tests.")

val command = "python3 -m unittest app_test.py"
val workingDirectory = new File("python/working/directory")

testPythonTask := {
  val s: TaskStreams = streams.value
  s.log.info("Executing task testPython")
  Process(command,
    // optional
    workingDirectory,
    // optional system variables
    "CLASSPATH" -> "path/to.jar",
    "OTHER_SYS_VAR" -> "other_value") ! s.log
}

//attach custom test task to default test tasks
test in Test := {
  testPythonTask.value
  (test in Test).value
}

testOnly in Test := {
  testPythonTask.value
  (testOnly in Test).value
}