
org.jetbrains.kotlinx.jupyter.test.repl.IntegrationApiTests.kt Maven / Gradle / Ivy
package org.jetbrains.kotlinx.jupyter.test.repl
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeInstanceOf
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import org.jetbrains.kotlinx.jupyter.api.CodePreprocessor
import org.jetbrains.kotlinx.jupyter.api.DeclarationKind
import org.jetbrains.kotlinx.jupyter.api.KotlinKernelHost
import org.jetbrains.kotlinx.jupyter.api.MimeTypes
import org.jetbrains.kotlinx.jupyter.api.Renderable
import org.jetbrains.kotlinx.jupyter.api.libraries.ColorScheme
import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinition
import org.jetbrains.kotlinx.jupyter.api.libraries.createLibrary
import org.jetbrains.kotlinx.jupyter.api.libraries.mavenLocal
import org.jetbrains.kotlinx.jupyter.api.libraries.repositories
import org.jetbrains.kotlinx.jupyter.exceptions.ReplCompilerException
import org.jetbrains.kotlinx.jupyter.libraries.LibraryResolver
import org.jetbrains.kotlinx.jupyter.libraries.buildDependenciesInitCode
import org.jetbrains.kotlinx.jupyter.libraries.createLibraryHttpUtil
import org.jetbrains.kotlinx.jupyter.repl.ReplForJupyter
import org.jetbrains.kotlinx.jupyter.repl.creating.createRepl
import org.jetbrains.kotlinx.jupyter.test.TestDisplayHandler
import org.jetbrains.kotlinx.jupyter.test.classpath
import org.jetbrains.kotlinx.jupyter.test.evalError
import org.jetbrains.kotlinx.jupyter.test.evalEx
import org.jetbrains.kotlinx.jupyter.test.evalInterrupted
import org.jetbrains.kotlinx.jupyter.test.evalRaw
import org.jetbrains.kotlinx.jupyter.test.evalRendered
import org.jetbrains.kotlinx.jupyter.test.library
import org.jetbrains.kotlinx.jupyter.test.testLoggerFactory
import org.jetbrains.kotlinx.jupyter.test.testRepositories
import org.jetbrains.kotlinx.jupyter.test.toLibraries
import org.jetbrains.kotlinx.jupyter.util.EMPTY
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertDoesNotThrow
import kotlin.reflect.KClass
import kotlin.reflect.full.declaredMemberProperties
import kotlin.test.assertNull
class IntegrationApiTests {
private val httpUtil = createLibraryHttpUtil(testLoggerFactory)
private fun makeRepl(libraryResolver: LibraryResolver): ReplForJupyter {
return createRepl(
httpUtil,
scriptClasspath = classpath,
homeDir = null,
mavenRepositories = testRepositories,
libraryResolver = libraryResolver,
)
}
private fun makeRepl(vararg libs: Pair): ReplForJupyter {
return makeRepl(libs.toList().toLibraries())
}
@Test
fun `field handling`() {
val lib =
"mylib" to
library {
val generated = mutableSetOf()
updateVariable> { list, property ->
val size = list.size
val className = "TypedIntList$size"
val propRef = if (property.returnType.isMarkedNullable) property.name + "!!" else property.name
val converter = "$className($propRef)"
if (generated.contains(size)) {
execute(converter).name!!
} else {
val properties = (list.indices).joinToString("\n") { "val value$it : Int get() = list[$it]" }
val classDeclaration =
"""
class $className(val list: List): List by list {
$properties
}
$converter
""".trimIndent()
generated.add(size)
execute(classDeclaration).name!!
}
}
}
val repl = makeRepl(lib)
// create list 'l' of size 3
val code1 =
"""
%use mylib
val l = listOf(1,2,3)
""".trimIndent()
repl.evalRaw(code1)
assertEquals(3, repl.evalRaw("l.value2"))
// create list 'q' of the same size 3
repl.evalRaw("val q = l.asReversed()")
assertEquals(1, repl.evalRaw("q.value2"))
// check that 'l' and 'q' have the same types
assertEquals(
3,
repl.evalRaw(
"""var a = l
a = q
a.value0
""".trimMargin(),
),
)
// create a list of size 6
repl.evalRaw("val w = l + a")
assertEquals(3, repl.evalRendered("w.value3"))
// check that 'value3' is not available for list 'l'
repl.evalError("l.value3")
repl.evalRaw("val e: List? = w.take(5)")
val res = repl.evalRendered("e")
assertEquals("TypedIntList5", res!!.javaClass.simpleName)
}
@Test
fun `after cell execution`() {
val lib =
"mylib" to
library {
afterCellExecution { _, _ ->
execute("2")
}
}
val repl = makeRepl(lib).trackExecution()
repl.execute("%use mylib\n1")
assertEquals(2, repl.executedCodes.size)
assertEquals(1, repl.results[0])
assertEquals(2, repl.results[1])
}
@Test
fun `code preprocessors`() {
val lib =
"mylib" to
library {
addCodePreprocessor(
object : CodePreprocessor {
override fun process(
code: String,
host: KotlinKernelHost,
): CodePreprocessor.Result {
return CodePreprocessor.Result(code.replace("2+2", "3+3"))
}
override fun accepts(code: String): Boolean {
return code == "2+2"
}
},
)
addCodePreprocessor(
object : CodePreprocessor {
override fun process(
code: String,
host: KotlinKernelHost,
): CodePreprocessor.Result {
return CodePreprocessor.Result(code.replace("1", "2"))
}
},
)
}
val repl = makeRepl(lib).trackExecution()
repl.execute("%use mylib")
val result = repl.execute("1+1").result.value
result shouldBe 6
}
@Test
fun `result code preprocessor`() {
val displays = mutableListOf()
val repl =
createRepl(
httpUtil,
scriptClasspath = classpath,
homeDir = null,
mavenRepositories = testRepositories,
displayHandler = TestDisplayHandler(displays),
)
repl.eval {
addLibrary(
createLibrary(repl.notebook) {
afterCellExecution { snippetInstance, result ->
@Suppress("UNCHECKED_CAST")
val kClass: KClass = snippetInstance::class as KClass
if (result.name != null) return@afterCellExecution
val cellDeclarations = notebook.currentCell!!.declarations
val propNamesWithOrder =
cellDeclarations
.filter { it.kind == DeclarationKind.PROPERTY }
.withIndex()
.associate {
it.value.name to it.index
}
val props = kClass.declaredMemberProperties
val lastProp =
props.maxByOrNull { prop ->
propNamesWithOrder[prop.name] ?: -1
} ?: return@afterCellExecution
lastProp.get(snippetInstance)?.let { this.display(it, null) }
}
},
)
}
repl.evalEx(
"""
val xyz=7
val abc = 9
val po = 97
""".trimIndent(),
)
repl.evalEx("var myVar = true")
displays shouldBe listOf(97, true)
}
@Test
fun `renderable objects`() {
val repl = makeRepl()
repl.evalRaw(
"""
@file:DependsOn("src/test/testData/kotlin-jupyter-api-test-0.0.16.jar")
""".trimIndent(),
)
val res =
repl.evalRendered(
"""
ses.visualizeColor("red")
""".trimIndent(),
)
val result = res as Renderable
val json = result.render(repl.notebook).toJson(Json.EMPTY, null)
val jsonData = json["data"] as JsonObject
val htmlString = jsonData[MimeTypes.HTML] as JsonPrimitive
kotlin.test.assertEquals("""red""", htmlString.content)
}
@Test
fun `library options`() {
val libs =
listOf(
"lib" to
"""
{
"dependencies": [
"src/test/testData/kotlin-jupyter-api-test-0.0.18.jar"
]
}
""".trimIndent(),
)
val repl = makeRepl(libs.toLibraries())
repl.evalRaw("%use lib(a = 42, b=foo)")
val res = repl.evalRaw("integrationOptions")
res.shouldBeInstanceOf
© 2015 - 2025 Weber Informatics LLC | Privacy Policy