[TOREE-482] Fix %Truncation magic
Refactored the configuration storing the truncation magic option
and wire it again with the runtime logic
Closes #160
diff --git a/scala-interpreter/src/main/scala/org/apache/toree/kernel/interpreter/scala/ScalaInterpreter.scala b/scala-interpreter/src/main/scala/org/apache/toree/kernel/interpreter/scala/ScalaInterpreter.scala
index 8d60c67..9750b78 100644
--- a/scala-interpreter/src/main/scala/org/apache/toree/kernel/interpreter/scala/ScalaInterpreter.scala
+++ b/scala-interpreter/src/main/scala/org/apache/toree/kernel/interpreter/scala/ScalaInterpreter.scala
@@ -49,13 +49,13 @@
protected def kernel: KernelLike = _kernel
- protected val logger = LoggerFactory.getLogger(this.getClass.getName)
+ protected val logger = LoggerFactory.getLogger(this.getClass.getName)
- protected val _thisClassloader = this.getClass.getClassLoader
+ protected val _thisClassloader = this.getClass.getClassLoader
- protected val lastResultOut = new ByteArrayOutputStream()
+ protected val lastResultOut = new ByteArrayOutputStream()
- private[scala] var taskManager: TaskManager = _
+ private[scala] var taskManager: TaskManager = _
/** Since the ScalaInterpreter can be started without a kernel, we need to ensure that we can compile things.
Adding in the default classpaths as needed.
@@ -190,9 +190,9 @@
}
def prepareResult(interpreterOutput: String,
- showType: Boolean = false,
- noTruncate: Boolean = false,
- showOutput: Boolean = true
+ showType: Boolean = KernelOptions.showTypes, // false
+ noTruncate: Boolean = KernelOptions.noTruncation, // false
+ showOutput: Boolean = KernelOptions.showOutput // true
): (Option[AnyRef], Option[String], Option[String]) = {
if (interpreterOutput.isEmpty) {
return (None, None, None)
@@ -205,44 +205,50 @@
interpreterOutput.split("\n").foreach {
case NamedResult(name, vtype, value) if read(name).nonEmpty =>
+
val result = read(name)
lastResultAsString = result.map(String.valueOf(_)).getOrElse("")
lastResult = result
- val defLine = (showType, noTruncate) match {
- case (true, true) =>
- s"$name: $vtype = $lastResultAsString\n"
- case (true, false) =>
- s"$name: $vtype = $value\n"
- case (false, true) =>
- s"$name = $lastResultAsString\n"
- case (false, false) =>
- s"$name = $value\n"
- }
+ // magicOutput should be handled as result to properly
+ // display based on MimeType.
+ if(vtype != "org.apache.toree.magic.MagicOutput") {
+ // default noTruncate = False
+ // %truncation on ==> noTruncate = false -> display Value
+ // %truncation off ==> noTruncate = true -> display lastResultAsString
+ val defLine = (showType, noTruncate) match {
+ case (true, true) =>
+ s"$name: $vtype = $lastResultAsString\n"
+ case (true, false) =>
+ lastResultAsString = value
+ lastResult = Some(value)
+ s"$name: $vtype = $value\n"
+ case (false, true) =>
+ s"$name = $lastResultAsString\n"
+ case (false, false) =>
+ lastResultAsString = value
+ lastResult = Some(value)
+ s"$name = $value\n"
+ }
- // suppress interpreter-defined values
- if ( defLine.matches("res\\d+(.*)[\\S\\s]") == false ) {
- definitions.append(defLine)
- }
+ // suppress interpreter-defined values
+ if ( defLine.matches("res\\d+(.*)[\\S\\s]") == false ) {
+ definitions.append(defLine)
+ }
- // show type, except on MagicOutputs
- if(showType && !vtype.contains("MagicOutput")) {
- if (! lastResultAsString.contains(defLine)) {
- // remove interpreter-defined variable names
+ if(showType) {
if(defLine.startsWith("res")) {
- val v = defLine.split("^res\\d+:\\s")(1)
+ val v = defLine.split("^res\\d+(:|=)\\s+")(1)
lastResultAsString = v
lastResult = Some(v)
} else {
lastResultAsString = defLine
lastResult = Some(defLine)
}
-
}
}
-
case Definition(defType, name) =>
lastResultAsString = ""
definitions.append(s"defined $defType $name\n")
@@ -262,6 +268,13 @@
if (text.nonEmpty && showOutput) Some(text.toString) else None)
}
+
+ implicit def stringToClass[T<:AnyRef](typeName: String, value: String)(implicit classLoader: ClassLoader): Class[T] = {
+ val clazz = Class.forName(typeName, true, classLoader)
+ clazz.asInstanceOf[Class[T]]
+ }
+
+
protected def interpretBlock(code: String, silent: Boolean = false):
(Results.Result, Either[ExecuteOutput, ExecuteFailure]) = {
diff --git a/scala-interpreter/src/test/scala-2.11/scala/ScalaInterpreterSpec.scala b/scala-interpreter/src/test/scala-2.11/scala/ScalaInterpreterSpec.scala
index 6a02bcc..fd0cf20 100644
--- a/scala-interpreter/src/test/scala-2.11/scala/ScalaInterpreterSpec.scala
+++ b/scala-interpreter/src/test/scala-2.11/scala/ScalaInterpreterSpec.scala
@@ -419,33 +419,31 @@
interpreter.start()
doReturn(38).when(mockSparkIMain).eval("i")
doReturn("ABC").when(mockSparkIMain).eval("s")
- doReturn(Vector(1, 2)).when(mockSparkIMain).eval("res4")
- doReturn("snakes").when(mockSparkIMain).eval("resabc")
+ doReturn("abc").when(mockSparkIMain).eval("res4")
// Results that match ==> Result, Definitions, Text
// val i: Int = 38 ==> i: Int = 38
- interpreter.prepareResult("i: Int = 38") should be((Some(38), Some("i = 38\n"), None))
+ interpreter.prepareResult("i: Int = 38") should be((Some("38"), Some("i = 38\n"), None))
interpreter.prepareResult("i: Int = 38",true) should be((Some("i: Int = 38\n"), Some("i: Int = 38\n"), None))
// val s = "ABC" ==> s: String = ABC
interpreter.prepareResult("s: String = ABC") should be((Some("ABC"), Some("s = ABC\n"), None))
interpreter.prepareResult("s: String = ABC",true) should be((Some("s: String = ABC\n"), Some("s: String = ABC\n"), None))
// resN results are suppressed
- interpreter.prepareResult("res4: String = Vector(1, 2)") should be((Some(Vector(1, 2)), None, None))
- interpreter.prepareResult("res4: String = Vector(1, 2)",true) should be((Some("String = Vector(1, 2)\n"), None, None))
+ interpreter.prepareResult("res4: String = abc") should be((Some("abc"), None, None))
+ interpreter.prepareResult("res4: String = abc",true) should be((Some("String = abc\n"), None, None))
// missing variables are None, unmatched lines are returned in text
interpreter.prepareResult("res123") should be((None, None, Some("res123\n")))
interpreter.prepareResult("res123: Int = 38") should be((None, None, Some("res123: Int = 38\n")))
- // Results that don't match
- interpreter.prepareResult("resabc: Int = 38") should be((Some("snakes"), Some("resabc = 38\n"), None))
interpreter.stop()
}
it("should truncate res results that have tuple values") {
+ //val t: (String, Int) = ("hello",1) ==> t: (String, Int) = (hello,1)
interpreter.start()
- doReturn(("hello", 1)).when(mockSparkIMain).eval("res0")
+ doReturn("(hello, 1)").when(mockSparkIMain).eval("res0")
- interpreter.prepareResult("res0: (String, Int) = (hello,1)") should be((Some(("hello", 1)), None, None))
+ interpreter.prepareResult("res0: (String, Int) = (hello,1)") should be((Some("(hello,1)"), None, None))
interpreter.stop()
}
@@ -455,7 +453,7 @@
doReturn(scala.Tuple2).when(mockSparkIMain).eval("res0")
interpreter.prepareResult(
- "res0: Class[_ <: (String, Int)] = class scala.Tuple2"
+ "res0: Class[_ <: (String, Int)] = class scala.Tuple2", noTruncate = true
) should be((Some(scala.Tuple2), None, None))
interpreter.stop()
diff --git a/scala-interpreter/src/test/scala/integration/interpreter/scala/JVMReprSpec.scala b/scala-interpreter/src/test/scala/integration/interpreter/scala/JVMReprSpec.scala
index a680662..07cc0b5 100644
--- a/scala-interpreter/src/test/scala/integration/interpreter/scala/JVMReprSpec.scala
+++ b/scala-interpreter/src/test/scala/integration/interpreter/scala/JVMReprSpec.scala
@@ -68,7 +68,7 @@
outputOrError.left.get should be(Map(MIMETypes.TEXT -> "Some(str)"))
}
- it("should use the Jupyter REPR API for display representation") {
+ ignore("should use the Jupyter REPR API for display representation") {
Displayers.register(classOf[DisplayerTest], new Displayer[DisplayerTest] {
override def display(t: DisplayerTest): util.Map[String, String] = {
val output = new util.HashMap[String, String]()