Skip to content

Commit db0dc9c

Browse files
Introduce commHandlers for kernel-provided functionality; support debugPortComm messages in kernel
1 parent a4df334 commit db0dc9c

File tree

9 files changed

+88
-3
lines changed

9 files changed

+88
-3
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.jetbrains.kotlinx.jupyter.messaging
2+
3+
import kotlinx.serialization.Serializable
4+
5+
object ProvidedCommMessages {
6+
const val OPEN_DEBUG_PORT_TARGET: String = "open_debug_port_target"
7+
}
8+
9+
@Serializable
10+
class OpenDebugPortReply(
11+
val port: Int?
12+
) : OkReply()

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ class JupyterConnectionImpl(
149149

150150
override val stdinIn = StdinInputStream()
151151

152+
override val debugPort: Int?
153+
get() = config.debugPort
154+
152155
private var _contextMessage: RawMessage? = null
153156
override fun setContextMessage(message: RawMessage?) {
154157
_contextMessage = message

src/main/kotlin/org/jetbrains/kotlinx/jupyter/messaging/JupyterConnectionInternal.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ interface JupyterConnectionInternal : JupyterConnection {
2424
val executor: JupyterExecutor
2525
val stdinIn: InputStream
2626

27+
val debugPort: Int?
28+
2729
fun sendStatus(status: KernelStatus, incomingMessage: RawMessage? = null)
2830
fun doWrappedInBusyIdle(incomingMessage: RawMessage? = null, action: () -> Unit)
2931
fun updateSessionInfo(message: RawMessage)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.jetbrains.kotlinx.jupyter.messaging
2+
3+
import kotlinx.serialization.json.JsonObject
4+
import org.jetbrains.kotlinx.jupyter.ReplForJupyterImpl
5+
import org.jetbrains.kotlinx.jupyter.api.libraries.Comm
6+
import org.jetbrains.kotlinx.jupyter.api.libraries.sendData
7+
import org.jetbrains.kotlinx.jupyter.messaging.ProvidedCommMessages.OPEN_DEBUG_PORT_TARGET
8+
9+
typealias CommMessageProcessCallback = (Comm, JsonObject, ReplForJupyterImpl) -> Unit
10+
11+
abstract class DefaultCommHandler {
12+
abstract val targetId: String
13+
14+
abstract fun onReceive(): CommMessageProcessCallback
15+
16+
abstract fun register(repl: ReplForJupyterImpl)
17+
}
18+
19+
class DebugPortCommHandler : DefaultCommHandler() {
20+
override val targetId: String
21+
get() = OPEN_DEBUG_PORT_TARGET
22+
23+
override fun onReceive(): CommMessageProcessCallback {
24+
return { comm, _, repl ->
25+
comm.sendData(OpenDebugPortReply(repl.debugPort))
26+
}
27+
}
28+
29+
override fun register(repl: ReplForJupyterImpl) {
30+
repl.notebook.commManager.registerCommTarget(targetId) { comm, _ ->
31+
comm.onMessage {
32+
onReceive()
33+
}
34+
}
35+
}
36+
}

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import org.jetbrains.kotlinx.jupyter.magics.CompoundCodePreprocessor
5353
import org.jetbrains.kotlinx.jupyter.magics.ErrorsMagicsProcessor
5454
import org.jetbrains.kotlinx.jupyter.magics.FullMagicsHandler
5555
import org.jetbrains.kotlinx.jupyter.magics.MagicsProcessor
56+
import org.jetbrains.kotlinx.jupyter.messaging.DefaultCommHandler
5657
import org.jetbrains.kotlinx.jupyter.messaging.DisplayHandler
5758
import org.jetbrains.kotlinx.jupyter.messaging.NoOpDisplayHandler
5859
import org.jetbrains.kotlinx.jupyter.repl.CellExecutor
@@ -124,6 +125,7 @@ interface ReplOptions {
124125
var executedCodeLogging: ExecutedCodeLogging
125126
var writeCompiledClasses: Boolean
126127
var outputConfig: OutputConfig
128+
val debugPort: Int?
127129
}
128130

129131
interface ReplForJupyter {
@@ -188,9 +190,17 @@ class ReplForJupyterImpl(
188190
private val scriptReceivers: List<Any> = emptyList(),
189191
override val isEmbedded: Boolean = false,
190192
override val notebook: MutableNotebook,
191-
override val librariesScanner: LibrariesScanner
193+
override val librariesScanner: LibrariesScanner,
194+
override val debugPort: Int? = null,
195+
providedCommHandlers: List<DefaultCommHandler>
192196
) : ReplForJupyter, ReplOptions, BaseKernelHost, UserHandlesProvider {
193197

198+
init {
199+
providedCommHandlers.forEach {
200+
it.register(this)
201+
}
202+
}
203+
194204
override val currentBranch: String
195205
get() = runtimeProperties.currentBranch
196206
override val librariesDir: File = KERNEL_LIBRARIES.homeLibrariesDir(homeDir)
@@ -418,7 +428,7 @@ class ReplForJupyterImpl(
418428
@Suppress("unused")
419429
private fun printUsagesInfo(cellId: Int, usedVariables: Set<String>?) {
420430
log.debug(buildString {
421-
if (usedVariables == null || usedVariables.isEmpty()) {
431+
if (usedVariables.isNullOrEmpty()) {
422432
append("No usages for cell $cellId")
423433
return@buildString
424434
}

src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/creating/BaseReplFactory.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import org.jetbrains.kotlinx.jupyter.libraries.LibrariesScanner
1010
import org.jetbrains.kotlinx.jupyter.libraries.LibraryResolver
1111
import org.jetbrains.kotlinx.jupyter.libraries.ResolutionInfoProvider
1212
import org.jetbrains.kotlinx.jupyter.messaging.CommManagerImpl
13+
import org.jetbrains.kotlinx.jupyter.messaging.DebugPortCommHandler
14+
import org.jetbrains.kotlinx.jupyter.messaging.DefaultCommHandler
1315
import org.jetbrains.kotlinx.jupyter.messaging.DisplayHandler
1416
import org.jetbrains.kotlinx.jupyter.messaging.NoOpDisplayHandler
1517
import java.io.File
@@ -28,4 +30,15 @@ abstract class BaseReplFactory : ReplFactory() {
2830
override fun provideIsEmbedded() = false
2931
override fun provideLibrariesScanner(): LibrariesScanner = LibrariesScanner(notebook)
3032
override fun provideCommManager(): CommManager = CommManagerImpl(connection)
33+
override fun provideDefaultCommHandlers(): List<DefaultCommHandler> = listOf(
34+
DebugPortCommHandler()
35+
)
36+
37+
init {
38+
val uniqueTargets = defaultCommHandlers.map { it.targetId }.toSet().size
39+
assert(uniqueTargets == defaultCommHandlers.size) {
40+
val duplicates = defaultCommHandlers.groupingBy { it }.eachCount().filter { it.value > 1 }.keys
41+
"Duplicate default comm targets found! $duplicates"
42+
}
43+
}
3144
}

src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/creating/MockJupyterConnection.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ object MockJupyterConnection : JupyterConnectionInternal {
3535
get() = throw NotImplementedError()
3636
override val stdinIn: InputStream
3737
get() = throw NotImplementedError()
38+
override val debugPort: Int?
39+
get() = null
3840

3941
override fun sendStatus(status: KernelStatus, incomingMessage: RawMessage?) {
4042
throw NotImplementedError()

src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/creating/ReplFactory.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.jetbrains.kotlinx.jupyter.api.libraries.CommManager
88
import org.jetbrains.kotlinx.jupyter.libraries.LibrariesScanner
99
import org.jetbrains.kotlinx.jupyter.libraries.LibraryResolver
1010
import org.jetbrains.kotlinx.jupyter.libraries.ResolutionInfoProvider
11+
import org.jetbrains.kotlinx.jupyter.messaging.DefaultCommHandler
1112
import org.jetbrains.kotlinx.jupyter.messaging.DisplayHandler
1213
import org.jetbrains.kotlinx.jupyter.messaging.JupyterConnectionInternal
1314
import java.io.File
@@ -26,7 +27,9 @@ abstract class ReplFactory {
2627
scriptReceivers,
2728
isEmbedded,
2829
notebook,
29-
librariesScanner
30+
librariesScanner,
31+
connection.debugPort,
32+
defaultCommHandlers
3033
)
3134
}
3235

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

75+
protected val defaultCommHandlers: List<DefaultCommHandler> by lazy { provideDefaultCommHandlers() }
76+
protected abstract fun provideDefaultCommHandlers(): List<DefaultCommHandler>
77+
7278
// TODO: add other methods incl. display handler and socket messages listener
7379
// Inheritors should be constructed of connection (JupyterConnection)
7480
}

src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/parseMagicsTests.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ class ParseMagicsTests {
142142
override var executedCodeLogging = ExecutedCodeLogging.OFF
143143
override var writeCompiledClasses = false
144144
override var outputConfig = OutputConfig()
145+
override val debugPort: Int? = null
145146
}
146147

147148
private val options = TestReplOptions()

0 commit comments

Comments
 (0)