##// END OF EJS Templates
Only set channels to null when they are fully closed
Jessica B. Hamrick -
Show More
@@ -1,746 +1,762
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 5 'base/js/namespace',
6 6 'jquery',
7 7 'base/js/utils',
8 8 'services/kernels/js/comm',
9 9 'widgets/js/init',
10 10 ], function(IPython, $, utils, comm, widgetmanager) {
11 11 "use strict";
12 12
13 13 // Initialization and connection.
14 14 /**
15 15 * A Kernel Class to communicate with the Python kernel
16 16 * @Class Kernel
17 17 */
18 18 var Kernel = function (kernel_service_url, ws_url, notebook, id, name) {
19 19 this.events = notebook.events;
20 20
21 21 this.id = id;
22 22 this.name = name;
23 23
24 24 this.channels = {
25 25 'shell': null,
26 26 'iopub': null,
27 27 'stdin': null
28 28 };
29 29
30 30 this.kernel_service_url = kernel_service_url;
31 31 this.kernel_url = utils.url_join_encode(this.kernel_service_url, this.id);
32 32 this.ws_url = ws_url || IPython.utils.get_body_data("wsUrl");
33 33 if (!this.ws_url) {
34 34 // trailing 's' in https will become wss for secure web sockets
35 35 this.ws_url = location.protocol.replace('http', 'ws') + "//" + location.host;
36 36 }
37 37
38 38 this.username = "username";
39 39 this.session_id = utils.uuid();
40 40 this._msg_callbacks = {};
41 41
42 42 if (typeof(WebSocket) !== 'undefined') {
43 43 this.WebSocket = WebSocket;
44 44 } else if (typeof(MozWebSocket) !== 'undefined') {
45 45 this.WebSocket = MozWebSocket;
46 46 } else {
47 47 alert('Your browser does not have WebSocket support, please try Chrome, Safari or Firefox β‰₯ 6. Firefox 4 and 5 are also supported by you have to enable WebSockets in about:config.');
48 48 }
49 49
50 50 this.bind_events();
51 51 this.init_iopub_handlers();
52 52 this.comm_manager = new comm.CommManager(this);
53 53 this.widget_manager = new widgetmanager.WidgetManager(this.comm_manager, notebook);
54 54
55 55 this.last_msg_id = null;
56 56 this.last_msg_callbacks = {};
57 57 };
58 58
59 59
60 60 Kernel.prototype._get_msg = function (msg_type, content, metadata) {
61 61 var msg = {
62 62 header : {
63 63 msg_id : utils.uuid(),
64 64 username : this.username,
65 65 session : this.session_id,
66 66 msg_type : msg_type,
67 67 version : "5.0"
68 68 },
69 69 metadata : metadata || {},
70 70 content : content,
71 71 parent_header : {}
72 72 };
73 73 return msg;
74 74 };
75 75
76 76 Kernel.prototype.bind_events = function () {
77 77 var that = this;
78 78 this.events.on('send_input_reply.Kernel', function(evt, data) {
79 79 that.send_input_reply(data);
80 80 });
81 81 };
82 82
83 83 // Initialize the iopub handlers
84 84
85 85 Kernel.prototype.init_iopub_handlers = function () {
86 86 var output_msg_types = ['stream', 'display_data', 'execute_result', 'error'];
87 87 this._iopub_handlers = {};
88 88 this.register_iopub_handler('status', $.proxy(this._handle_status_message, this));
89 89 this.register_iopub_handler('clear_output', $.proxy(this._handle_clear_output, this));
90 90
91 91 for (var i=0; i < output_msg_types.length; i++) {
92 92 this.register_iopub_handler(output_msg_types[i], $.proxy(this._handle_output_message, this));
93 93 }
94 94 };
95 95
96 96 /**
97 97 * GET /api/kernels
98 98 */
99 99 Kernel.prototype.list = function (success, error) {
100 100 $.ajax(this.kernel_service_url, {
101 101 processData: false,
102 102 cache: false,
103 103 type: "GET",
104 104 dataType: "json",
105 105 success: success,
106 106 error: this._on_error(error)
107 107 });
108 108 };
109 109
110 110 /**
111 111 * POST /api/kernels
112 112 */
113 113 Kernel.prototype.start = function (success, error) {
114 114 var that = this;
115 115 var on_success = function (data, status, xhr) {
116 116 that._kernel_started(data);
117 117 if (success) {
118 118 success(data, status, xhr);
119 119 }
120 120 };
121 121
122 122 $.ajax(this.kernel_service_url, {
123 123 processData: false,
124 124 cache: false,
125 125 type: "POST",
126 126 dataType: "json",
127 127 success: this._on_success(on_success),
128 128 error: this._on_error(error)
129 129 });
130 130 };
131 131
132 132 /**
133 133 * GET /api/kernels/[:kernel_id]
134 134 */
135 135 Kernel.prototype.get_info = function (success, error) {
136 136 $.ajax(this.kernel_url, {
137 137 processData: false,
138 138 cache: false,
139 139 type: "GET",
140 140 dataType: "json",
141 141 success: this._on_success(success),
142 142 error: this._on_error(error)
143 143 });
144 144 };
145 145
146 146 /**
147 147 * DELETE /api/kernels/[:kernel_id]
148 148 */
149 149 Kernel.prototype.kill = function (success, error) {
150 150 this._kernel_dead();
151 151 $.ajax(this.kernel_url, {
152 152 processData: false,
153 153 cache: false,
154 154 type: "DELETE",
155 155 dataType: "json",
156 156 success: this._on_success(success),
157 157 error: this._on_error(error)
158 158 });
159 159 };
160 160
161 161 /**
162 162 * POST /api/kernels/[:kernel_id]/interrupt
163 163 */
164 164 Kernel.prototype.interrupt = function (success, error) {
165 165 this.events.trigger('status_interrupting.Kernel', {kernel: this});
166 166 var url = utils.url_join_encode(this.kernel_url, 'interrupt');
167 167 $.ajax(url, {
168 168 processData: false,
169 169 cache: false,
170 170 type: "POST",
171 171 dataType: "json",
172 172 success: this._on_success(success),
173 173 error: this._on_error(error)
174 174 });
175 175 };
176 176
177 177 /**
178 178 * POST /api/kernels/[:kernel_id]/restart
179 179 */
180 180 Kernel.prototype.restart = function (success, error) {
181 181 this.events.trigger('status_restarting.Kernel', {kernel: this});
182 182 this.stop_channels();
183 183
184 184 var that = this;
185 185 var on_success = function (data, status, xhr) {
186 186 that._kernel_started(data, status, xhr);
187 187 if (success) {
188 188 success(data, status, xhr);
189 189 }
190 190 };
191 191
192 192 var url = utils.url_join_encode(this.kernel_url, 'restart');
193 193 $.ajax(url, {
194 194 processData: false,
195 195 cache: false,
196 196 type: "POST",
197 197 dataType: "json",
198 198 success: this._on_success(on_success),
199 199 error: this._on_error(error)
200 200 });
201 201 };
202 202
203 203 /**
204 204 * Not actually a HTTP request, but useful function nonetheless
205 205 * for reconnecting to the kernel if the connection is somehow lost
206 206 */
207 207 Kernel.prototype.reconnect = function () {
208 208 this.events.trigger('status_reconnecting.Kernel');
209 209 var that = this;
210 210 setTimeout(function () {
211 211 that.start_channels();
212 212 }, 5000);
213 213 };
214 214
215 215 Kernel.prototype._on_success = function (success) {
216 216 var that = this;
217 217 return function (data, status, xhr) {
218 218 if (data) {
219 219 that.id = data.id;
220 220 that.name = data.name;
221 221 }
222 222 that.kernel_url = utils.url_join_encode(that.kernel_service_url, that.id);
223 223 if (success) {
224 224 success(data, status, xhr);
225 225 }
226 226 };
227 227 };
228 228
229 229 Kernel.prototype._on_error = function (error) {
230 230 return function (xhr, status, err) {
231 231 utils.log_ajax_error(xhr, status, err);
232 232 if (error) {
233 233 error(xhr, status, err);
234 234 }
235 235 };
236 236 };
237 237
238 238 Kernel.prototype._kernel_started = function (json) {
239 239 console.log("Kernel started: ", json.id);
240 240 this.events.trigger('status_started.Kernel', {kernel: this});
241 241 this.start_channels();
242 242 };
243 243
244 244 Kernel.prototype._kernel_connected = function () {
245 245 var that = this;
246 246 console.log('Connected to kernel: ', this.id);
247 247 this.events.trigger('status_connected.Kernel');
248 248 this.kernel_info(function () {
249 249 that.events.trigger('status_idle.Kernel');
250 250 });
251 251 };
252 252
253 253 Kernel.prototype._kernel_dead = function () {
254 254 this.events.trigger('status_dead.Kernel');
255 255 this.stop_channels();
256 256 };
257 257
258 258
259 259 /**
260 260 * Start the `shell`and `iopub` channels.
261 261 * Will stop and restart them if they already exist.
262 262 *
263 263 * @method start_channels
264 264 */
265 265 Kernel.prototype.start_channels = function () {
266 266 var that = this;
267 267 this.stop_channels();
268 268 var ws_host_url = this.ws_url + this.kernel_url;
269 269 console.log("Starting WebSockets:", ws_host_url);
270 270 this.channels.shell = new this.WebSocket(
271 271 this.ws_url + utils.url_join_encode(this.kernel_url, "shell")
272 272 );
273 273 this.channels.stdin = new this.WebSocket(
274 274 this.ws_url + utils.url_join_encode(this.kernel_url, "stdin")
275 275 );
276 276 this.channels.iopub = new this.WebSocket(
277 277 this.ws_url + utils.url_join_encode(this.kernel_url, "iopub")
278 278 );
279 279
280 280 var already_called_onclose = false; // only alert once
281 281 var ws_closed_early = function(evt){
282 282 if (already_called_onclose){
283 283 return;
284 284 }
285 285 already_called_onclose = true;
286 286 if ( ! evt.wasClean ){
287 287 that._ws_closed(ws_host_url, true);
288 288 }
289 289 };
290 290 var ws_closed_late = function(evt){
291 291 if (already_called_onclose){
292 292 return;
293 293 }
294 294 already_called_onclose = true;
295 295 if ( ! evt.wasClean ){
296 296 that._ws_closed(ws_host_url, false);
297 297 }
298 298 };
299 299 var ws_error = function(evt){
300 300 if (already_called_onclose){
301 301 return;
302 302 }
303 303 already_called_onclose = true;
304 304 that._ws_closed(ws_host_url, false);
305 305 };
306 306
307 307 for (var c in this.channels) {
308 308 this.channels[c].onopen = $.proxy(this._ws_opened, this);
309 309 this.channels[c].onclose = ws_closed_early;
310 310 this.channels[c].onerror = ws_error;
311 311 }
312 312 // switch from early-close to late-close message after 1s
313 313 setTimeout(function() {
314 314 for (var c in that.channels) {
315 315 if (that.channels[c] !== null) {
316 316 that.channels[c].onclose = ws_closed_late;
317 317 }
318 318 }
319 319 }, 1000);
320 320 this.channels.shell.onmessage = $.proxy(this._handle_shell_reply, this);
321 321 this.channels.iopub.onmessage = $.proxy(this._handle_iopub_message, this);
322 322 this.channels.stdin.onmessage = $.proxy(this._handle_input_request, this);
323 323 };
324 324
325 325 /**
326 326 * Handle a websocket entering the open state
327 327 * sends session and cookie authentication info as first message.
328 328 * Once all sockets are open, signal the Kernel.status_started event.
329 329 * @method _ws_opened
330 330 */
331 331 Kernel.prototype._ws_opened = function (evt) {
332 332 // send the session id so the Session object Python-side
333 333 // has the same identity
334 334 evt.target.send(this.session_id + ':' + document.cookie);
335 335
336 336 if (this.is_connected()) {
337 337 // all events ready, trigger started event.
338 338 this._kernel_connected();
339 339 }
340 340 };
341 341
342 342 Kernel.prototype._ws_closed = function(ws_url, early) {
343 343 this.stop_channels();
344 344 this.events.trigger('status_disconnected.Kernel');
345 345 if (!early) {
346 346 this.reconnect();
347 347 } else {
348 348 console.log('WebSocket connection failed: ', ws_url);
349 349 this.events.trigger('early_disconnect.Kernel', ws_url);
350 350 }
351 351 };
352 352
353 353 /**
354 354 * Stop the websocket channels.
355 355 * @method stop_channels
356 356 */
357 357 Kernel.prototype.stop_channels = function () {
358 var that = this;
359 var close = function (c) {
360 return function () {
361 if (that.channels[c].readyState === WebSocket.CLOSED) {
362 that.channels[c] = null;
363 }
364 };
365 };
358 366 for (var c in this.channels) {
359 367 if ( this.channels[c] !== null ) {
360 this.channels[c].onclose = null;
368 this.channels[c].onclose = close(c);
361 369 this.channels[c].close();
362 this.channels[c] = null;
363 370 }
364 371 }
365 372 };
366 373
367 374 // Main public methods.
368 375
369 376 Kernel.prototype.is_connected = function () {
370 377 for (var c in this.channels) {
371 378 // if any channel is not ready, then we're not connected
372 379 if (this.channels[c] === null) {
373 380 return false;
374 381 }
375 382 if (this.channels[c].readyState !== WebSocket.OPEN) {
376 383 return false;
377 384 }
378 385 }
379 386 return true;
380 387 };
381 388
389 Kernel.prototype.is_fully_disconnected = function () {
390 for (var c in this.channels) {
391 if (this.channels[c] === null) {
392 return true;
393 }
394 }
395 return false;
396 };
397
382 398 // send a message on the Kernel's shell channel
383 399 Kernel.prototype.send_shell_message = function (msg_type, content, callbacks, metadata) {
384 400 if (!this.is_connected()) {
385 401 throw new Error("kernel is not connected");
386 402 }
387 403 var msg = this._get_msg(msg_type, content, metadata);
388 404 this.channels.shell.send(JSON.stringify(msg));
389 405 this.set_callbacks_for_msg(msg.header.msg_id, callbacks);
390 406 return msg.header.msg_id;
391 407 };
392 408
393 409 /**
394 410 * Get kernel info
395 411 *
396 412 * @param callback {function}
397 413 * @method kernel_info
398 414 *
399 415 * When calling this method, pass a callback function that expects one argument.
400 416 * The callback will be passed the complete `kernel_info_reply` message documented
401 417 * [here](http://ipython.org/ipython-doc/dev/development/messaging.html#kernel-info)
402 418 */
403 419 Kernel.prototype.kernel_info = function (callback) {
404 420 var callbacks;
405 421 if (callback) {
406 422 callbacks = { shell : { reply : callback } };
407 423 }
408 424 return this.send_shell_message("kernel_info_request", {}, callbacks);
409 425 };
410 426
411 427 /**
412 428 * Get info on an object
413 429 *
414 430 * @param code {string}
415 431 * @param cursor_pos {integer}
416 432 * @param callback {function}
417 433 * @method inspect
418 434 *
419 435 * When calling this method, pass a callback function that expects one argument.
420 436 * The callback will be passed the complete `inspect_reply` message documented
421 437 * [here](http://ipython.org/ipython-doc/dev/development/messaging.html#object-information)
422 438 */
423 439 Kernel.prototype.inspect = function (code, cursor_pos, callback) {
424 440 var callbacks;
425 441 if (callback) {
426 442 callbacks = { shell : { reply : callback } };
427 443 }
428 444
429 445 var content = {
430 446 code : code,
431 447 cursor_pos : cursor_pos,
432 448 detail_level : 0
433 449 };
434 450 return this.send_shell_message("inspect_request", content, callbacks);
435 451 };
436 452
437 453 /**
438 454 * Execute given code into kernel, and pass result to callback.
439 455 *
440 456 * @async
441 457 * @method execute
442 458 * @param {string} code
443 459 * @param [callbacks] {Object} With the following keys (all optional)
444 460 * @param callbacks.shell.reply {function}
445 461 * @param callbacks.shell.payload.[payload_name] {function}
446 462 * @param callbacks.iopub.output {function}
447 463 * @param callbacks.iopub.clear_output {function}
448 464 * @param callbacks.input {function}
449 465 * @param {object} [options]
450 466 * @param [options.silent=false] {Boolean}
451 467 * @param [options.user_expressions=empty_dict] {Dict}
452 468 * @param [options.allow_stdin=false] {Boolean} true|false
453 469 *
454 470 * @example
455 471 *
456 472 * The options object should contain the options for the execute call. Its default
457 473 * values are:
458 474 *
459 475 * options = {
460 476 * silent : true,
461 477 * user_expressions : {},
462 478 * allow_stdin : false
463 479 * }
464 480 *
465 481 * When calling this method pass a callbacks structure of the form:
466 482 *
467 483 * callbacks = {
468 484 * shell : {
469 485 * reply : execute_reply_callback,
470 486 * payload : {
471 487 * set_next_input : set_next_input_callback,
472 488 * }
473 489 * },
474 490 * iopub : {
475 491 * output : output_callback,
476 492 * clear_output : clear_output_callback,
477 493 * },
478 494 * input : raw_input_callback
479 495 * }
480 496 *
481 497 * Each callback will be passed the entire message as a single arugment.
482 498 * Payload handlers will be passed the corresponding payload and the execute_reply message.
483 499 */
484 500 Kernel.prototype.execute = function (code, callbacks, options) {
485 501 var content = {
486 502 code : code,
487 503 silent : true,
488 504 store_history : false,
489 505 user_expressions : {},
490 506 allow_stdin : false
491 507 };
492 508 callbacks = callbacks || {};
493 509 if (callbacks.input !== undefined) {
494 510 content.allow_stdin = true;
495 511 }
496 512 $.extend(true, content, options);
497 513 this.events.trigger('execution_request.Kernel', {kernel: this, content:content});
498 514 return this.send_shell_message("execute_request", content, callbacks);
499 515 };
500 516
501 517 /**
502 518 * When calling this method, pass a function to be called with the `complete_reply` message
503 519 * as its only argument when it arrives.
504 520 *
505 521 * `complete_reply` is documented
506 522 * [here](http://ipython.org/ipython-doc/dev/development/messaging.html#complete)
507 523 *
508 524 * @method complete
509 525 * @param code {string}
510 526 * @param cursor_pos {integer}
511 527 * @param callback {function}
512 528 *
513 529 */
514 530 Kernel.prototype.complete = function (code, cursor_pos, callback) {
515 531 var callbacks;
516 532 if (callback) {
517 533 callbacks = { shell : { reply : callback } };
518 534 }
519 535 var content = {
520 536 code : code,
521 537 cursor_pos : cursor_pos
522 538 };
523 539 return this.send_shell_message("complete_request", content, callbacks);
524 540 };
525 541
526 542 Kernel.prototype.send_input_reply = function (input) {
527 543 if (!this.is_connected()) {
528 544 throw new Error("kernel is not connected");
529 545 }
530 546 var content = {
531 547 value : input
532 548 };
533 549 this.events.trigger('input_reply.Kernel', {kernel: this, content:content});
534 550 var msg = this._get_msg("input_reply", content);
535 551 this.channels.stdin.send(JSON.stringify(msg));
536 552 return msg.header.msg_id;
537 553 };
538 554
539 555
540 556 // Reply handlers
541 557
542 558 Kernel.prototype.register_iopub_handler = function (msg_type, callback) {
543 559 this._iopub_handlers[msg_type] = callback;
544 560 };
545 561
546 562 Kernel.prototype.get_iopub_handler = function (msg_type) {
547 563 // get iopub handler for a specific message type
548 564 return this._iopub_handlers[msg_type];
549 565 };
550 566
551 567
552 568 Kernel.prototype.get_callbacks_for_msg = function (msg_id) {
553 569 // get callbacks for a specific message
554 570 if (msg_id == this.last_msg_id) {
555 571 return this.last_msg_callbacks;
556 572 } else {
557 573 return this._msg_callbacks[msg_id];
558 574 }
559 575 };
560 576
561 577
562 578 Kernel.prototype.clear_callbacks_for_msg = function (msg_id) {
563 579 if (this._msg_callbacks[msg_id] !== undefined ) {
564 580 delete this._msg_callbacks[msg_id];
565 581 }
566 582 };
567 583
568 584 Kernel.prototype._finish_shell = function (msg_id) {
569 585 var callbacks = this._msg_callbacks[msg_id];
570 586 if (callbacks !== undefined) {
571 587 callbacks.shell_done = true;
572 588 if (callbacks.iopub_done) {
573 589 this.clear_callbacks_for_msg(msg_id);
574 590 }
575 591 }
576 592 };
577 593
578 594 Kernel.prototype._finish_iopub = function (msg_id) {
579 595 var callbacks = this._msg_callbacks[msg_id];
580 596 if (callbacks !== undefined) {
581 597 callbacks.iopub_done = true;
582 598 if (callbacks.shell_done) {
583 599 this.clear_callbacks_for_msg(msg_id);
584 600 }
585 601 }
586 602 };
587 603
588 604 /* Set callbacks for a particular message.
589 605 * Callbacks should be a struct of the following form:
590 606 * shell : {
591 607 *
592 608 * }
593 609
594 610 */
595 611 Kernel.prototype.set_callbacks_for_msg = function (msg_id, callbacks) {
596 612 this.last_msg_id = msg_id;
597 613 if (callbacks) {
598 614 // shallow-copy mapping, because we will modify it at the top level
599 615 var cbcopy = this._msg_callbacks[msg_id] = this.last_msg_callbacks = {};
600 616 cbcopy.shell = callbacks.shell;
601 617 cbcopy.iopub = callbacks.iopub;
602 618 cbcopy.input = callbacks.input;
603 619 cbcopy.shell_done = (!callbacks.shell);
604 620 cbcopy.iopub_done = (!callbacks.iopub);
605 621 } else {
606 622 this.last_msg_callbacks = {};
607 623 }
608 624 };
609 625
610 626
611 627 Kernel.prototype._handle_shell_reply = function (e) {
612 628 var reply = $.parseJSON(e.data);
613 629 this.events.trigger('shell_reply.Kernel', {kernel: this, reply:reply});
614 630 var content = reply.content;
615 631 var metadata = reply.metadata;
616 632 var parent_id = reply.parent_header.msg_id;
617 633 var callbacks = this.get_callbacks_for_msg(parent_id);
618 634 if (!callbacks || !callbacks.shell) {
619 635 return;
620 636 }
621 637 var shell_callbacks = callbacks.shell;
622 638
623 639 // signal that shell callbacks are done
624 640 this._finish_shell(parent_id);
625 641
626 642 if (shell_callbacks.reply !== undefined) {
627 643 shell_callbacks.reply(reply);
628 644 }
629 645 if (content.payload && shell_callbacks.payload) {
630 646 this._handle_payloads(content.payload, shell_callbacks.payload, reply);
631 647 }
632 648 };
633 649
634 650
635 651 Kernel.prototype._handle_payloads = function (payloads, payload_callbacks, msg) {
636 652 var l = payloads.length;
637 653 // Payloads are handled by triggering events because we don't want the Kernel
638 654 // to depend on the Notebook or Pager classes.
639 655 for (var i=0; i<l; i++) {
640 656 var payload = payloads[i];
641 657 var callback = payload_callbacks[payload.source];
642 658 if (callback) {
643 659 callback(payload, msg);
644 660 }
645 661 }
646 662 };
647 663
648 664 Kernel.prototype._handle_status_message = function (msg) {
649 665 var execution_state = msg.content.execution_state;
650 666 var parent_id = msg.parent_header.msg_id;
651 667
652 668 // dispatch status msg callbacks, if any
653 669 var callbacks = this.get_callbacks_for_msg(parent_id);
654 670 if (callbacks && callbacks.iopub && callbacks.iopub.status) {
655 671 try {
656 672 callbacks.iopub.status(msg);
657 673 } catch (e) {
658 674 console.log("Exception in status msg handler", e, e.stack);
659 675 }
660 676 }
661 677
662 678 if (execution_state === 'busy') {
663 679 this.events.trigger('status_busy.Kernel', {kernel: this});
664 680 } else if (execution_state === 'idle') {
665 681 // signal that iopub callbacks are (probably) done
666 682 // async output may still arrive,
667 683 // but only for the most recent request
668 684 this._finish_iopub(parent_id);
669 685
670 686 // trigger status_idle event
671 687 this.events.trigger('status_idle.Kernel', {kernel: this});
672 688 } else if (execution_state === 'restarting') {
673 689 // autorestarting is distinct from restarting,
674 690 // in that it means the kernel died and the server is restarting it.
675 691 // status_restarting sets the notification widget,
676 692 // autorestart shows the more prominent dialog.
677 693 this.events.trigger('status_autorestarting.Kernel', {kernel: this});
678 694 this.events.trigger('status_restarting.Kernel', {kernel: this});
679 695 } else if (execution_state === 'dead') {
680 696 this.stop_channels();
681 697 this.events.trigger('status_dead.Kernel', {kernel: this});
682 698 this.events.trigger('status_restart_failed.Kernel', {kernel: this});
683 699 }
684 700 };
685 701
686 702
687 703 // handle clear_output message
688 704 Kernel.prototype._handle_clear_output = function (msg) {
689 705 var callbacks = this.get_callbacks_for_msg(msg.parent_header.msg_id);
690 706 if (!callbacks || !callbacks.iopub) {
691 707 return;
692 708 }
693 709 var callback = callbacks.iopub.clear_output;
694 710 if (callback) {
695 711 callback(msg);
696 712 }
697 713 };
698 714
699 715
700 716 // handle an output message (execute_result, display_data, etc.)
701 717 Kernel.prototype._handle_output_message = function (msg) {
702 718 var callbacks = this.get_callbacks_for_msg(msg.parent_header.msg_id);
703 719 if (!callbacks || !callbacks.iopub) {
704 720 return;
705 721 }
706 722 var callback = callbacks.iopub.output;
707 723 if (callback) {
708 724 callback(msg);
709 725 }
710 726 };
711 727
712 728 // dispatch IOPub messages to respective handlers.
713 729 // each message type should have a handler.
714 730 Kernel.prototype._handle_iopub_message = function (e) {
715 731 var msg = $.parseJSON(e.data);
716 732
717 733 var handler = this.get_iopub_handler(msg.header.msg_type);
718 734 if (handler !== undefined) {
719 735 handler(msg);
720 736 }
721 737 };
722 738
723 739
724 740 Kernel.prototype._handle_input_request = function (e) {
725 741 var request = $.parseJSON(e.data);
726 742 var header = request.header;
727 743 var content = request.content;
728 744 var metadata = request.metadata;
729 745 var msg_type = header.msg_type;
730 746 if (msg_type !== 'input_request') {
731 747 console.log("Invalid input request!", request);
732 748 return;
733 749 }
734 750 var callbacks = this.get_callbacks_for_msg(request.parent_header.msg_id);
735 751 if (callbacks) {
736 752 if (callbacks.input) {
737 753 callbacks.input(request);
738 754 }
739 755 }
740 756 };
741 757
742 758 // Backwards compatability.
743 759 IPython.Kernel = Kernel;
744 760
745 761 return {'Kernel': Kernel};
746 762 });
General Comments 0
You need to be logged in to leave comments. Login now