Skip to content

Commit c645d10

Browse files
Handle allow_stdin=false
1 parent 0ea9551 commit c645d10

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

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

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.min
88
import org.zeromq.SocketType
99
import org.zeromq.ZMQ
1010
import java.io.Closeable
11+
import java.io.IOException
1112
import java.security.SignatureException
1213
import javax.crypto.Mac
1314
import javax.crypto.spec.SecretKeySpec
@@ -208,3 +209,9 @@ fun ZMQ.Socket.receiveMessage(start: ByteArray, hmac: HMAC): Message? {
208209
content.parseJson()
209210
)
210211
}
212+
213+
object DisabledStdinInputStream : java.io.InputStream() {
214+
override fun read(): Int {
215+
throw IOException("Input from stdin is unsupported by the client")
216+
}
217+
}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,8 @@ fun JupyterConnection.evalWithIO(config: OutputConfig, srcMessage: Message, body
394394
System.setErr(PrintStream(forkedError, false, "UTF-8"))
395395

396396
val `in` = System.`in`
397-
System.setIn(stdinIn)
397+
val allowStdIn = srcMessage.content?.boolean("allow_stdin") ?: true
398+
System.setIn(if (allowStdIn) stdinIn else DisabledStdinInputStream)
398399
try {
399400
return try {
400401
val exec = body()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.jetbrains.kotlin.jupyter.test
2+
3+
import org.jetbrains.kotlin.jupyter.JupyterSockets
4+
import org.jetbrains.kotlin.jupyter.get
5+
import org.jetbrains.kotlin.jupyter.jsonObject
6+
import org.junit.jupiter.api.Assertions.assertEquals
7+
import org.junit.jupiter.api.Test
8+
import org.zeromq.ZMQ
9+
import kotlin.test.assertNotNull
10+
import kotlin.test.assertTrue
11+
12+
class NoStdinTests : KernelServerTestsBase() {
13+
fun execute(code: String) {
14+
val context = ZMQ.context(1)
15+
val shell = ClientSocket(context, JupyterSockets.shell)
16+
val ioPub = ClientSocket(context, JupyterSockets.iopub)
17+
val stdin = ClientSocket(context, JupyterSockets.stdin)
18+
ioPub.subscribe(byteArrayOf())
19+
try {
20+
shell.connect()
21+
ioPub.connect()
22+
stdin.connect()
23+
24+
shell.sendMessage("execute_request",
25+
content = jsonObject("code" to code, "allow_stdin" to false))
26+
27+
28+
var msg = shell.receiveMessage()
29+
assertEquals("execute_reply", msg.type())
30+
msg = ioPub.receiveMessage()
31+
assertEquals("status", msg.type())
32+
assertEquals("busy", msg.content["execution_state"])
33+
msg = ioPub.receiveMessage()
34+
assertEquals("execute_input", msg.type())
35+
36+
msg = ioPub.receiveMessage()
37+
assertEquals("stream", msg.type())
38+
assertEquals("stderr", msg.content["name"])
39+
val text = msg.content?.string("text");
40+
assertNotNull(text)
41+
assertTrue(text.startsWith("java.io.IOException: Input from stdin is unsupported by the client"))
42+
43+
msg = ioPub.receiveMessage()
44+
assertEquals("status", msg.type())
45+
assertEquals("idle", msg.content["execution_state"])
46+
47+
} finally {
48+
shell.close()
49+
ioPub.close()
50+
stdin.close()
51+
context.term()
52+
}
53+
}
54+
55+
@Test
56+
fun testReadLine() {
57+
execute("readLine() ?: \"blah\"")
58+
}
59+
60+
@Test
61+
fun testStdinRead() {
62+
execute("System.`in`.read()")
63+
}
64+
}

0 commit comments

Comments
 (0)