Skip to content

Commit

Permalink
Introduce commHandlers for kernel-provided functionality; support deb…
Browse files Browse the repository at this point in the history
…ugPortComm messages in kernel
  • Loading branch information
nikolay-egorov committed Aug 30, 2022
1 parent a4df334 commit db0dc9c
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.jetbrains.kotlinx.jupyter.messaging

import kotlinx.serialization.Serializable

object ProvidedCommMessages {
const val OPEN_DEBUG_PORT_TARGET: String = "open_debug_port_target"
}

@Serializable
class OpenDebugPortReply(
val port: Int?
) : OkReply()
3 changes: 3 additions & 0 deletions src/main/kotlin/org/jetbrains/kotlinx/jupyter/connection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ class JupyterConnectionImpl(

override val stdinIn = StdinInputStream()

override val debugPort: Int?
get() = config.debugPort

private var _contextMessage: RawMessage? = null
override fun setContextMessage(message: RawMessage?) {
_contextMessage = message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ interface JupyterConnectionInternal : JupyterConnection {
val executor: JupyterExecutor
val stdinIn: InputStream

val debugPort: Int?

fun sendStatus(status: KernelStatus, incomingMessage: RawMessage? = null)
fun doWrappedInBusyIdle(incomingMessage: RawMessage? = null, action: () -> Unit)
fun updateSessionInfo(message: RawMessage)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.jetbrains.kotlinx.jupyter.messaging

import kotlinx.serialization.json.JsonObject
import org.jetbrains.kotlinx.jupyter.ReplForJupyterImpl
import org.jetbrains.kotlinx.jupyter.api.libraries.Comm
import org.jetbrains.kotlinx.jupyter.api.libraries.sendData
import org.jetbrains.kotlinx.jupyter.messaging.ProvidedCommMessages.OPEN_DEBUG_PORT_TARGET

typealias CommMessageProcessCallback = (Comm, JsonObject, ReplForJupyterImpl) -> Unit

abstract class DefaultCommHandler {
abstract val targetId: String

abstract fun onReceive(): CommMessageProcessCallback

abstract fun register(repl: ReplForJupyterImpl)
}

class DebugPortCommHandler : DefaultCommHandler() {
override val targetId: String
get() = OPEN_DEBUG_PORT_TARGET

override fun onReceive(): CommMessageProcessCallback {
return { comm, _, repl ->
comm.sendData(OpenDebugPortReply(repl.debugPort))
}
}

override fun register(repl: ReplForJupyterImpl) {
repl.notebook.commManager.registerCommTarget(targetId) { comm, _ ->
comm.onMessage {
onReceive()
}
}
}
}
14 changes: 12 additions & 2 deletions src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import org.jetbrains.kotlinx.jupyter.magics.CompoundCodePreprocessor
import org.jetbrains.kotlinx.jupyter.magics.ErrorsMagicsProcessor
import org.jetbrains.kotlinx.jupyter.magics.FullMagicsHandler
import org.jetbrains.kotlinx.jupyter.magics.MagicsProcessor
import org.jetbrains.kotlinx.jupyter.messaging.DefaultCommHandler
import org.jetbrains.kotlinx.jupyter.messaging.DisplayHandler
import org.jetbrains.kotlinx.jupyter.messaging.NoOpDisplayHandler
import org.jetbrains.kotlinx.jupyter.repl.CellExecutor
Expand Down Expand Up @@ -124,6 +125,7 @@ interface ReplOptions {
var executedCodeLogging: ExecutedCodeLogging
var writeCompiledClasses: Boolean
var outputConfig: OutputConfig
val debugPort: Int?
}

interface ReplForJupyter {
Expand Down Expand Up @@ -188,9 +190,17 @@ class ReplForJupyterImpl(
private val scriptReceivers: List<Any> = emptyList(),
override val isEmbedded: Boolean = false,
override val notebook: MutableNotebook,
override val librariesScanner: LibrariesScanner
override val librariesScanner: LibrariesScanner,
override val debugPort: Int? = null,
providedCommHandlers: List<DefaultCommHandler>
) : ReplForJupyter, ReplOptions, BaseKernelHost, UserHandlesProvider {

init {
providedCommHandlers.forEach {
it.register(this)
}
}

override val currentBranch: String
get() = runtimeProperties.currentBranch
override val librariesDir: File = KERNEL_LIBRARIES.homeLibrariesDir(homeDir)
Expand Down Expand Up @@ -418,7 +428,7 @@ class ReplForJupyterImpl(
@Suppress("unused")
private fun printUsagesInfo(cellId: Int, usedVariables: Set<String>?) {
log.debug(buildString {
if (usedVariables == null || usedVariables.isEmpty()) {
if (usedVariables.isNullOrEmpty()) {
append("No usages for cell $cellId")
return@buildString
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import org.jetbrains.kotlinx.jupyter.libraries.LibrariesScanner
import org.jetbrains.kotlinx.jupyter.libraries.LibraryResolver
import org.jetbrains.kotlinx.jupyter.libraries.ResolutionInfoProvider
import org.jetbrains.kotlinx.jupyter.messaging.CommManagerImpl
import org.jetbrains.kotlinx.jupyter.messaging.DebugPortCommHandler
import org.jetbrains.kotlinx.jupyter.messaging.DefaultCommHandler
import org.jetbrains.kotlinx.jupyter.messaging.DisplayHandler
import org.jetbrains.kotlinx.jupyter.messaging.NoOpDisplayHandler
import java.io.File
Expand All @@ -28,4 +30,15 @@ abstract class BaseReplFactory : ReplFactory() {
override fun provideIsEmbedded() = false
override fun provideLibrariesScanner(): LibrariesScanner = LibrariesScanner(notebook)
override fun provideCommManager(): CommManager = CommManagerImpl(connection)
override fun provideDefaultCommHandlers(): List<DefaultCommHandler> = listOf(
DebugPortCommHandler()
)

init {
val uniqueTargets = defaultCommHandlers.map { it.targetId }.toSet().size
assert(uniqueTargets == defaultCommHandlers.size) {
val duplicates = defaultCommHandlers.groupingBy { it }.eachCount().filter { it.value > 1 }.keys
"Duplicate default comm targets found! $duplicates"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ object MockJupyterConnection : JupyterConnectionInternal {
get() = throw NotImplementedError()
override val stdinIn: InputStream
get() = throw NotImplementedError()
override val debugPort: Int?
get() = null

override fun sendStatus(status: KernelStatus, incomingMessage: RawMessage?) {
throw NotImplementedError()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.jetbrains.kotlinx.jupyter.api.libraries.CommManager
import org.jetbrains.kotlinx.jupyter.libraries.LibrariesScanner
import org.jetbrains.kotlinx.jupyter.libraries.LibraryResolver
import org.jetbrains.kotlinx.jupyter.libraries.ResolutionInfoProvider
import org.jetbrains.kotlinx.jupyter.messaging.DefaultCommHandler
import org.jetbrains.kotlinx.jupyter.messaging.DisplayHandler
import org.jetbrains.kotlinx.jupyter.messaging.JupyterConnectionInternal
import java.io.File
Expand All @@ -26,7 +27,9 @@ abstract class ReplFactory {
scriptReceivers,
isEmbedded,
notebook,
librariesScanner
librariesScanner,
connection.debugPort,
defaultCommHandlers
)
}

Expand Down Expand Up @@ -69,6 +72,9 @@ abstract class ReplFactory {
protected val commManager: CommManager by lazy { provideCommManager() }
protected abstract fun provideCommManager(): CommManager

protected val defaultCommHandlers: List<DefaultCommHandler> by lazy { provideDefaultCommHandlers() }
protected abstract fun provideDefaultCommHandlers(): List<DefaultCommHandler>

// TODO: add other methods incl. display handler and socket messages listener
// Inheritors should be constructed of connection (JupyterConnection)
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class ParseMagicsTests {
override var executedCodeLogging = ExecutedCodeLogging.OFF
override var writeCompiledClasses = false
override var outputConfig = OutputConfig()
override val debugPort: Int? = null
}

private val options = TestReplOptions()
Expand Down

0 comments on commit db0dc9c

Please sign in to comment.