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