Skip to content

Commit

Permalink
Add Toree API compatibility option
Browse files Browse the repository at this point in the history
  • Loading branch information
alexarchambault committed Jun 21, 2023
1 parent ec47c3b commit 26c995a
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ final case class LauncherOptions(
connectionFile: Option[String] = None,
variableInspector: Option[Boolean] = None,
toreeMagics: Option[Boolean] = None,
toreeApi: Option[Boolean] = None,
toreeCompatibility: Option[Boolean] = None,
color: Option[Boolean] = None,
@HelpMessage("Send log to a file rather than stderr")
@ValueDescription("/path/to/log-file")
Expand Down Expand Up @@ -41,6 +43,10 @@ final case class LauncherOptions(
b ++= Seq(s"--variable-inspector=$value")
for (value <- toreeMagics)
b ++= Seq(s"--toree-magics=$value")
for (value <- toreeApi)
b ++= Seq(s"--toree-api=$value")
for (value <- toreeCompatibility)
b ++= Seq(s"--toree-compatibility=$value")
for (value <- color)
b ++= Seq(s"--color=$value")
for (value <- logTo)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ final class ScalaInterpreter(
logCtx,
jupyterApi.VariableInspector.enabled,
outputDir = params.outputDir,
compileOnly = params.compileOnly
compileOnly = params.compileOnly,
addToreeApiCompatibilityImport = params.toreeApiCompatibility
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ final case class ScalaInterpreterParams(
useThreadInterrupt: Boolean = false,
outputDir: Either[os.Path, Boolean] = Right(true),
toreeMagics: Boolean = false,
toreeApiCompatibility: Boolean = false,
compileOnly: Boolean = false,
extraClassPath: List[os.Path] = Nil,
initialCellCount: Int = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ object AmmInterpreter {
ImportData("almond.input.Input")
)

private def toreeApiCompatibilityImports = Imports(
ImportData("almond.toree.ToreeCompatibility.KernelToreeOps")
)

/** Instantiate an [[ammonite.interp.Interpreter]] to be used from [[ScalaInterpreter]].
*/
def apply(
Expand All @@ -77,7 +81,8 @@ object AmmInterpreter {
logCtx: LoggerContext,
variableInspectorEnabled: () => Boolean,
outputDir: Either[os.Path, Boolean],
compileOnly: Boolean
compileOnly: Boolean,
addToreeApiCompatibilityImport: Boolean
): ammonite.interp.Interpreter = {

val automaticDependenciesMatchers = automaticDependencies
Expand Down Expand Up @@ -108,6 +113,22 @@ object AmmInterpreter {

try {

val addToreeApiCompatibilityImport0 =
addToreeApiCompatibilityImport && {
val loader = frames0().head.classloader
val clsOpt =
try Some(loader.loadClass("almond.toree.ToreeCompatibility$"))
catch {
case _: ClassNotFoundException =>
None
}
if (clsOpt.isEmpty)
log.error(
"Ignoring Toree API compatibility option, as sh.almond::toree-hooks isn't part of the user class path"
)
clsOpt.nonEmpty
}

log.info("Creating Ammonite interpreter")

val interpParams = ammonite.interp.Interpreter.Parameters(
Expand Down Expand Up @@ -184,7 +205,8 @@ object AmmInterpreter {

val imports = ammonite.main.Defaults.replImports ++
ammonite.interp.Interpreter.predefImports ++
almondImports
almondImports ++
(if (addToreeApiCompatibilityImport0) toreeApiCompatibilityImports else Imports())
for ((e, _) <- ammInterp0.initializePredef(Nil, customPredefs, extraBridges, imports))
e match {
case Res.Failure(msg) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ object TestUtil {

private case class Options(
predef: List[String] = Nil,
toreeMagics: Boolean = false
toreeMagics: Boolean = false,
toreeApi: Boolean = false
)

private val optionsParser: caseapp.Parser[Options] = caseapp.Parser.derive
Expand All @@ -125,7 +126,8 @@ object TestUtil {
initialColors = Colors.BlackWhite,
updateBackgroundVariablesEcOpt = Some(new SequentialExecutionContext),
predefFiles = opt.predef.map(Paths.get(_)),
toreeMagics = opt.toreeMagics
toreeMagics = opt.toreeMagics,
toreeApiCompatibility = opt.toreeApi
)
},
logCtx = logCtx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ final case class Options(
tmpOutputDirectory: Option[Boolean] = None,

@HelpMessage("Add experimental support for Toree magics")
toreeMagics: Boolean = false,
toreeMagics: Option[Boolean] = None,
@HelpMessage("Add experimental support for Toree API compatibility")
toreeApi: Option[Boolean] = None,
@HelpMessage("Add experimental support for Toree compatibility (magics and API)")
toreeCompatibility: Option[Boolean] = None,

@HelpMessage("Enable or disable color cell output upon startup (enabled by default, pass --color=false to disable)")
color: Boolean = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ object ScalaKernel extends CaseApp[Options] {
options.tmpOutputDirectory
.getOrElse(true) // Create tmp output dir by default
},
toreeMagics = options.toreeMagics,
toreeMagics = options.toreeMagics.orElse(options.toreeCompatibility).getOrElse(false),
toreeApiCompatibility =
options.toreeApi.orElse(options.toreeCompatibility).getOrElse(false),
compileOnly = options.compileOnly,
extraClassPath = options.extraClassPath
.filter(_.trim.nonEmpty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,24 +349,37 @@ object Tests {
}
}

def toreeHtml()(implicit sessionId: SessionId, runner: Runner): Unit =
runner.withSession("--toree-magics") { implicit session =>
def toreeHtml()(implicit sessionId: SessionId, runner: Runner): Unit = {
val launcherOptions =
if (runner.differedStartUp)
Seq("--shared-dependencies", "sh.almond::toree-hooks:_")
else
Seq("--shared", "sh.almond::toree-hooks")
runner.withLauncherOptionsSession(launcherOptions: _*)("--toree-magics", "--toree-api") {
implicit session =>

execute(
"""%%html
|<p>
|<b>Hello</b>
|</p>
|""".stripMargin,
"",
displaysHtml = Seq(
"""<p>
execute(
"""%%html
|<p>
|<b>Hello</b>
|</p>
|""".stripMargin
|""".stripMargin,
"",
displaysHtml = Seq(
"""<p>
|<b>Hello</b>
|</p>
|""".stripMargin
)
)

execute(
"""kernel.display.html("<p><b>Hello</b></p>")""",
"",
displaysHtml = Seq("<p><b>Hello</b></p>")
)
)
}
}

private def java17Cmd(): String = {
val isAtLeastJava17 =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package almond.toree

import almond.interpreter.api.DisplayData
import ammonite.interp.api.InterpAPI

import java.io.{InputStream, PrintStream}
import java.net.URI
import java.nio.file.Paths

/** Import the members of this object to add source-compatibility for some Toree API calls, such as
* 'kernel.display', or 'kernel.addJars'.
*/
object ToreeCompatibility {
implicit class KernelToreeOps(private val kernel: almond.api.JupyterApi) {

def display: ToreeDisplayMethodsLike =
new ToreeDisplayMethodsLike {
def content(mimeType: String, data: String) =
kernel.publish.display(DisplayData(Map(mimeType -> data)))
def clear(wait: Boolean = false) =
// no-op, not sure what we're supposed to do here…
()
}

def out: PrintStream = System.out
def err: PrintStream = System.err
def in: InputStream = System.in

def addJars(uris: URI*)(implicit interp: InterpAPI): Unit = {
val (fileUris, other) = uris.partition(_.getScheme == "file")
for (uri <- other)
System.err.println(s"Warning: ignoring $uri")
val files = fileUris.map(Paths.get(_)).map(os.Path(_, os.pwd))
interp.load.cp(files)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package almond.toree

trait ToreeDisplayMethodsLike {
def content(mimeType: String, data: String): Unit
def html(data: String): Unit = content("text/html", data)
def javascript(data: String): Unit = content("application/javascript", data)
def clear(wait: Boolean = false): Unit
}

0 comments on commit 26c995a

Please sign in to comment.