Show More
@@ -1,15 +1,7 b'' | |||
|
1 | 1 | """Base class to manage comms""" |
|
2 | 2 | |
|
3 | #----------------------------------------------------------------------------- | |
|
4 | # Copyright (C) 2013 The IPython Development Team | |
|
5 | # | |
|
6 | # Distributed under the terms of the BSD License. The full license is in | |
|
7 | # the file COPYING, distributed as part of this software. | |
|
8 | #----------------------------------------------------------------------------- | |
|
9 | ||
|
10 | #----------------------------------------------------------------------------- | |
|
11 | # Imports | |
|
12 | #----------------------------------------------------------------------------- | |
|
3 | # Copyright (c) IPython Development Team. | |
|
4 | # Distributed under the terms of the Modified BSD License. | |
|
13 | 5 | |
|
14 | 6 | import sys |
|
15 | 7 | |
@@ -23,9 +15,6 b' from IPython.utils.traitlets import Instance, Unicode, Dict, Any' | |||
|
23 | 15 | |
|
24 | 16 | from .comm import Comm |
|
25 | 17 | |
|
26 | #----------------------------------------------------------------------------- | |
|
27 | # Code | |
|
28 | #----------------------------------------------------------------------------- | |
|
29 | 18 | |
|
30 | 19 | def lazy_keys(dikt): |
|
31 | 20 | """Return lazy-evaluated string representation of a dictionary's keys |
@@ -36,27 +25,6 b' def lazy_keys(dikt):' | |||
|
36 | 25 | return LazyEvaluate(lambda d: list(d.keys())) |
|
37 | 26 | |
|
38 | 27 | |
|
39 | def with_output(method): | |
|
40 | """method decorator for ensuring output is handled properly in a message handler | |
|
41 | ||
|
42 | - sets parent header before entering the method | |
|
43 | - publishes busy/idle | |
|
44 | - flushes stdout/stderr after | |
|
45 | """ | |
|
46 | def method_with_output(self, stream, ident, msg): | |
|
47 | parent = msg['header'] | |
|
48 | self.shell.set_parent(parent) | |
|
49 | self.shell.kernel._publish_status('busy', parent) | |
|
50 | try: | |
|
51 | return method(self, stream, ident, msg) | |
|
52 | finally: | |
|
53 | sys.stdout.flush() | |
|
54 | sys.stderr.flush() | |
|
55 | self.shell.kernel._publish_status('idle', parent) | |
|
56 | ||
|
57 | return method_with_output | |
|
58 | ||
|
59 | ||
|
60 | 28 | class CommManager(LoggingConfigurable): |
|
61 | 29 | """Manager for Comms in the Kernel""" |
|
62 | 30 | |
@@ -127,7 +95,6 b' class CommManager(LoggingConfigurable):' | |||
|
127 | 95 | return comm |
|
128 | 96 | |
|
129 | 97 | # Message handlers |
|
130 | @with_output | |
|
131 | 98 | def comm_open(self, stream, ident, msg): |
|
132 | 99 | """Handler for comm_open messages""" |
|
133 | 100 | content = msg['content'] |
@@ -151,7 +118,6 b' class CommManager(LoggingConfigurable):' | |||
|
151 | 118 | comm.close() |
|
152 | 119 | self.unregister_comm(comm_id) |
|
153 | 120 | |
|
154 | @with_output | |
|
155 | 121 | def comm_msg(self, stream, ident, msg): |
|
156 | 122 | """Handler for comm_msg messages""" |
|
157 | 123 | content = msg['content'] |
@@ -165,7 +131,6 b' class CommManager(LoggingConfigurable):' | |||
|
165 | 131 | except Exception: |
|
166 | 132 | self.log.error("Exception in comm_msg for %s", comm_id, exc_info=True) |
|
167 | 133 | |
|
168 | @with_output | |
|
169 | 134 | def comm_close(self, stream, ident, msg): |
|
170 | 135 | """Handler for comm_close messages""" |
|
171 | 136 | content = msg['content'] |
@@ -162,6 +162,10 b' class Kernel(Configurable):' | |||
|
162 | 162 | self.log.error("Invalid Message", exc_info=True) |
|
163 | 163 | return |
|
164 | 164 | |
|
165 | # Set the parent message for side effects. | |
|
166 | self.set_parent(idents, msg) | |
|
167 | self._publish_status(u'busy') | |
|
168 | ||
|
165 | 169 | header = msg['header'] |
|
166 | 170 | msg_id = header['msg_id'] |
|
167 | 171 | msg_type = msg['header']['msg_type'] |
@@ -197,6 +201,10 b' class Kernel(Configurable):' | |||
|
197 | 201 | finally: |
|
198 | 202 | signal(SIGINT, sig) |
|
199 | 203 | |
|
204 | sys.stdout.flush() | |
|
205 | sys.stderr.flush() | |
|
206 | self._publish_status(u'idle') | |
|
207 | ||
|
200 | 208 | def enter_eventloop(self): |
|
201 | 209 | """enter eventloop""" |
|
202 | 210 | self.log.info("entering eventloop %s", self.eventloop) |
@@ -281,7 +289,7 b' class Kernel(Configurable):' | |||
|
281 | 289 | self.session.send(self.iopub_socket, |
|
282 | 290 | u'status', |
|
283 | 291 | {u'execution_state': status}, |
|
284 | parent=parent, | |
|
292 | parent=parent or self._parent_header, | |
|
285 | 293 | ident=self._topic('status'), |
|
286 | 294 | ) |
|
287 | 295 | |
@@ -313,8 +321,6 b' class Kernel(Configurable):' | |||
|
313 | 321 | def execute_request(self, stream, ident, parent): |
|
314 | 322 | """handle an execute_request""" |
|
315 | 323 | |
|
316 | self._publish_status(u'busy', parent) | |
|
317 | ||
|
318 | 324 | try: |
|
319 | 325 | content = parent[u'content'] |
|
320 | 326 | code = py3compat.cast_unicode_py2(content[u'code']) |
@@ -329,9 +335,6 b' class Kernel(Configurable):' | |||
|
329 | 335 | |
|
330 | 336 | md = self._make_metadata(parent['metadata']) |
|
331 | 337 | |
|
332 | # Set the parent message of the display hook and out streams. | |
|
333 | self.set_parent(ident, parent) | |
|
334 | ||
|
335 | 338 | # Re-broadcast our input for the benefit of listening clients, and |
|
336 | 339 | # start computing output |
|
337 | 340 | if not silent: |
@@ -367,8 +370,6 b' class Kernel(Configurable):' | |||
|
367 | 370 | if not silent and reply_msg['content']['status'] == u'error': |
|
368 | 371 | self._abort_queues() |
|
369 | 372 | |
|
370 | self._publish_status(u'idle', parent) | |
|
371 | ||
|
372 | 373 | def do_execute(self, code, silent, store_history=True, |
|
373 | 374 | user_experssions=None, allow_stdin=False): |
|
374 | 375 | """Execute user code. Must be overridden by subclasses. |
@@ -484,11 +485,6 b' class Kernel(Configurable):' | |||
|
484 | 485 | self.log.error("Got bad msg: %s", parent, exc_info=True) |
|
485 | 486 | return |
|
486 | 487 | |
|
487 | self._publish_status(u'busy', parent) | |
|
488 | ||
|
489 | # Set the parent message of the display hook and out streams. | |
|
490 | self.set_parent(ident, parent) | |
|
491 | ||
|
492 | 488 | md = self._make_metadata(parent['metadata']) |
|
493 | 489 | |
|
494 | 490 | reply_content, result_buf = self.do_apply(content, bufs, msg_id, md) |
@@ -503,8 +499,6 b' class Kernel(Configurable):' | |||
|
503 | 499 | self.session.send(stream, u'apply_reply', reply_content, |
|
504 | 500 | parent=parent, ident=ident,buffers=result_buf, metadata=md) |
|
505 | 501 | |
|
506 | self._publish_status(u'idle', parent) | |
|
507 | ||
|
508 | 502 | def do_apply(self, content, bufs, msg_id, reply_metadata): |
|
509 | 503 | """Override in subclasses to support the IPython parallel framework. |
|
510 | 504 | """ |
@@ -886,12 +886,17 b' This message type is used by frontends to monitor the status of the kernel.' | |||
|
886 | 886 | Message type: ``status``:: |
|
887 | 887 | |
|
888 | 888 | content = { |
|
889 |
# When the kernel starts to |
|
|
889 | # When the kernel starts to handle a message, it will enter the 'busy' | |
|
890 | 890 | # state and when it finishes, it will enter the 'idle' state. |
|
891 | 891 | # The kernel will publish state 'starting' exactly once at process startup. |
|
892 | 892 | execution_state : ('busy', 'idle', 'starting') |
|
893 | 893 | } |
|
894 | 894 | |
|
895 | .. versionchanged:: 5.0 | |
|
896 | ||
|
897 | Busy and idle messages should be sent before/after handling every shell message, | |
|
898 | not just execution. | |
|
899 | ||
|
895 | 900 | Clear output |
|
896 | 901 | ------------ |
|
897 | 902 |
General Comments 0
You need to be logged in to leave comments.
Login now