9
9
"io/ioutil"
10
10
"log"
11
11
"os"
12
+ "runtime"
12
13
"strings"
13
14
14
15
"github.com/cosmos72/gomacro/base"
@@ -43,18 +44,38 @@ type SocketGroup struct {
43
44
Key []byte
44
45
}
45
46
46
- // kernelInfo holds information about the igo kernel, for
47
- // kernel_info_reply messages.
48
- type kernelInfo struct {
49
- ProtocolVersion []int `json:"protocol_version"`
50
- Language string `json:"language"`
51
- }
52
-
53
47
// kernelStatus holds a kernel state, for status broadcast messages.
54
48
type kernelStatus struct {
55
49
ExecutionState string `json:"execution_state"`
56
50
}
57
51
52
+ // KernelLanguageInfo holds information about the language that this kernel executes code in
53
+ type kernelLanguageInfo struct {
54
+ Name string `json:"name"`
55
+ Version string `json:"version"`
56
+ MIMEType string `json:"mimetype"`
57
+ FileExtension string `json:"file_extension"`
58
+ PygmentsLexer string `json:"pygments_lexer"`
59
+ CodeMirrorMode string `json:"codemirror_mode"`
60
+ NBConvertExporter string `json:"nbconvert_exporter"`
61
+ }
62
+
63
+ // HelpLink stores data to be displayed in the help menu of the notebook
64
+ type helpLink struct {
65
+ Text string `json:"text"`
66
+ URL string `json:"url"`
67
+ }
68
+
69
+ // KernelInfo holds information about the igo kernel, for kernel_info_reply messages.
70
+ type kernelInfo struct {
71
+ ProtocolVersion string `json:"protocol_version"`
72
+ Implementation string `json:"implementation"`
73
+ ImplementationVersion string `json:"implementation_version"`
74
+ LanguageInfo kernelLanguageInfo `json:"language_info"`
75
+ Banner string `json:"banner"`
76
+ HelpLinks []helpLink `json:"help_links"`
77
+ }
78
+
58
79
// shutdownReply encodes a boolean indication of stutdown/restart
59
80
type shutdownReply struct {
60
81
Restart bool `json:"restart"`
@@ -120,11 +141,11 @@ func runKernel(connectionFile string) {
120
141
121
142
handleShellMsg (ir , msgReceipt {msg , ids , sockets })
122
143
123
- // TODO Handle stdin socket.
144
+ // TODO Handle stdin socket.
124
145
case sockets .StdinSocket :
125
146
sockets .StdinSocket .RecvMessageBytes (0 )
126
147
127
- // Handle control messages.
148
+ // Handle control messages.
128
149
case sockets .ControlSocket :
129
150
msgParts , err = sockets .ControlSocket .RecvMessageBytes (0 )
130
151
if err != nil {
@@ -210,31 +231,29 @@ func handleShellMsg(ir *classic.Interp, receipt msgReceipt) {
210
231
211
232
// sendKernelInfo sends a kernel_info_reply message.
212
233
func sendKernelInfo (receipt msgReceipt ) error {
213
- reply , err := NewMsg ("kernel_info_reply" , receipt .Msg )
214
- if err != nil {
215
- return err
216
- }
217
-
218
- reply .Content = kernelInfo {[]int {4 , 0 }, "go" }
219
- if err := receipt .SendResponse (receipt .Sockets .ShellSocket , reply ); err != nil {
220
- return err
221
- }
222
-
223
- return nil
234
+ return receipt .Reply ("kernel_info_reply" ,
235
+ kernelInfo {
236
+ ProtocolVersion : "5.0" ,
237
+ Implementation : "gophernotes" ,
238
+ ImplementationVersion : Version ,
239
+ Banner : fmt .Sprintf ("Go kernel: gophernotes - v%s" , Version ),
240
+ LanguageInfo : kernelLanguageInfo {
241
+ Name : "go" ,
242
+ Version : runtime .Version (),
243
+ FileExtension : ".go" ,
244
+ },
245
+ HelpLinks : []helpLink {
246
+ {Text : "Go" , URL : "https://golang.org/" },
247
+ {Text : "gophernotes" , URL : "https://github.com/gopherdata/gophernotes" },
248
+ },
249
+ },
250
+ )
224
251
}
225
252
226
253
// handleExecuteRequest runs code from an execute_request method,
227
254
// and sends the various reply messages.
228
255
func handleExecuteRequest (ir * classic.Interp , receipt msgReceipt ) error {
229
-
230
- // Prepare the reply message.
231
- reply , err := NewMsg ("execute_reply" , receipt .Msg )
232
- if err != nil {
233
- return err
234
- }
235
-
236
- content := make (map [string ]interface {})
237
-
256
+ // Extract the data from the request
238
257
reqcontent := receipt .Msg .Content .(map [string ]interface {})
239
258
code := reqcontent ["code" ].(string )
240
259
in := bufio .NewReader (strings .NewReader (code ))
@@ -244,8 +263,18 @@ func handleExecuteRequest(ir *classic.Interp, receipt msgReceipt) error {
244
263
ExecCounter ++
245
264
}
246
265
266
+ // Prepare the map that will hold the reply content
267
+ content := make (map [string ]interface {})
247
268
content ["execution_count" ] = ExecCounter
248
269
270
+ // Tell the front-end that the kernel is working and when finished notify the
271
+ // front-end that the kernel is idle again
272
+ receipt .PublishKernelBusy ()
273
+ defer receipt .PublishKernelIdle ()
274
+
275
+ // Tell the front-end what the kernel is about to execute
276
+ receipt .PublishExecutionInput (ExecCounter , code )
277
+
249
278
// Redirect the standard out from the REPL.
250
279
oldStdout := os .Stdout
251
280
rOut , wOut , err := os .Pipe ()
@@ -306,25 +335,15 @@ func handleExecuteRequest(ir *classic.Interp, receipt msgReceipt) error {
306
335
wErr .Close ()
307
336
stdErr := <- outStderr
308
337
338
+ // TODO write stdout and stderr to streams rather than publishing as results
339
+
309
340
if len (val ) > 0 {
310
341
content ["status" ] = "ok"
311
- content ["payload" ] = make ([]map [string ]interface {}, 0 )
312
- content ["user_variables" ] = make (map [string ]string )
313
342
content ["user_expressions" ] = make (map [string ]string )
314
- if ! silent {
315
- var outContent OutputMsg
316
-
317
- out , err := NewMsg ("execute_result" , receipt .Msg )
318
- if err != nil {
319
- return err
320
- }
321
343
322
- outContent .Execcount = ExecCounter
323
- outContent .Data = make (map [string ]string )
324
- outContent .Data ["text/plain" ] = val
325
- outContent .Metadata = make (map [string ]interface {})
326
- out .Content = outContent
327
- receipt .SendResponse (receipt .Sockets .IOPubSocket , out )
344
+ if ! silent {
345
+ // Publish the result of the execution
346
+ receipt .PublishExecutionResult (ExecCounter , val )
328
347
}
329
348
}
330
349
@@ -334,51 +353,29 @@ func handleExecuteRequest(ir *classic.Interp, receipt msgReceipt) error {
334
353
content ["evalue" ] = stdErr
335
354
content ["traceback" ] = nil
336
355
337
- errormsg , err := NewMsg ("pyerr" , receipt .Msg )
338
- if err != nil {
339
- return err
340
- }
341
-
342
- errormsg .Content = ErrMsg {"Error" , stdErr , []string {stdErr }}
343
- receipt .SendResponse (receipt .Sockets .IOPubSocket , errormsg )
356
+ receipt .PublishExecutionError (stdErr , stdErr )
344
357
}
345
358
346
359
// Send the output back to the notebook.
347
- reply .Content = content
348
-
349
- if err := receipt .SendResponse (receipt .Sockets .ShellSocket , reply ); err != nil {
350
- return err
351
- }
352
-
353
- idle , err := NewMsg ("status" , receipt .Msg )
354
- if err != nil {
355
- return err
356
- }
357
-
358
- idle .Content = kernelStatus {"idle" }
359
-
360
- if err := receipt .SendResponse (receipt .Sockets .IOPubSocket , idle ); err != nil {
361
- return err
362
- }
363
-
364
- return nil
360
+ return receipt .Reply ("execute_reply" , content )
365
361
}
366
362
367
363
// handleShutdownRequest sends a "shutdown" message
368
364
func handleShutdownRequest (receipt msgReceipt ) {
369
- reply , err := NewMsg ("shutdown_reply" , receipt .Msg )
370
- if err != nil {
371
- log .Fatal (err )
372
- }
373
-
374
365
content := receipt .Msg .Content .(map [string ]interface {})
375
366
restart := content ["restart" ].(bool )
376
- reply .Content = shutdownReply {restart }
377
367
378
- if err := receipt .SendResponse (receipt .Sockets .ShellSocket , reply ); err != nil {
368
+ err := receipt .Reply ("shutdown_reply" ,
369
+ shutdownReply {
370
+ Restart : restart ,
371
+ },
372
+ )
373
+
374
+ if err != nil {
379
375
log .Fatal (err )
380
376
}
381
377
378
+
382
379
log .Println ("Shutting down in response to shutdown_request" )
383
380
os .Exit (0 )
384
381
}
0 commit comments