Skip to content

Commit 71853eb

Browse files
committed
Refactor rendering API
1 parent ccce3d3 commit 71853eb

File tree

16 files changed

+72
-51
lines changed

16 files changed

+72
-51
lines changed

jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/Notebook.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,5 @@ interface Notebook {
6868
* Renderers processor gives an ability to render values and
6969
* and add new renderers
7070
*/
71-
val renderersProcessor: TypeRenderersProcessor
71+
val renderersProcessor: RenderersProcessor
7272
}

jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/TypeRenderersProcessor.kt renamed to jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/RenderersProcessor.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ package org.jetbrains.kotlinx.jupyter.api
33
import org.jetbrains.kotlinx.jupyter.api.libraries.ExecutionHost
44

55
/**
6-
* [TypeRenderersProcessor] is responsible for rendering objects.
6+
* [RenderersProcessor] is responsible for rendering objects.
77
* You may use it to render values exactly like notebook renders results,
88
* and also register new renderers in runtime.
99
*/
10-
interface TypeRenderersProcessor {
10+
interface RenderersProcessor {
1111
/**
1212
* Renders [value] in context of this execution [host]
1313
*/
@@ -17,5 +17,5 @@ interface TypeRenderersProcessor {
1717
* Adds new [renderer] for this notebook.
1818
* Don't turn on the optimizations for [PrecompiledRendererTypeHandler]
1919
*/
20-
fun registerWithoutOptimizing(renderer: RendererTypeHandler)
20+
fun registerWithoutOptimizing(renderer: RendererHandler)
2121
}

jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import org.jetbrains.kotlinx.jupyter.api.FileAnnotationCallback
1515
import org.jetbrains.kotlinx.jupyter.api.FileAnnotationHandler
1616
import org.jetbrains.kotlinx.jupyter.api.KotlinKernelHost
1717
import org.jetbrains.kotlinx.jupyter.api.Notebook
18+
import org.jetbrains.kotlinx.jupyter.api.RendererHandler
1819
import org.jetbrains.kotlinx.jupyter.api.RendererTypeHandler
1920
import org.jetbrains.kotlinx.jupyter.api.ResultHandlerExecution
2021
import org.jetbrains.kotlinx.jupyter.api.SubtypeRendererTypeHandler
@@ -32,7 +33,7 @@ abstract class JupyterIntegration : LibraryDefinitionProducer {
3233

3334
class Builder(val notebook: Notebook) {
3435

35-
private val renderers = mutableListOf<RendererTypeHandler>()
36+
private val renderers = mutableListOf<RendererHandler>()
3637

3738
private val init = mutableListOf<ExecutionCallback<*>>()
3839

@@ -58,6 +59,11 @@ abstract class JupyterIntegration : LibraryDefinitionProducer {
5859

5960
private val codePreprocessors = mutableListOf<CodePreprocessor>()
6061

62+
fun addRenderer(handler: RendererHandler) {
63+
renderers.add(handler)
64+
}
65+
66+
// Left for ABI compatibility
6167
fun addRenderer(handler: RendererTypeHandler) {
6268
renderers.add(handler)
6369
}

jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinition.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import org.jetbrains.kotlinx.jupyter.api.ExecutionCallback
77
import org.jetbrains.kotlinx.jupyter.api.FieldHandler
88
import org.jetbrains.kotlinx.jupyter.api.FileAnnotationHandler
99
import org.jetbrains.kotlinx.jupyter.api.KotlinKernelVersion
10-
import org.jetbrains.kotlinx.jupyter.api.RendererTypeHandler
10+
import org.jetbrains.kotlinx.jupyter.api.RendererHandler
1111

1212
/**
1313
* Library definition represents "library" concept in Kotlin kernel.
@@ -59,7 +59,7 @@ interface LibraryDefinition {
5959
* List of type renderers. Consider using [org.jetbrains.kotlinx.jupyter.api.Renderable]
6060
* as it's generally more convenient
6161
*/
62-
val renderers: List<RendererTypeHandler>
62+
val renderers: List<RendererHandler>
6363
get() = emptyList()
6464

6565
/**

jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/libraries/LibraryDefinitionImpl.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import org.jetbrains.kotlinx.jupyter.api.ExecutionCallback
77
import org.jetbrains.kotlinx.jupyter.api.FieldHandler
88
import org.jetbrains.kotlinx.jupyter.api.FileAnnotationHandler
99
import org.jetbrains.kotlinx.jupyter.api.KotlinKernelVersion
10-
import org.jetbrains.kotlinx.jupyter.api.RendererTypeHandler
10+
import org.jetbrains.kotlinx.jupyter.api.RendererHandler
1111

1212
/**
1313
* Trivial implementation of [LibraryDefinition] - simple container.
@@ -20,7 +20,7 @@ class LibraryDefinitionImpl private constructor() : LibraryDefinition {
2020
override var initCell: List<ExecutionCallback<*>> = emptyList()
2121
override var afterCellExecution: List<AfterCellExecutionCallback> = emptyList()
2222
override var shutdown: List<ExecutionCallback<*>> = emptyList()
23-
override var renderers: List<RendererTypeHandler> = emptyList()
23+
override var renderers: List<RendererHandler> = emptyList()
2424
override var converters: List<FieldHandler> = emptyList()
2525
override var classAnnotations: List<ClassAnnotationHandler> = emptyList()
2626
override var fileAnnotations: List<FileAnnotationHandler> = emptyList()

jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/renderersHandling.kt

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,32 @@ class ResultHandlerCodeExecution(val code: Code) : ResultHandlerExecution {
3737
}
3838

3939
/**
40-
* Type handler for result renderers
40+
* [RendererHandler] renders results for which [accepts] returns `true`
4141
*/
42-
interface RendererTypeHandler : VariablesSubstitutionAware<RendererTypeHandler> {
42+
interface RendererHandler : VariablesSubstitutionAware<RendererHandler> {
4343
/**
44-
* Returns true if this renderer accepts [type], false otherwise
44+
* Returns true if this renderer accepts [value], false otherwise
4545
*/
46-
fun acceptsType(type: KClass<*>): Boolean
46+
fun accepts(value: Any?): Boolean
4747

4848
/**
4949
* Execution to handle result.
50-
* Should not throw if [acceptsType] returns true
50+
* Should not throw if [accepts] returns true
5151
*/
5252
val execution: ResultHandlerExecution
5353
}
5454

55+
/**
56+
* [RendererTypeHandler] handles results for which runtime types [acceptsType] returns `true`
57+
*/
58+
interface RendererTypeHandler : RendererHandler {
59+
fun acceptsType(type: KClass<*>): Boolean
60+
61+
override fun accepts(value: Any?): Boolean {
62+
return if (value == null) false else acceptsType(value::class)
63+
}
64+
}
65+
5566
/**
5667
* Precompiled renderer type handler. Override this interface if
5768
* you want type rendering to be optimized.
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ package org.jetbrains.kotlinx.jupyter.codegen
33
import org.jetbrains.kotlinx.jupyter.api.Code
44
import org.jetbrains.kotlinx.jupyter.api.FieldValue
55
import org.jetbrains.kotlinx.jupyter.api.PrecompiledRendererTypeHandler
6-
import org.jetbrains.kotlinx.jupyter.api.RendererTypeHandler
7-
import org.jetbrains.kotlinx.jupyter.api.TypeRenderersProcessor
6+
import org.jetbrains.kotlinx.jupyter.api.RendererHandler
7+
import org.jetbrains.kotlinx.jupyter.api.RenderersProcessor
88
import org.jetbrains.kotlinx.jupyter.api.libraries.ExecutionHost
99

10-
interface ResultsTypeRenderersProcessor : TypeRenderersProcessor {
10+
interface ResultsRenderersProcessor : RenderersProcessor {
1111
/**
1212
* Renders cell result [field] represented as [FieldValue] in the [host] context
1313
*/
@@ -18,5 +18,5 @@ interface ResultsTypeRenderersProcessor : TypeRenderersProcessor {
1818
* Returns code to be executed on execution host
1919
* for [PrecompiledRendererTypeHandler]'s.
2020
*/
21-
fun register(renderer: RendererTypeHandler): Code?
21+
fun register(renderer: RendererHandler): Code?
2222
}

src/main/kotlin/org/jetbrains/kotlinx/jupyter/apiImpl.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import org.jetbrains.kotlinx.jupyter.api.DisplayResultWithCell
88
import org.jetbrains.kotlinx.jupyter.api.JREInfoProvider
99
import org.jetbrains.kotlinx.jupyter.api.KotlinKernelVersion
1010
import org.jetbrains.kotlinx.jupyter.api.Notebook
11-
import org.jetbrains.kotlinx.jupyter.api.TypeRenderersProcessor
11+
import org.jetbrains.kotlinx.jupyter.api.RenderersProcessor
1212
import java.lang.IllegalStateException
1313

1414
class DisplayResultWrapper private constructor(
@@ -99,7 +99,7 @@ class NotebookImpl(
9999
private val runtimeProperties: ReplRuntimeProperties,
100100
) : Notebook {
101101
private val cells = hashMapOf<Int, CodeCellImpl>()
102-
internal var typeRenderersProcessor: TypeRenderersProcessor? = null
102+
internal var typeRenderersProcessor: RenderersProcessor? = null
103103

104104
override val cellsList: Collection<CodeCellImpl>
105105
get() = cells.values
@@ -159,6 +159,6 @@ class NotebookImpl(
159159
override val lastCell: CodeCellImpl?
160160
get() = history(1)
161161

162-
override val renderersProcessor: TypeRenderersProcessor
162+
override val renderersProcessor: RenderersProcessor
163163
get() = typeRenderersProcessor ?: throw IllegalStateException("Type renderers processor is not initialized yet")
164164
}

src/main/kotlin/org/jetbrains/kotlinx/jupyter/codegen/TypeRenderersProcessorImpl.kt renamed to src/main/kotlin/org/jetbrains/kotlinx/jupyter/codegen/RenderersProcessorImpl.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ package org.jetbrains.kotlinx.jupyter.codegen
33
import org.jetbrains.kotlinx.jupyter.api.Code
44
import org.jetbrains.kotlinx.jupyter.api.FieldValue
55
import org.jetbrains.kotlinx.jupyter.api.PrecompiledRendererTypeHandler
6-
import org.jetbrains.kotlinx.jupyter.api.RendererTypeHandler
6+
import org.jetbrains.kotlinx.jupyter.api.RendererHandler
77
import org.jetbrains.kotlinx.jupyter.api.libraries.ExecutionHost
88
import org.jetbrains.kotlinx.jupyter.exceptions.LibraryProblemPart
99
import org.jetbrains.kotlinx.jupyter.exceptions.rethrowAsLibraryException
1010
import org.jetbrains.kotlinx.jupyter.repl.ContextUpdater
1111

12-
class TypeRenderersProcessorImpl(
12+
class RenderersProcessorImpl(
1313
private val contextUpdater: ContextUpdater,
14-
) : ResultsTypeRenderersProcessor {
14+
) : ResultsRenderersProcessor {
1515
private var counter = 0
16-
private val typeRenderers: MutableList<HandlerWithInfo> = mutableListOf()
16+
private val renderers: MutableList<HandlerWithInfo> = mutableListOf()
1717

1818
override tailrec fun renderResult(host: ExecutionHost, field: FieldValue): Any? {
19-
val value = field.value ?: return null
20-
val (handler, id) = typeRenderers.firstOrNull { it.handler.acceptsType(value::class) }
19+
val value = field.value
20+
val (handler, id) = renderers.firstOrNull { it.handler.accepts(value) }
2121
?: return value
2222
return if (id == null) {
2323
val newField = rethrowAsLibraryException(LibraryProblemPart.RENDERERS) {
@@ -39,30 +39,30 @@ class TypeRenderersProcessorImpl(
3939
return renderResult(host, FieldValue(value, null))
4040
}
4141

42-
override fun register(renderer: RendererTypeHandler): Code? {
42+
override fun register(renderer: RendererHandler): Code? {
4343
return register(renderer, true)
4444
}
4545

46-
override fun registerWithoutOptimizing(renderer: RendererTypeHandler) {
46+
override fun registerWithoutOptimizing(renderer: RendererHandler) {
4747
register(renderer, false)
4848
}
4949

50-
private fun register(renderer: RendererTypeHandler, doOptimization: Boolean): Code? {
50+
private fun register(renderer: RendererHandler, doOptimization: Boolean): Code? {
5151
if (!doOptimization || renderer !is PrecompiledRendererTypeHandler || !renderer.mayBePrecompiled) {
52-
typeRenderers.add(HandlerWithInfo(renderer, null))
52+
renderers.add(HandlerWithInfo(renderer, null))
5353
return null
5454
}
5555

5656
val id = counter++
57-
typeRenderers.add(HandlerWithInfo(renderer, id))
57+
renderers.add(HandlerWithInfo(renderer, id))
5858
val methodName = getMethodName(id)
5959
return renderer.precompile(methodName, "___value")
6060
}
6161

6262
private fun getMethodName(id: Int) = "___renderResult$id"
6363

6464
private data class HandlerWithInfo(
65-
val handler: RendererTypeHandler,
65+
val handler: RendererHandler,
6666
val id: Int?,
6767
)
6868
}

src/main/kotlin/org/jetbrains/kotlinx/jupyter/protocol.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,8 @@ class CapturingOutputStream(
411411
}
412412
}
413413

414-
fun Any.toDisplayResult(notebook: Notebook): DisplayResult? = when (this) {
414+
fun Any?.toDisplayResult(notebook: Notebook): DisplayResult? = when (this) {
415+
null -> textResult("null")
415416
is DisplayResult -> this
416417
is Renderable -> this.render(notebook)
417418
is Unit -> null
@@ -475,7 +476,7 @@ fun JupyterConnection.evalWithIO(repl: ReplForJupyter, srcMessage: Message, body
475476
else -> {
476477
flushStreams()
477478
try {
478-
val result = exec.resultValue?.toDisplayResult(repl.notebook)
479+
val result = exec.resultValue.toDisplayResult(repl.notebook)
479480
OkResponseWithMessage(result, exec.metadata)
480481
} catch (e: Exception) {
481482
AbortResponseWithMessage("error: Unable to convert result to a string: $e")

0 commit comments

Comments
 (0)