Show More
@@ -0,0 +1,43 b'' | |||||
|
1 | ||||
|
2 | // | |||
|
3 | // Tests for the Session object | |||
|
4 | // | |||
|
5 | ||||
|
6 | casper.notebook_test(function () { | |||
|
7 | this.evaluate(function () { | |||
|
8 | var kernel = IPython.notebook.session.kernel; | |||
|
9 | IPython._channels = [ | |||
|
10 | kernel.shell_channel, | |||
|
11 | kernel.iopub_channel, | |||
|
12 | kernel.stdin_channel | |||
|
13 | ]; | |||
|
14 | IPython.notebook.session.delete(); | |||
|
15 | }); | |||
|
16 | ||||
|
17 | this.waitFor(function () { | |||
|
18 | return this.evaluate(function(){ | |||
|
19 | for (var i=0; i < IPython._channels.length; i++) { | |||
|
20 | var ws = IPython._channels[i]; | |||
|
21 | if (ws.readyState !== ws.CLOSED) { | |||
|
22 | return false; | |||
|
23 | } | |||
|
24 | } | |||
|
25 | return true; | |||
|
26 | }); | |||
|
27 | }); | |||
|
28 | ||||
|
29 | this.then(function () { | |||
|
30 | var states = this.evaluate(function() { | |||
|
31 | var states = []; | |||
|
32 | for (var i = 0; i < IPython._channels.length; i++) { | |||
|
33 | states.push(IPython._channels[i].readyState); | |||
|
34 | } | |||
|
35 | return states; | |||
|
36 | }); | |||
|
37 | ||||
|
38 | for (var i = 0; i < states.length; i++) { | |||
|
39 | this.test.assertEquals(states[i], WebSocket.CLOSED, | |||
|
40 | "Session.delete closes websockets[" + i + "]"); | |||
|
41 | } | |||
|
42 | }); | |||
|
43 | }); |
@@ -84,6 +84,9 b' class KernelActionHandler(IPythonHandler):' | |||||
84 |
|
84 | |||
85 | class ZMQChannelHandler(AuthenticatedZMQStreamHandler): |
|
85 | class ZMQChannelHandler(AuthenticatedZMQStreamHandler): | |
86 |
|
86 | |||
|
87 | def __repr__(self): | |||
|
88 | return "%s(%s)" % (self.__class__.__name__, getattr(self, 'kernel_id', 'uninitialized')) | |||
|
89 | ||||
87 | def create_stream(self): |
|
90 | def create_stream(self): | |
88 | km = self.kernel_manager |
|
91 | km = self.kernel_manager | |
89 | meth = getattr(km, 'connect_%s' % self.channel) |
|
92 | meth = getattr(km, 'connect_%s' % self.channel) | |
@@ -145,6 +148,12 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):' | |||||
145 | self.zmq_stream.on_recv(self._on_zmq_reply) |
|
148 | self.zmq_stream.on_recv(self._on_zmq_reply) | |
146 |
|
149 | |||
147 | def on_message(self, msg): |
|
150 | def on_message(self, msg): | |
|
151 | if self.zmq_stream is None: | |||
|
152 | return | |||
|
153 | elif self.zmq_stream.closed(): | |||
|
154 | self.log.info("%s closed, closing websocket.", self) | |||
|
155 | self.close() | |||
|
156 | return | |||
148 | msg = json.loads(msg) |
|
157 | msg = json.loads(msg) | |
149 | self.session.send(self.zmq_stream, msg) |
|
158 | self.session.send(self.zmq_stream, msg) | |
150 |
|
159 |
@@ -54,9 +54,19 b' define([' | |||||
54 | return; |
|
54 | return; | |
55 | } |
|
55 | } | |
56 | var ks = this.kernelspecs[kernel_name]; |
|
56 | var ks = this.kernelspecs[kernel_name]; | |
57 | this.events.trigger('spec_changed.Kernel', ks); |
|
57 | try { | |
58 | this.notebook.session.delete(); |
|
|||
59 | this.notebook.start_session(kernel_name); |
|
58 | this.notebook.start_session(kernel_name); | |
|
59 | } catch (e) { | |||
|
60 | if (e.name === 'SessionAlreadyStarting') { | |||
|
61 | console.log("Cannot change kernel while waiting for pending session start."); | |||
|
62 | } else { | |||
|
63 | // unhandled error | |||
|
64 | throw e; | |||
|
65 | } | |||
|
66 | // only trigger spec_changed if change was successful | |||
|
67 | return; | |||
|
68 | } | |||
|
69 | this.events.trigger('spec_changed.Kernel', ks); | |||
60 | }; |
|
70 | }; | |
61 |
|
71 | |||
62 | KernelSelector.prototype.bind_events = function() { |
|
72 | KernelSelector.prototype.bind_events = function() { |
@@ -157,12 +157,13 b' define([' | |||||
157 | } |
|
157 | } | |
158 | }); |
|
158 | }); | |
159 | this.element.find('#kill_and_exit').click(function () { |
|
159 | this.element.find('#kill_and_exit').click(function () { | |
160 | that.notebook.session.delete(); |
|
160 | var close_window = function () { | |
161 | setTimeout(function(){ |
|
|||
162 | // allow closing of new tabs in Chromium, impossible in FF |
|
161 | // allow closing of new tabs in Chromium, impossible in FF | |
163 | window.open('', '_self', ''); |
|
162 | window.open('', '_self', ''); | |
164 | window.close(); |
|
163 | window.close(); | |
165 |
} |
|
164 | }; | |
|
165 | // finish with close on success or failure | |||
|
166 | that.notebook.session.delete(close_window, close_window); | |||
166 | }); |
|
167 | }); | |
167 | // Edit |
|
168 | // Edit | |
168 | this.element.find('#cut_cell').click(function () { |
|
169 | this.element.find('#cut_cell').click(function () { |
@@ -62,6 +62,7 b' define([' | |||||
62 | this.save_widget = options.save_widget; |
|
62 | this.save_widget = options.save_widget; | |
63 | this.tooltip = new tooltip.Tooltip(this.events); |
|
63 | this.tooltip = new tooltip.Tooltip(this.events); | |
64 | this.ws_url = options.ws_url; |
|
64 | this.ws_url = options.ws_url; | |
|
65 | this._session_starting = false; | |||
65 | // default_kernel_name is a temporary measure while we implement proper |
|
66 | // default_kernel_name is a temporary measure while we implement proper | |
66 | // kernel selection and delayed start. Do not rely on it. |
|
67 | // kernel selection and delayed start. Do not rely on it. | |
67 | this.default_kernel_name = 'python'; |
|
68 | this.default_kernel_name = 'python'; | |
@@ -1525,9 +1526,38 b' define([' | |||||
1525 | * @method start_session |
|
1526 | * @method start_session | |
1526 | */ |
|
1527 | */ | |
1527 | Notebook.prototype.start_session = function (kernel_name) { |
|
1528 | Notebook.prototype.start_session = function (kernel_name) { | |
|
1529 | var that = this; | |||
1528 | if (kernel_name === undefined) { |
|
1530 | if (kernel_name === undefined) { | |
1529 | kernel_name = this.default_kernel_name; |
|
1531 | kernel_name = this.default_kernel_name; | |
1530 | } |
|
1532 | } | |
|
1533 | if (this._session_starting) { | |||
|
1534 | throw new session.SessionAlreadyStarting(); | |||
|
1535 | } | |||
|
1536 | this._session_starting = true; | |||
|
1537 | ||||
|
1538 | if (this.session !== null) { | |||
|
1539 | var s = this.session; | |||
|
1540 | this.session = null; | |||
|
1541 | // need to start the new session in a callback after delete, | |||
|
1542 | // because javascript does not guarantee the ordering of AJAX requests (?!) | |||
|
1543 | s.delete(function () { | |||
|
1544 | // on successful delete, start new session | |||
|
1545 | that._session_starting = false; | |||
|
1546 | that.start_session(kernel_name); | |||
|
1547 | }, function (jqXHR, status, error) { | |||
|
1548 | // log the failed delete, but still create a new session | |||
|
1549 | // 404 just means it was already deleted by someone else, | |||
|
1550 | // but other errors are possible. | |||
|
1551 | utils.log_ajax_error(jqXHR, status, error); | |||
|
1552 | that._session_starting = false; | |||
|
1553 | that.start_session(kernel_name); | |||
|
1554 | } | |||
|
1555 | ); | |||
|
1556 | return; | |||
|
1557 | } | |||
|
1558 | ||||
|
1559 | ||||
|
1560 | ||||
1531 | this.session = new session.Session({ |
|
1561 | this.session = new session.Session({ | |
1532 | base_url: this.base_url, |
|
1562 | base_url: this.base_url, | |
1533 | ws_url: this.ws_url, |
|
1563 | ws_url: this.ws_url, | |
@@ -1539,7 +1569,10 b' define([' | |||||
1539 | kernel_name: kernel_name, |
|
1569 | kernel_name: kernel_name, | |
1540 | notebook: this}); |
|
1570 | notebook: this}); | |
1541 |
|
1571 | |||
1542 | this.session.start($.proxy(this._session_started, this)); |
|
1572 | this.session.start( | |
|
1573 | $.proxy(this._session_started, this), | |||
|
1574 | $.proxy(this._session_start_failed, this) | |||
|
1575 | ); | |||
1543 | }; |
|
1576 | }; | |
1544 |
|
1577 | |||
1545 |
|
1578 | |||
@@ -1549,6 +1582,7 b' define([' | |||||
1549 | * |
|
1582 | * | |
1550 | */ |
|
1583 | */ | |
1551 | Notebook.prototype._session_started = function(){ |
|
1584 | Notebook.prototype._session_started = function (){ | |
|
1585 | this._session_starting = false; | |||
1552 | this.kernel = this.session.kernel; |
|
1586 | this.kernel = this.session.kernel; | |
1553 | var ncells = this.ncells(); |
|
1587 | var ncells = this.ncells(); | |
1554 | for (var i=0; i<ncells; i++) { |
|
1588 | for (var i=0; i<ncells; i++) { | |
@@ -1558,6 +1592,10 b' define([' | |||||
1558 | } |
|
1592 | } | |
1559 | } |
|
1593 | } | |
1560 | }; |
|
1594 | }; | |
|
1595 | Notebook.prototype._session_start_failed = function (jqxhr, status, error){ | |||
|
1596 | this._session_starting = false; | |||
|
1597 | utils.log_ajax_error(jqxhr, status, error); | |||
|
1598 | }; | |||
1561 |
|
1599 | |||
1562 | /** |
|
1600 | /** | |
1563 | * Prompt the user to restart the IPython kernel. |
|
1601 | * Prompt the user to restart the IPython kernel. |
@@ -109,6 +109,12 b' define([' | |||||
109 | knw.set_message("Restarting kernel", 2000); |
|
109 | knw.set_message("Restarting kernel", 2000); | |
110 | }); |
|
110 | }); | |
111 |
|
111 | |||
|
112 | this.events.on('status_dead.Kernel',function () { | |||
|
113 | that.save_widget.update_document_title(); | |||
|
114 | knw.danger("Dead kernel"); | |||
|
115 | $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead'); | |||
|
116 | }); | |||
|
117 | ||||
112 | this.events.on('status_interrupting.Kernel',function () { |
|
118 | this.events.on('status_interrupting.Kernel',function () { | |
113 | knw.set_message("Interrupting kernel", 2000); |
|
119 | knw.set_message("Interrupting kernel", 2000); | |
114 | }); |
|
120 | }); | |
@@ -118,6 +124,8 b' define([' | |||||
118 | $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy'); |
|
124 | $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy'); | |
119 |
|
125 | |||
120 | this.events.on('status_started.Kernel', function (evt, data) { |
|
126 | this.events.on('status_started.Kernel', function (evt, data) { | |
|
127 | knw.info("Websockets Connected", 500); | |||
|
128 | that.events.trigger('status_busy.Kernel'); | |||
121 | data.kernel.kernel_info(function () { |
|
129 | data.kernel.kernel_info(function () { | |
122 | that.events.trigger('status_idle.Kernel'); |
|
130 | that.events.trigger('status_idle.Kernel'); | |
123 | }); |
|
131 | }); | |
@@ -153,8 +161,13 b' define([' | |||||
153 | var ws_url = data.ws_url; |
|
161 | var ws_url = data.ws_url; | |
154 | var early = data.early; |
|
162 | var early = data.early; | |
155 | var msg; |
|
163 | var msg; | |
|
164 | ||||
|
165 | $kernel_ind_icon | |||
|
166 | .attr('class', 'kernel_disconnected_icon') | |||
|
167 | .attr('title', 'No Connection to Kernel'); | |||
|
168 | ||||
156 | if (!early) { |
|
169 | if (!early) { | |
157 |
knw. |
|
170 | knw.warning('Reconnecting'); | |
158 | setTimeout(function () { |
|
171 | setTimeout(function () { | |
159 | kernel.start_channels(); |
|
172 | kernel.start_channels(); | |
160 | }, 5000); |
|
173 | }, 5000); | |
@@ -173,7 +186,7 b' define([' | |||||
173 | "OK": {}, |
|
186 | "OK": {}, | |
174 | "Reconnect": { |
|
187 | "Reconnect": { | |
175 | click: function () { |
|
188 | click: function () { | |
176 |
knw. |
|
189 | knw.warning('Reconnecting'); | |
177 | setTimeout(function () { |
|
190 | setTimeout(function () { | |
178 | kernel.start_channels(); |
|
191 | kernel.start_channels(); | |
179 | }, 5000); |
|
192 | }, 5000); |
@@ -43,4 +43,12 b'' | |||||
43 | .icon(@fa-var-circle); |
|
43 | .icon(@fa-var-circle); | |
44 | } |
|
44 | } | |
45 |
|
45 | |||
|
46 | .kernel_dead_icon:before { | |||
|
47 | .icon(@fa-var-bomb); | |||
|
48 | } | |||
|
49 | ||||
|
50 | .kernel_disconnected_icon:before { | |||
|
51 | .icon(@fa-var-chain-broken); | |||
|
52 | } | |||
|
53 | ||||
46 |
|
54 |
@@ -179,10 +179,18 b' define([' | |||||
179 | that._websocket_closed(ws_host_url, false); |
|
179 | that._websocket_closed(ws_host_url, false); | |
180 | } |
|
180 | } | |
181 | }; |
|
181 | }; | |
|
182 | var ws_error = function(evt){ | |||
|
183 | if (already_called_onclose){ | |||
|
184 | return; | |||
|
185 | } | |||
|
186 | already_called_onclose = true; | |||
|
187 | that._websocket_closed(ws_host_url, false); | |||
|
188 | }; | |||
182 | var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel]; |
|
189 | var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel]; | |
183 | for (var i=0; i < channels.length; i++) { |
|
190 | for (var i=0; i < channels.length; i++) { | |
184 | channels[i].onopen = $.proxy(this._ws_opened, this); |
|
191 | channels[i].onopen = $.proxy(this._ws_opened, this); | |
185 | channels[i].onclose = ws_closed_early; |
|
192 | channels[i].onclose = ws_closed_early; | |
|
193 | channels[i].onerror = ws_error; | |||
186 | } |
|
194 | } | |
187 | // switch from early-close to late-close message after 1s |
|
195 | // switch from early-close to late-close message after 1s | |
188 | setTimeout(function() { |
|
196 | setTimeout(function() { | |
@@ -211,7 +219,7 b' define([' | |||||
211 | var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel]; |
|
219 | var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel]; | |
212 | for (var i=0; i < channels.length; i++) { |
|
220 | for (var i=0; i < channels.length; i++) { | |
213 | // if any channel is not ready, don't trigger event. |
|
221 | // if any channel is not ready, don't trigger event. | |
214 |
if ( |
|
222 | if ( channels[i].readyState == WebSocket.OPEN ) return; | |
215 | } |
|
223 | } | |
216 | // all events ready, trigger started event. |
|
224 | // all events ready, trigger started event. | |
217 | this.events.trigger('status_started.Kernel', {kernel: this}); |
|
225 | this.events.trigger('status_started.Kernel', {kernel: this}); | |
@@ -385,15 +393,17 b' define([' | |||||
385 | }; |
|
393 | }; | |
386 |
|
394 | |||
387 |
|
395 | |||
388 | Kernel.prototype.kill = function () { |
|
396 | Kernel.prototype.kill = function (success, error) { | |
389 | if (this.running) { |
|
397 | if (this.running) { | |
390 | this.running = false; |
|
398 | this.running = false; | |
391 | var settings = { |
|
399 | var settings = { | |
392 | cache : false, |
|
400 | cache : false, | |
393 | type : "DELETE", |
|
401 | type : "DELETE", | |
394 | error : utils.log_ajax_error, |
|
402 | success : success, | |
|
403 | error : error || utils.log_ajax_error, | |||
395 | }; |
|
404 | }; | |
396 | $.ajax(utils.url_join_encode(this.kernel_url), settings); |
|
405 | $.ajax(utils.url_join_encode(this.kernel_url), settings); | |
|
406 | this.stop_channels(); | |||
397 | } |
|
407 | } | |
398 | }; |
|
408 | }; | |
399 |
|
409 |
@@ -21,7 +21,7 b' define([' | |||||
21 | this.ws_url = options.ws_url; |
|
21 | this.ws_url = options.ws_url; | |
22 | }; |
|
22 | }; | |
23 |
|
23 | |||
24 |
Session.prototype.start = function( |
|
24 | Session.prototype.start = function (success, error) { | |
25 | var that = this; |
|
25 | var that = this; | |
26 | var model = { |
|
26 | var model = { | |
27 | notebook : { |
|
27 | notebook : { | |
@@ -40,11 +40,17 b' define([' | |||||
40 | dataType : "json", |
|
40 | dataType : "json", | |
41 | success : function (data, status, xhr) { |
|
41 | success : function (data, status, xhr) { | |
42 | that._handle_start_success(data); |
|
42 | that._handle_start_success(data); | |
43 |
if ( |
|
43 | if (success) { | |
44 |
|
|
44 | success(data, status, xhr); | |
45 | } |
|
45 | } | |
46 | }, |
|
46 | }, | |
47 |
error : |
|
47 | error : function (xhr, status, err) { | |
|
48 | that._handle_start_failure(xhr, status, err); | |||
|
49 | if (error !== undefined) { | |||
|
50 | error(xhr, status, err); | |||
|
51 | } | |||
|
52 | utils.log_ajax_error(xhr, status, err); | |||
|
53 | } | |||
48 | }; |
|
54 | }; | |
49 | var url = utils.url_join_encode(this.base_url, 'api/sessions'); |
|
55 | var url = utils.url_join_encode(this.base_url, 'api/sessions'); | |
50 | $.ajax(url, settings); |
|
56 | $.ajax(url, settings); | |
@@ -71,15 +77,19 b' define([' | |||||
71 | $.ajax(url, settings); |
|
77 | $.ajax(url, settings); | |
72 | }; |
|
78 | }; | |
73 |
|
79 | |||
74 | Session.prototype.delete = function() { |
|
80 | Session.prototype.delete = function (success, error) { | |
75 | var settings = { |
|
81 | var settings = { | |
76 | processData : false, |
|
82 | processData : false, | |
77 | cache : false, |
|
83 | cache : false, | |
78 | type : "DELETE", |
|
84 | type : "DELETE", | |
79 | dataType : "json", |
|
85 | dataType : "json", | |
80 | error : utils.log_ajax_error, |
|
86 | success : success, | |
|
87 | error : error || utils.log_ajax_error, | |||
81 | }; |
|
88 | }; | |
|
89 | if (this.kernel) { | |||
82 | this.kernel.running = false; |
|
90 | this.kernel.running = false; | |
|
91 | this.kernel.stop_channels(); | |||
|
92 | } | |||
83 | var url = utils.url_join_encode(this.base_url, 'api/sessions', this.id); |
|
93 | var url = utils.url_join_encode(this.base_url, 'api/sessions', this.id); | |
84 | $.ajax(url, settings); |
|
94 | $.ajax(url, settings); | |
85 | }; |
|
95 | }; | |
@@ -100,6 +110,11 b' define([' | |||||
100 | this.kernel._kernel_started(data.kernel); |
|
110 | this.kernel._kernel_started(data.kernel); | |
101 | }; |
|
111 | }; | |
102 |
|
112 | |||
|
113 | Session.prototype._handle_start_failure = function (xhr, status, error) { | |||
|
114 | this.events.trigger('start_failed.Session', [this, xhr, status, error]); | |||
|
115 | this.events.trigger('status_dead.Kernel'); | |||
|
116 | }; | |||
|
117 | ||||
103 | /** |
|
118 | /** | |
104 | * Prompt the user to restart the IPython kernel. |
|
119 | * Prompt the user to restart the IPython kernel. | |
105 | * |
|
120 | * | |
@@ -118,8 +133,18 b' define([' | |||||
118 | this.kernel.kill(); |
|
133 | this.kernel.kill(); | |
119 | }; |
|
134 | }; | |
120 |
|
135 | |||
|
136 | var SessionAlreadyStarting = function (message) { | |||
|
137 | this.name = "SessionAlreadyStarting"; | |||
|
138 | this.message = (message || ""); | |||
|
139 | }; | |||
|
140 | ||||
|
141 | SessionAlreadyStarting.prototype = Error.prototype; | |||
|
142 | ||||
121 | // For backwards compatability. |
|
143 | // For backwards compatability. | |
122 | IPython.Session = Session; |
|
144 | IPython.Session = Session; | |
123 |
|
145 | |||
124 | return {'Session': Session}; |
|
146 | return { | |
|
147 | Session: Session, | |||
|
148 | SessionAlreadyStarting: SessionAlreadyStarting, | |||
|
149 | }; | |||
125 | }); |
|
150 | }); |
@@ -9998,6 +9998,38 b' ul#help_menu li a i {' | |||||
9998 | .kernel_busy_icon:before.pull-right { |
|
9998 | .kernel_busy_icon:before.pull-right { | |
9999 | margin-left: .3em; |
|
9999 | margin-left: .3em; | |
10000 | } |
|
10000 | } | |
|
10001 | .kernel_dead_icon:before { | |||
|
10002 | display: inline-block; | |||
|
10003 | font-family: FontAwesome; | |||
|
10004 | font-style: normal; | |||
|
10005 | font-weight: normal; | |||
|
10006 | line-height: 1; | |||
|
10007 | -webkit-font-smoothing: antialiased; | |||
|
10008 | -moz-osx-font-smoothing: grayscale; | |||
|
10009 | content: "\f1e2"; | |||
|
10010 | } | |||
|
10011 | .kernel_dead_icon:before.pull-left { | |||
|
10012 | margin-right: .3em; | |||
|
10013 | } | |||
|
10014 | .kernel_dead_icon:before.pull-right { | |||
|
10015 | margin-left: .3em; | |||
|
10016 | } | |||
|
10017 | .kernel_disconnected_icon:before { | |||
|
10018 | display: inline-block; | |||
|
10019 | font-family: FontAwesome; | |||
|
10020 | font-style: normal; | |||
|
10021 | font-weight: normal; | |||
|
10022 | line-height: 1; | |||
|
10023 | -webkit-font-smoothing: antialiased; | |||
|
10024 | -moz-osx-font-smoothing: grayscale; | |||
|
10025 | content: "\f127"; | |||
|
10026 | } | |||
|
10027 | .kernel_disconnected_icon:before.pull-left { | |||
|
10028 | margin-right: .3em; | |||
|
10029 | } | |||
|
10030 | .kernel_disconnected_icon:before.pull-right { | |||
|
10031 | margin-left: .3em; | |||
|
10032 | } | |||
10001 | .notification_widget { |
|
10033 | .notification_widget { | |
10002 | color: #777777; |
|
10034 | color: #777777; | |
10003 | padding: 1px 12px; |
|
10035 | padding: 1px 12px; |
@@ -1,6 +1,6 b'' | |||||
1 |
|
1 | |||
2 | // |
|
2 | // | |
3 | // Miscellaneous javascript tests |
|
3 | // Kernel tests | |
4 | // |
|
4 | // | |
5 | casper.notebook_test(function () { |
|
5 | casper.notebook_test(function () { | |
6 | this.evaluate(function () { |
|
6 | this.evaluate(function () { | |
@@ -25,4 +25,40 b' casper.notebook_test(function () {' | |||||
25 | this.test.assertTrue( kernel_info_response.content !== undefined, 'Kernel_info_reply is not undefined'); |
|
25 | this.test.assertTrue( kernel_info_response.content !== undefined, 'Kernel_info_reply is not undefined'); | |
26 | }); |
|
26 | }); | |
27 |
|
27 | |||
|
28 | this.thenEvaluate(function () { | |||
|
29 | var kernel = IPython.notebook.session.kernel; | |||
|
30 | IPython._channels = [ | |||
|
31 | kernel.shell_channel, | |||
|
32 | kernel.iopub_channel, | |||
|
33 | kernel.stdin_channel | |||
|
34 | ]; | |||
|
35 | kernel.kill(); | |||
|
36 | }); | |||
|
37 | ||||
|
38 | this.waitFor(function () { | |||
|
39 | return this.evaluate(function(){ | |||
|
40 | for (var i=0; i < IPython._channels.length; i++) { | |||
|
41 | var ws = IPython._channels[i]; | |||
|
42 | if (ws.readyState !== ws.CLOSED) { | |||
|
43 | return false; | |||
|
44 | } | |||
|
45 | } | |||
|
46 | return true; | |||
|
47 | }); | |||
|
48 | }); | |||
|
49 | ||||
|
50 | this.then(function () { | |||
|
51 | var states = this.evaluate(function() { | |||
|
52 | var states = []; | |||
|
53 | for (var i = 0; i < IPython._channels.length; i++) { | |||
|
54 | states.push(IPython._channels[i].readyState); | |||
|
55 | } | |||
|
56 | return states; | |||
|
57 | }); | |||
|
58 | ||||
|
59 | for (var i = 0; i < states.length; i++) { | |||
|
60 | this.test.assertEquals(states[i], WebSocket.CLOSED, | |||
|
61 | "Kernel.kill closes websockets[" + i + "]"); | |||
|
62 | } | |||
|
63 | }); | |||
28 | }); |
|
64 | }); |
General Comments 0
You need to be logged in to leave comments.
Login now