
org.jetbrains.kotlinx.jupyter.test.repl.IntegrationApiTests.kt Maven / Gradle / Ivy
package org.jetbrains.kotlinx.jupyter.test.repl
import io.kotest.assertions.throwables.shouldThrow
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.EvalRequestData
import org.jetbrains.kotlinx.jupyter.ReplForJupyter
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.exceptions.ReplEvalRuntimeException
import org.jetbrains.kotlinx.jupyter.libraries.EmptyResolutionInfoProvider
import org.jetbrains.kotlinx.jupyter.libraries.LibraryResolver
import org.jetbrains.kotlinx.jupyter.libraries.buildDependenciesInitCode
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.evalEx
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.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 org.junit.jupiter.api.assertThrows
import kotlin.reflect.KClass
import kotlin.reflect.full.declaredMemberProperties
import kotlin.test.assertNull
class IntegrationApiTests {
private fun makeRepl(libraryResolver: LibraryResolver): ReplForJupyter {
return createRepl(EmptyResolutionInfoProvider, classpath, null, testRepositories, 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'
assertThrows {
repl.evalRaw("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(EmptyResolutionInfoProvider, classpath, null, 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