##// END OF EJS Templates
Add the new search option `n` to the messaging protocol
Takafumi Arakaki -
Show More
@@ -1,931 +1,932 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """A simple interactive kernel that talks to a frontend over 0MQ.
2 """A simple interactive kernel that talks to a frontend over 0MQ.
3
3
4 Things to do:
4 Things to do:
5
5
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
7 call set_parent on all the PUB objects with the message about to be executed.
7 call set_parent on all the PUB objects with the message about to be executed.
8 * Implement random port and security key logic.
8 * Implement random port and security key logic.
9 * Implement control messages.
9 * Implement control messages.
10 * Implement event loop and poll version.
10 * Implement event loop and poll version.
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Standard library imports
18 # Standard library imports
19 import __builtin__
19 import __builtin__
20 import atexit
20 import atexit
21 import sys
21 import sys
22 import time
22 import time
23 import traceback
23 import traceback
24 import logging
24 import logging
25 import uuid
25 import uuid
26
26
27 from datetime import datetime
27 from datetime import datetime
28 from signal import (
28 from signal import (
29 signal, getsignal, default_int_handler, SIGINT, SIG_IGN
29 signal, getsignal, default_int_handler, SIGINT, SIG_IGN
30 )
30 )
31
31
32 # System library imports
32 # System library imports
33 import zmq
33 import zmq
34 from zmq.eventloop import ioloop
34 from zmq.eventloop import ioloop
35 from zmq.eventloop.zmqstream import ZMQStream
35 from zmq.eventloop.zmqstream import ZMQStream
36
36
37 # Local imports
37 # Local imports
38 from IPython.config.configurable import Configurable
38 from IPython.config.configurable import Configurable
39 from IPython.config.application import boolean_flag, catch_config_error
39 from IPython.config.application import boolean_flag, catch_config_error
40 from IPython.core.application import ProfileDir
40 from IPython.core.application import ProfileDir
41 from IPython.core.error import StdinNotImplementedError
41 from IPython.core.error import StdinNotImplementedError
42 from IPython.core.shellapp import (
42 from IPython.core.shellapp import (
43 InteractiveShellApp, shell_flags, shell_aliases
43 InteractiveShellApp, shell_flags, shell_aliases
44 )
44 )
45 from IPython.utils import io
45 from IPython.utils import io
46 from IPython.utils import py3compat
46 from IPython.utils import py3compat
47 from IPython.utils.frame import extract_module_locals
47 from IPython.utils.frame import extract_module_locals
48 from IPython.utils.jsonutil import json_clean
48 from IPython.utils.jsonutil import json_clean
49 from IPython.utils.traitlets import (
49 from IPython.utils.traitlets import (
50 Any, Instance, Float, Dict, CaselessStrEnum, List, Set, Integer, Unicode
50 Any, Instance, Float, Dict, CaselessStrEnum, List, Set, Integer, Unicode
51 )
51 )
52
52
53 from entry_point import base_launch_kernel
53 from entry_point import base_launch_kernel
54 from kernelapp import KernelApp, kernel_flags, kernel_aliases
54 from kernelapp import KernelApp, kernel_flags, kernel_aliases
55 from serialize import serialize_object, unpack_apply_message
55 from serialize import serialize_object, unpack_apply_message
56 from session import Session, Message
56 from session import Session, Message
57 from zmqshell import ZMQInteractiveShell
57 from zmqshell import ZMQInteractiveShell
58
58
59
59
60 #-----------------------------------------------------------------------------
60 #-----------------------------------------------------------------------------
61 # Main kernel class
61 # Main kernel class
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63
63
64 class Kernel(Configurable):
64 class Kernel(Configurable):
65
65
66 #---------------------------------------------------------------------------
66 #---------------------------------------------------------------------------
67 # Kernel interface
67 # Kernel interface
68 #---------------------------------------------------------------------------
68 #---------------------------------------------------------------------------
69
69
70 # attribute to override with a GUI
70 # attribute to override with a GUI
71 eventloop = Any(None)
71 eventloop = Any(None)
72 def _eventloop_changed(self, name, old, new):
72 def _eventloop_changed(self, name, old, new):
73 """schedule call to eventloop from IOLoop"""
73 """schedule call to eventloop from IOLoop"""
74 loop = ioloop.IOLoop.instance()
74 loop = ioloop.IOLoop.instance()
75 loop.add_timeout(time.time()+0.1, self.enter_eventloop)
75 loop.add_timeout(time.time()+0.1, self.enter_eventloop)
76
76
77 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
77 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
78 session = Instance(Session)
78 session = Instance(Session)
79 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
79 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
80 shell_streams = List()
80 shell_streams = List()
81 control_stream = Instance(ZMQStream)
81 control_stream = Instance(ZMQStream)
82 iopub_socket = Instance(zmq.Socket)
82 iopub_socket = Instance(zmq.Socket)
83 stdin_socket = Instance(zmq.Socket)
83 stdin_socket = Instance(zmq.Socket)
84 log = Instance(logging.Logger)
84 log = Instance(logging.Logger)
85
85
86 user_module = Any()
86 user_module = Any()
87 def _user_module_changed(self, name, old, new):
87 def _user_module_changed(self, name, old, new):
88 if self.shell is not None:
88 if self.shell is not None:
89 self.shell.user_module = new
89 self.shell.user_module = new
90
90
91 user_ns = Dict(default_value=None)
91 user_ns = Dict(default_value=None)
92 def _user_ns_changed(self, name, old, new):
92 def _user_ns_changed(self, name, old, new):
93 if self.shell is not None:
93 if self.shell is not None:
94 self.shell.user_ns = new
94 self.shell.user_ns = new
95 self.shell.init_user_ns()
95 self.shell.init_user_ns()
96
96
97 # identities:
97 # identities:
98 int_id = Integer(-1)
98 int_id = Integer(-1)
99 ident = Unicode()
99 ident = Unicode()
100
100
101 def _ident_default(self):
101 def _ident_default(self):
102 return unicode(uuid.uuid4())
102 return unicode(uuid.uuid4())
103
103
104
104
105 # Private interface
105 # Private interface
106
106
107 # Time to sleep after flushing the stdout/err buffers in each execute
107 # Time to sleep after flushing the stdout/err buffers in each execute
108 # cycle. While this introduces a hard limit on the minimal latency of the
108 # cycle. While this introduces a hard limit on the minimal latency of the
109 # execute cycle, it helps prevent output synchronization problems for
109 # execute cycle, it helps prevent output synchronization problems for
110 # clients.
110 # clients.
111 # Units are in seconds. The minimum zmq latency on local host is probably
111 # Units are in seconds. The minimum zmq latency on local host is probably
112 # ~150 microseconds, set this to 500us for now. We may need to increase it
112 # ~150 microseconds, set this to 500us for now. We may need to increase it
113 # a little if it's not enough after more interactive testing.
113 # a little if it's not enough after more interactive testing.
114 _execute_sleep = Float(0.0005, config=True)
114 _execute_sleep = Float(0.0005, config=True)
115
115
116 # Frequency of the kernel's event loop.
116 # Frequency of the kernel's event loop.
117 # Units are in seconds, kernel subclasses for GUI toolkits may need to
117 # Units are in seconds, kernel subclasses for GUI toolkits may need to
118 # adapt to milliseconds.
118 # adapt to milliseconds.
119 _poll_interval = Float(0.05, config=True)
119 _poll_interval = Float(0.05, config=True)
120
120
121 # If the shutdown was requested over the network, we leave here the
121 # If the shutdown was requested over the network, we leave here the
122 # necessary reply message so it can be sent by our registered atexit
122 # necessary reply message so it can be sent by our registered atexit
123 # handler. This ensures that the reply is only sent to clients truly at
123 # handler. This ensures that the reply is only sent to clients truly at
124 # the end of our shutdown process (which happens after the underlying
124 # the end of our shutdown process (which happens after the underlying
125 # IPython shell's own shutdown).
125 # IPython shell's own shutdown).
126 _shutdown_message = None
126 _shutdown_message = None
127
127
128 # This is a dict of port number that the kernel is listening on. It is set
128 # This is a dict of port number that the kernel is listening on. It is set
129 # by record_ports and used by connect_request.
129 # by record_ports and used by connect_request.
130 _recorded_ports = Dict()
130 _recorded_ports = Dict()
131
131
132 # set of aborted msg_ids
132 # set of aborted msg_ids
133 aborted = Set()
133 aborted = Set()
134
134
135
135
136 def __init__(self, **kwargs):
136 def __init__(self, **kwargs):
137 super(Kernel, self).__init__(**kwargs)
137 super(Kernel, self).__init__(**kwargs)
138
138
139 # Initialize the InteractiveShell subclass
139 # Initialize the InteractiveShell subclass
140 self.shell = ZMQInteractiveShell.instance(config=self.config,
140 self.shell = ZMQInteractiveShell.instance(config=self.config,
141 profile_dir = self.profile_dir,
141 profile_dir = self.profile_dir,
142 user_module = self.user_module,
142 user_module = self.user_module,
143 user_ns = self.user_ns,
143 user_ns = self.user_ns,
144 )
144 )
145 self.shell.displayhook.session = self.session
145 self.shell.displayhook.session = self.session
146 self.shell.displayhook.pub_socket = self.iopub_socket
146 self.shell.displayhook.pub_socket = self.iopub_socket
147 self.shell.displayhook.topic = self._topic('pyout')
147 self.shell.displayhook.topic = self._topic('pyout')
148 self.shell.display_pub.session = self.session
148 self.shell.display_pub.session = self.session
149 self.shell.display_pub.pub_socket = self.iopub_socket
149 self.shell.display_pub.pub_socket = self.iopub_socket
150 self.shell.data_pub.session = self.session
150 self.shell.data_pub.session = self.session
151 self.shell.data_pub.pub_socket = self.iopub_socket
151 self.shell.data_pub.pub_socket = self.iopub_socket
152
152
153 # TMP - hack while developing
153 # TMP - hack while developing
154 self.shell._reply_content = None
154 self.shell._reply_content = None
155
155
156 # Build dict of handlers for message types
156 # Build dict of handlers for message types
157 msg_types = [ 'execute_request', 'complete_request',
157 msg_types = [ 'execute_request', 'complete_request',
158 'object_info_request', 'history_request',
158 'object_info_request', 'history_request',
159 'connect_request', 'shutdown_request',
159 'connect_request', 'shutdown_request',
160 'apply_request',
160 'apply_request',
161 ]
161 ]
162 self.shell_handlers = {}
162 self.shell_handlers = {}
163 for msg_type in msg_types:
163 for msg_type in msg_types:
164 self.shell_handlers[msg_type] = getattr(self, msg_type)
164 self.shell_handlers[msg_type] = getattr(self, msg_type)
165
165
166 control_msg_types = msg_types + [ 'clear_request', 'abort_request' ]
166 control_msg_types = msg_types + [ 'clear_request', 'abort_request' ]
167 self.control_handlers = {}
167 self.control_handlers = {}
168 for msg_type in control_msg_types:
168 for msg_type in control_msg_types:
169 self.control_handlers[msg_type] = getattr(self, msg_type)
169 self.control_handlers[msg_type] = getattr(self, msg_type)
170
170
171 def dispatch_control(self, msg):
171 def dispatch_control(self, msg):
172 """dispatch control requests"""
172 """dispatch control requests"""
173 idents,msg = self.session.feed_identities(msg, copy=False)
173 idents,msg = self.session.feed_identities(msg, copy=False)
174 try:
174 try:
175 msg = self.session.unserialize(msg, content=True, copy=False)
175 msg = self.session.unserialize(msg, content=True, copy=False)
176 except:
176 except:
177 self.log.error("Invalid Control Message", exc_info=True)
177 self.log.error("Invalid Control Message", exc_info=True)
178 return
178 return
179
179
180 self.log.debug("Control received: %s", msg)
180 self.log.debug("Control received: %s", msg)
181
181
182 header = msg['header']
182 header = msg['header']
183 msg_id = header['msg_id']
183 msg_id = header['msg_id']
184 msg_type = header['msg_type']
184 msg_type = header['msg_type']
185
185
186 handler = self.control_handlers.get(msg_type, None)
186 handler = self.control_handlers.get(msg_type, None)
187 if handler is None:
187 if handler is None:
188 self.log.error("UNKNOWN CONTROL MESSAGE TYPE: %r", msg_type)
188 self.log.error("UNKNOWN CONTROL MESSAGE TYPE: %r", msg_type)
189 else:
189 else:
190 try:
190 try:
191 handler(self.control_stream, idents, msg)
191 handler(self.control_stream, idents, msg)
192 except Exception:
192 except Exception:
193 self.log.error("Exception in control handler:", exc_info=True)
193 self.log.error("Exception in control handler:", exc_info=True)
194
194
195 def dispatch_shell(self, stream, msg):
195 def dispatch_shell(self, stream, msg):
196 """dispatch shell requests"""
196 """dispatch shell requests"""
197 # flush control requests first
197 # flush control requests first
198 if self.control_stream:
198 if self.control_stream:
199 self.control_stream.flush()
199 self.control_stream.flush()
200
200
201 idents,msg = self.session.feed_identities(msg, copy=False)
201 idents,msg = self.session.feed_identities(msg, copy=False)
202 try:
202 try:
203 msg = self.session.unserialize(msg, content=True, copy=False)
203 msg = self.session.unserialize(msg, content=True, copy=False)
204 except:
204 except:
205 self.log.error("Invalid Message", exc_info=True)
205 self.log.error("Invalid Message", exc_info=True)
206 return
206 return
207
207
208 header = msg['header']
208 header = msg['header']
209 msg_id = header['msg_id']
209 msg_id = header['msg_id']
210 msg_type = msg['header']['msg_type']
210 msg_type = msg['header']['msg_type']
211
211
212 # Print some info about this message and leave a '--->' marker, so it's
212 # Print some info about this message and leave a '--->' marker, so it's
213 # easier to trace visually the message chain when debugging. Each
213 # easier to trace visually the message chain when debugging. Each
214 # handler prints its message at the end.
214 # handler prints its message at the end.
215 self.log.debug('\n*** MESSAGE TYPE:%s***', msg_type)
215 self.log.debug('\n*** MESSAGE TYPE:%s***', msg_type)
216 self.log.debug(' Content: %s\n --->\n ', msg['content'])
216 self.log.debug(' Content: %s\n --->\n ', msg['content'])
217
217
218 if msg_id in self.aborted:
218 if msg_id in self.aborted:
219 self.aborted.remove(msg_id)
219 self.aborted.remove(msg_id)
220 # is it safe to assume a msg_id will not be resubmitted?
220 # is it safe to assume a msg_id will not be resubmitted?
221 reply_type = msg_type.split('_')[0] + '_reply'
221 reply_type = msg_type.split('_')[0] + '_reply'
222 status = {'status' : 'aborted'}
222 status = {'status' : 'aborted'}
223 md = {'engine' : self.ident}
223 md = {'engine' : self.ident}
224 md.update(status)
224 md.update(status)
225 reply_msg = self.session.send(stream, reply_type, metadata=md,
225 reply_msg = self.session.send(stream, reply_type, metadata=md,
226 content=status, parent=msg, ident=idents)
226 content=status, parent=msg, ident=idents)
227 return
227 return
228
228
229 handler = self.shell_handlers.get(msg_type, None)
229 handler = self.shell_handlers.get(msg_type, None)
230 if handler is None:
230 if handler is None:
231 self.log.error("UNKNOWN MESSAGE TYPE: %r", msg_type)
231 self.log.error("UNKNOWN MESSAGE TYPE: %r", msg_type)
232 else:
232 else:
233 # ensure default_int_handler during handler call
233 # ensure default_int_handler during handler call
234 sig = signal(SIGINT, default_int_handler)
234 sig = signal(SIGINT, default_int_handler)
235 try:
235 try:
236 handler(stream, idents, msg)
236 handler(stream, idents, msg)
237 except Exception:
237 except Exception:
238 self.log.error("Exception in message handler:", exc_info=True)
238 self.log.error("Exception in message handler:", exc_info=True)
239 finally:
239 finally:
240 signal(SIGINT, sig)
240 signal(SIGINT, sig)
241
241
242 def enter_eventloop(self):
242 def enter_eventloop(self):
243 """enter eventloop"""
243 """enter eventloop"""
244 self.log.info("entering eventloop")
244 self.log.info("entering eventloop")
245 # restore default_int_handler
245 # restore default_int_handler
246 signal(SIGINT, default_int_handler)
246 signal(SIGINT, default_int_handler)
247 while self.eventloop is not None:
247 while self.eventloop is not None:
248 try:
248 try:
249 self.eventloop(self)
249 self.eventloop(self)
250 except KeyboardInterrupt:
250 except KeyboardInterrupt:
251 # Ctrl-C shouldn't crash the kernel
251 # Ctrl-C shouldn't crash the kernel
252 self.log.error("KeyboardInterrupt caught in kernel")
252 self.log.error("KeyboardInterrupt caught in kernel")
253 continue
253 continue
254 else:
254 else:
255 # eventloop exited cleanly, this means we should stop (right?)
255 # eventloop exited cleanly, this means we should stop (right?)
256 self.eventloop = None
256 self.eventloop = None
257 break
257 break
258 self.log.info("exiting eventloop")
258 self.log.info("exiting eventloop")
259
259
260 def start(self):
260 def start(self):
261 """register dispatchers for streams"""
261 """register dispatchers for streams"""
262 self.shell.exit_now = False
262 self.shell.exit_now = False
263 if self.control_stream:
263 if self.control_stream:
264 self.control_stream.on_recv(self.dispatch_control, copy=False)
264 self.control_stream.on_recv(self.dispatch_control, copy=False)
265
265
266 def make_dispatcher(stream):
266 def make_dispatcher(stream):
267 def dispatcher(msg):
267 def dispatcher(msg):
268 return self.dispatch_shell(stream, msg)
268 return self.dispatch_shell(stream, msg)
269 return dispatcher
269 return dispatcher
270
270
271 for s in self.shell_streams:
271 for s in self.shell_streams:
272 s.on_recv(make_dispatcher(s), copy=False)
272 s.on_recv(make_dispatcher(s), copy=False)
273
273
274 def do_one_iteration(self):
274 def do_one_iteration(self):
275 """step eventloop just once"""
275 """step eventloop just once"""
276 if self.control_stream:
276 if self.control_stream:
277 self.control_stream.flush()
277 self.control_stream.flush()
278 for stream in self.shell_streams:
278 for stream in self.shell_streams:
279 # handle at most one request per iteration
279 # handle at most one request per iteration
280 stream.flush(zmq.POLLIN, 1)
280 stream.flush(zmq.POLLIN, 1)
281 stream.flush(zmq.POLLOUT)
281 stream.flush(zmq.POLLOUT)
282
282
283
283
284 def record_ports(self, ports):
284 def record_ports(self, ports):
285 """Record the ports that this kernel is using.
285 """Record the ports that this kernel is using.
286
286
287 The creator of the Kernel instance must call this methods if they
287 The creator of the Kernel instance must call this methods if they
288 want the :meth:`connect_request` method to return the port numbers.
288 want the :meth:`connect_request` method to return the port numbers.
289 """
289 """
290 self._recorded_ports = ports
290 self._recorded_ports = ports
291
291
292 #---------------------------------------------------------------------------
292 #---------------------------------------------------------------------------
293 # Kernel request handlers
293 # Kernel request handlers
294 #---------------------------------------------------------------------------
294 #---------------------------------------------------------------------------
295
295
296 def _make_metadata(self, other=None):
296 def _make_metadata(self, other=None):
297 """init metadata dict, for execute/apply_reply"""
297 """init metadata dict, for execute/apply_reply"""
298 new_md = {
298 new_md = {
299 'dependencies_met' : True,
299 'dependencies_met' : True,
300 'engine' : self.ident,
300 'engine' : self.ident,
301 'started': datetime.now(),
301 'started': datetime.now(),
302 }
302 }
303 if other:
303 if other:
304 new_md.update(other)
304 new_md.update(other)
305 return new_md
305 return new_md
306
306
307 def _publish_pyin(self, code, parent, execution_count):
307 def _publish_pyin(self, code, parent, execution_count):
308 """Publish the code request on the pyin stream."""
308 """Publish the code request on the pyin stream."""
309
309
310 self.session.send(self.iopub_socket, u'pyin',
310 self.session.send(self.iopub_socket, u'pyin',
311 {u'code':code, u'execution_count': execution_count},
311 {u'code':code, u'execution_count': execution_count},
312 parent=parent, ident=self._topic('pyin')
312 parent=parent, ident=self._topic('pyin')
313 )
313 )
314
314
315 def _publish_status(self, status, parent=None):
315 def _publish_status(self, status, parent=None):
316 """send status (busy/idle) on IOPub"""
316 """send status (busy/idle) on IOPub"""
317 self.session.send(self.iopub_socket,
317 self.session.send(self.iopub_socket,
318 u'status',
318 u'status',
319 {u'execution_state': status},
319 {u'execution_state': status},
320 parent=parent,
320 parent=parent,
321 ident=self._topic('status'),
321 ident=self._topic('status'),
322 )
322 )
323
323
324
324
325 def execute_request(self, stream, ident, parent):
325 def execute_request(self, stream, ident, parent):
326 """handle an execute_request"""
326 """handle an execute_request"""
327
327
328 self._publish_status(u'busy', parent)
328 self._publish_status(u'busy', parent)
329
329
330 try:
330 try:
331 content = parent[u'content']
331 content = parent[u'content']
332 code = content[u'code']
332 code = content[u'code']
333 silent = content[u'silent']
333 silent = content[u'silent']
334 store_history = content.get(u'store_history', not silent)
334 store_history = content.get(u'store_history', not silent)
335 except:
335 except:
336 self.log.error("Got bad msg: ")
336 self.log.error("Got bad msg: ")
337 self.log.error("%s", parent)
337 self.log.error("%s", parent)
338 return
338 return
339
339
340 md = self._make_metadata(parent['metadata'])
340 md = self._make_metadata(parent['metadata'])
341
341
342 shell = self.shell # we'll need this a lot here
342 shell = self.shell # we'll need this a lot here
343
343
344 # Replace raw_input. Note that is not sufficient to replace
344 # Replace raw_input. Note that is not sufficient to replace
345 # raw_input in the user namespace.
345 # raw_input in the user namespace.
346 if content.get('allow_stdin', False):
346 if content.get('allow_stdin', False):
347 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
347 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
348 else:
348 else:
349 raw_input = lambda prompt='' : self._no_raw_input()
349 raw_input = lambda prompt='' : self._no_raw_input()
350
350
351 if py3compat.PY3:
351 if py3compat.PY3:
352 __builtin__.input = raw_input
352 __builtin__.input = raw_input
353 else:
353 else:
354 __builtin__.raw_input = raw_input
354 __builtin__.raw_input = raw_input
355
355
356 # Set the parent message of the display hook and out streams.
356 # Set the parent message of the display hook and out streams.
357 shell.displayhook.set_parent(parent)
357 shell.displayhook.set_parent(parent)
358 shell.display_pub.set_parent(parent)
358 shell.display_pub.set_parent(parent)
359 shell.data_pub.set_parent(parent)
359 shell.data_pub.set_parent(parent)
360 sys.stdout.set_parent(parent)
360 sys.stdout.set_parent(parent)
361 sys.stderr.set_parent(parent)
361 sys.stderr.set_parent(parent)
362
362
363 # Re-broadcast our input for the benefit of listening clients, and
363 # Re-broadcast our input for the benefit of listening clients, and
364 # start computing output
364 # start computing output
365 if not silent:
365 if not silent:
366 self._publish_pyin(code, parent, shell.execution_count)
366 self._publish_pyin(code, parent, shell.execution_count)
367
367
368 reply_content = {}
368 reply_content = {}
369 try:
369 try:
370 # FIXME: the shell calls the exception handler itself.
370 # FIXME: the shell calls the exception handler itself.
371 shell.run_cell(code, store_history=store_history, silent=silent)
371 shell.run_cell(code, store_history=store_history, silent=silent)
372 except:
372 except:
373 status = u'error'
373 status = u'error'
374 # FIXME: this code right now isn't being used yet by default,
374 # FIXME: this code right now isn't being used yet by default,
375 # because the run_cell() call above directly fires off exception
375 # because the run_cell() call above directly fires off exception
376 # reporting. This code, therefore, is only active in the scenario
376 # reporting. This code, therefore, is only active in the scenario
377 # where runlines itself has an unhandled exception. We need to
377 # where runlines itself has an unhandled exception. We need to
378 # uniformize this, for all exception construction to come from a
378 # uniformize this, for all exception construction to come from a
379 # single location in the codbase.
379 # single location in the codbase.
380 etype, evalue, tb = sys.exc_info()
380 etype, evalue, tb = sys.exc_info()
381 tb_list = traceback.format_exception(etype, evalue, tb)
381 tb_list = traceback.format_exception(etype, evalue, tb)
382 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
382 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
383 else:
383 else:
384 status = u'ok'
384 status = u'ok'
385
385
386 reply_content[u'status'] = status
386 reply_content[u'status'] = status
387
387
388 # Return the execution counter so clients can display prompts
388 # Return the execution counter so clients can display prompts
389 reply_content['execution_count'] = shell.execution_count - 1
389 reply_content['execution_count'] = shell.execution_count - 1
390
390
391 # FIXME - fish exception info out of shell, possibly left there by
391 # FIXME - fish exception info out of shell, possibly left there by
392 # runlines. We'll need to clean up this logic later.
392 # runlines. We'll need to clean up this logic later.
393 if shell._reply_content is not None:
393 if shell._reply_content is not None:
394 reply_content.update(shell._reply_content)
394 reply_content.update(shell._reply_content)
395 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='execute')
395 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='execute')
396 reply_content['engine_info'] = e_info
396 reply_content['engine_info'] = e_info
397 # reset after use
397 # reset after use
398 shell._reply_content = None
398 shell._reply_content = None
399
399
400 # At this point, we can tell whether the main code execution succeeded
400 # At this point, we can tell whether the main code execution succeeded
401 # or not. If it did, we proceed to evaluate user_variables/expressions
401 # or not. If it did, we proceed to evaluate user_variables/expressions
402 if reply_content['status'] == 'ok':
402 if reply_content['status'] == 'ok':
403 reply_content[u'user_variables'] = \
403 reply_content[u'user_variables'] = \
404 shell.user_variables(content.get(u'user_variables', []))
404 shell.user_variables(content.get(u'user_variables', []))
405 reply_content[u'user_expressions'] = \
405 reply_content[u'user_expressions'] = \
406 shell.user_expressions(content.get(u'user_expressions', {}))
406 shell.user_expressions(content.get(u'user_expressions', {}))
407 else:
407 else:
408 # If there was an error, don't even try to compute variables or
408 # If there was an error, don't even try to compute variables or
409 # expressions
409 # expressions
410 reply_content[u'user_variables'] = {}
410 reply_content[u'user_variables'] = {}
411 reply_content[u'user_expressions'] = {}
411 reply_content[u'user_expressions'] = {}
412
412
413 # Payloads should be retrieved regardless of outcome, so we can both
413 # Payloads should be retrieved regardless of outcome, so we can both
414 # recover partial output (that could have been generated early in a
414 # recover partial output (that could have been generated early in a
415 # block, before an error) and clear the payload system always.
415 # block, before an error) and clear the payload system always.
416 reply_content[u'payload'] = shell.payload_manager.read_payload()
416 reply_content[u'payload'] = shell.payload_manager.read_payload()
417 # Be agressive about clearing the payload because we don't want
417 # Be agressive about clearing the payload because we don't want
418 # it to sit in memory until the next execute_request comes in.
418 # it to sit in memory until the next execute_request comes in.
419 shell.payload_manager.clear_payload()
419 shell.payload_manager.clear_payload()
420
420
421 # Flush output before sending the reply.
421 # Flush output before sending the reply.
422 sys.stdout.flush()
422 sys.stdout.flush()
423 sys.stderr.flush()
423 sys.stderr.flush()
424 # FIXME: on rare occasions, the flush doesn't seem to make it to the
424 # FIXME: on rare occasions, the flush doesn't seem to make it to the
425 # clients... This seems to mitigate the problem, but we definitely need
425 # clients... This seems to mitigate the problem, but we definitely need
426 # to better understand what's going on.
426 # to better understand what's going on.
427 if self._execute_sleep:
427 if self._execute_sleep:
428 time.sleep(self._execute_sleep)
428 time.sleep(self._execute_sleep)
429
429
430 # Send the reply.
430 # Send the reply.
431 reply_content = json_clean(reply_content)
431 reply_content = json_clean(reply_content)
432
432
433 md['status'] = reply_content['status']
433 md['status'] = reply_content['status']
434 if reply_content['status'] == 'error' and \
434 if reply_content['status'] == 'error' and \
435 reply_content['ename'] == 'UnmetDependency':
435 reply_content['ename'] == 'UnmetDependency':
436 md['dependencies_met'] = False
436 md['dependencies_met'] = False
437
437
438 reply_msg = self.session.send(stream, u'execute_reply',
438 reply_msg = self.session.send(stream, u'execute_reply',
439 reply_content, parent, metadata=md,
439 reply_content, parent, metadata=md,
440 ident=ident)
440 ident=ident)
441
441
442 self.log.debug("%s", reply_msg)
442 self.log.debug("%s", reply_msg)
443
443
444 if not silent and reply_msg['content']['status'] == u'error':
444 if not silent and reply_msg['content']['status'] == u'error':
445 self._abort_queues()
445 self._abort_queues()
446
446
447 self._publish_status(u'idle', parent)
447 self._publish_status(u'idle', parent)
448
448
449 def complete_request(self, stream, ident, parent):
449 def complete_request(self, stream, ident, parent):
450 txt, matches = self._complete(parent)
450 txt, matches = self._complete(parent)
451 matches = {'matches' : matches,
451 matches = {'matches' : matches,
452 'matched_text' : txt,
452 'matched_text' : txt,
453 'status' : 'ok'}
453 'status' : 'ok'}
454 matches = json_clean(matches)
454 matches = json_clean(matches)
455 completion_msg = self.session.send(stream, 'complete_reply',
455 completion_msg = self.session.send(stream, 'complete_reply',
456 matches, parent, ident)
456 matches, parent, ident)
457 self.log.debug("%s", completion_msg)
457 self.log.debug("%s", completion_msg)
458
458
459 def object_info_request(self, stream, ident, parent):
459 def object_info_request(self, stream, ident, parent):
460 content = parent['content']
460 content = parent['content']
461 object_info = self.shell.object_inspect(content['oname'],
461 object_info = self.shell.object_inspect(content['oname'],
462 detail_level = content.get('detail_level', 0)
462 detail_level = content.get('detail_level', 0)
463 )
463 )
464 # Before we send this object over, we scrub it for JSON usage
464 # Before we send this object over, we scrub it for JSON usage
465 oinfo = json_clean(object_info)
465 oinfo = json_clean(object_info)
466 msg = self.session.send(stream, 'object_info_reply',
466 msg = self.session.send(stream, 'object_info_reply',
467 oinfo, parent, ident)
467 oinfo, parent, ident)
468 self.log.debug("%s", msg)
468 self.log.debug("%s", msg)
469
469
470 def history_request(self, stream, ident, parent):
470 def history_request(self, stream, ident, parent):
471 # We need to pull these out, as passing **kwargs doesn't work with
471 # We need to pull these out, as passing **kwargs doesn't work with
472 # unicode keys before Python 2.6.5.
472 # unicode keys before Python 2.6.5.
473 hist_access_type = parent['content']['hist_access_type']
473 hist_access_type = parent['content']['hist_access_type']
474 raw = parent['content']['raw']
474 raw = parent['content']['raw']
475 output = parent['content']['output']
475 output = parent['content']['output']
476 if hist_access_type == 'tail':
476 if hist_access_type == 'tail':
477 n = parent['content']['n']
477 n = parent['content']['n']
478 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
478 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
479 include_latest=True)
479 include_latest=True)
480
480
481 elif hist_access_type == 'range':
481 elif hist_access_type == 'range':
482 session = parent['content']['session']
482 session = parent['content']['session']
483 start = parent['content']['start']
483 start = parent['content']['start']
484 stop = parent['content']['stop']
484 stop = parent['content']['stop']
485 hist = self.shell.history_manager.get_range(session, start, stop,
485 hist = self.shell.history_manager.get_range(session, start, stop,
486 raw=raw, output=output)
486 raw=raw, output=output)
487
487
488 elif hist_access_type == 'search':
488 elif hist_access_type == 'search':
489 n = parent['content']['n']
489 pattern = parent['content']['pattern']
490 pattern = parent['content']['pattern']
490 hist = self.shell.history_manager.search(pattern, raw=raw,
491 hist = self.shell.history_manager.search(pattern, raw=raw,
491 output=output)
492 output=output, n=n)
492
493
493 else:
494 else:
494 hist = []
495 hist = []
495 hist = list(hist)
496 hist = list(hist)
496 content = {'history' : hist}
497 content = {'history' : hist}
497 content = json_clean(content)
498 content = json_clean(content)
498 msg = self.session.send(stream, 'history_reply',
499 msg = self.session.send(stream, 'history_reply',
499 content, parent, ident)
500 content, parent, ident)
500 self.log.debug("Sending history reply with %i entries", len(hist))
501 self.log.debug("Sending history reply with %i entries", len(hist))
501
502
502 def connect_request(self, stream, ident, parent):
503 def connect_request(self, stream, ident, parent):
503 if self._recorded_ports is not None:
504 if self._recorded_ports is not None:
504 content = self._recorded_ports.copy()
505 content = self._recorded_ports.copy()
505 else:
506 else:
506 content = {}
507 content = {}
507 msg = self.session.send(stream, 'connect_reply',
508 msg = self.session.send(stream, 'connect_reply',
508 content, parent, ident)
509 content, parent, ident)
509 self.log.debug("%s", msg)
510 self.log.debug("%s", msg)
510
511
511 def shutdown_request(self, stream, ident, parent):
512 def shutdown_request(self, stream, ident, parent):
512 self.shell.exit_now = True
513 self.shell.exit_now = True
513 content = dict(status='ok')
514 content = dict(status='ok')
514 content.update(parent['content'])
515 content.update(parent['content'])
515 self.session.send(stream, u'shutdown_reply', content, parent, ident=ident)
516 self.session.send(stream, u'shutdown_reply', content, parent, ident=ident)
516 # same content, but different msg_id for broadcasting on IOPub
517 # same content, but different msg_id for broadcasting on IOPub
517 self._shutdown_message = self.session.msg(u'shutdown_reply',
518 self._shutdown_message = self.session.msg(u'shutdown_reply',
518 content, parent
519 content, parent
519 )
520 )
520
521
521 self._at_shutdown()
522 self._at_shutdown()
522 # call sys.exit after a short delay
523 # call sys.exit after a short delay
523 loop = ioloop.IOLoop.instance()
524 loop = ioloop.IOLoop.instance()
524 loop.add_timeout(time.time()+0.1, loop.stop)
525 loop.add_timeout(time.time()+0.1, loop.stop)
525
526
526 #---------------------------------------------------------------------------
527 #---------------------------------------------------------------------------
527 # Engine methods
528 # Engine methods
528 #---------------------------------------------------------------------------
529 #---------------------------------------------------------------------------
529
530
530 def apply_request(self, stream, ident, parent):
531 def apply_request(self, stream, ident, parent):
531 try:
532 try:
532 content = parent[u'content']
533 content = parent[u'content']
533 bufs = parent[u'buffers']
534 bufs = parent[u'buffers']
534 msg_id = parent['header']['msg_id']
535 msg_id = parent['header']['msg_id']
535 except:
536 except:
536 self.log.error("Got bad msg: %s", parent, exc_info=True)
537 self.log.error("Got bad msg: %s", parent, exc_info=True)
537 return
538 return
538
539
539 self._publish_status(u'busy', parent)
540 self._publish_status(u'busy', parent)
540
541
541 # Set the parent message of the display hook and out streams.
542 # Set the parent message of the display hook and out streams.
542 shell = self.shell
543 shell = self.shell
543 shell.displayhook.set_parent(parent)
544 shell.displayhook.set_parent(parent)
544 shell.display_pub.set_parent(parent)
545 shell.display_pub.set_parent(parent)
545 shell.data_pub.set_parent(parent)
546 shell.data_pub.set_parent(parent)
546 sys.stdout.set_parent(parent)
547 sys.stdout.set_parent(parent)
547 sys.stderr.set_parent(parent)
548 sys.stderr.set_parent(parent)
548
549
549 # pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent)
550 # pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent)
550 # self.iopub_socket.send(pyin_msg)
551 # self.iopub_socket.send(pyin_msg)
551 # self.session.send(self.iopub_socket, u'pyin', {u'code':code},parent=parent)
552 # self.session.send(self.iopub_socket, u'pyin', {u'code':code},parent=parent)
552 md = self._make_metadata(parent['metadata'])
553 md = self._make_metadata(parent['metadata'])
553 try:
554 try:
554 working = shell.user_ns
555 working = shell.user_ns
555
556
556 prefix = "_"+str(msg_id).replace("-","")+"_"
557 prefix = "_"+str(msg_id).replace("-","")+"_"
557
558
558 f,args,kwargs = unpack_apply_message(bufs, working, copy=False)
559 f,args,kwargs = unpack_apply_message(bufs, working, copy=False)
559
560
560 fname = getattr(f, '__name__', 'f')
561 fname = getattr(f, '__name__', 'f')
561
562
562 fname = prefix+"f"
563 fname = prefix+"f"
563 argname = prefix+"args"
564 argname = prefix+"args"
564 kwargname = prefix+"kwargs"
565 kwargname = prefix+"kwargs"
565 resultname = prefix+"result"
566 resultname = prefix+"result"
566
567
567 ns = { fname : f, argname : args, kwargname : kwargs , resultname : None }
568 ns = { fname : f, argname : args, kwargname : kwargs , resultname : None }
568 # print ns
569 # print ns
569 working.update(ns)
570 working.update(ns)
570 code = "%s = %s(*%s,**%s)" % (resultname, fname, argname, kwargname)
571 code = "%s = %s(*%s,**%s)" % (resultname, fname, argname, kwargname)
571 try:
572 try:
572 exec code in shell.user_global_ns, shell.user_ns
573 exec code in shell.user_global_ns, shell.user_ns
573 result = working.get(resultname)
574 result = working.get(resultname)
574 finally:
575 finally:
575 for key in ns.iterkeys():
576 for key in ns.iterkeys():
576 working.pop(key)
577 working.pop(key)
577
578
578 result_buf = serialize_object(result,
579 result_buf = serialize_object(result,
579 buffer_threshold=self.session.buffer_threshold,
580 buffer_threshold=self.session.buffer_threshold,
580 item_threshold=self.session.item_threshold,
581 item_threshold=self.session.item_threshold,
581 )
582 )
582
583
583 except:
584 except:
584 # invoke IPython traceback formatting
585 # invoke IPython traceback formatting
585 shell.showtraceback()
586 shell.showtraceback()
586 # FIXME - fish exception info out of shell, possibly left there by
587 # FIXME - fish exception info out of shell, possibly left there by
587 # run_code. We'll need to clean up this logic later.
588 # run_code. We'll need to clean up this logic later.
588 reply_content = {}
589 reply_content = {}
589 if shell._reply_content is not None:
590 if shell._reply_content is not None:
590 reply_content.update(shell._reply_content)
591 reply_content.update(shell._reply_content)
591 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='apply')
592 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='apply')
592 reply_content['engine_info'] = e_info
593 reply_content['engine_info'] = e_info
593 # reset after use
594 # reset after use
594 shell._reply_content = None
595 shell._reply_content = None
595
596
596 self.session.send(self.iopub_socket, u'pyerr', reply_content, parent=parent,
597 self.session.send(self.iopub_socket, u'pyerr', reply_content, parent=parent,
597 ident=self._topic('pyerr'))
598 ident=self._topic('pyerr'))
598 result_buf = []
599 result_buf = []
599
600
600 if reply_content['ename'] == 'UnmetDependency':
601 if reply_content['ename'] == 'UnmetDependency':
601 md['dependencies_met'] = False
602 md['dependencies_met'] = False
602 else:
603 else:
603 reply_content = {'status' : 'ok'}
604 reply_content = {'status' : 'ok'}
604
605
605 # put 'ok'/'error' status in header, for scheduler introspection:
606 # put 'ok'/'error' status in header, for scheduler introspection:
606 md['status'] = reply_content['status']
607 md['status'] = reply_content['status']
607
608
608 # flush i/o
609 # flush i/o
609 sys.stdout.flush()
610 sys.stdout.flush()
610 sys.stderr.flush()
611 sys.stderr.flush()
611
612
612 reply_msg = self.session.send(stream, u'apply_reply', reply_content,
613 reply_msg = self.session.send(stream, u'apply_reply', reply_content,
613 parent=parent, ident=ident,buffers=result_buf, metadata=md)
614 parent=parent, ident=ident,buffers=result_buf, metadata=md)
614
615
615 self._publish_status(u'idle', parent)
616 self._publish_status(u'idle', parent)
616
617
617 #---------------------------------------------------------------------------
618 #---------------------------------------------------------------------------
618 # Control messages
619 # Control messages
619 #---------------------------------------------------------------------------
620 #---------------------------------------------------------------------------
620
621
621 def abort_request(self, stream, ident, parent):
622 def abort_request(self, stream, ident, parent):
622 """abort a specifig msg by id"""
623 """abort a specifig msg by id"""
623 msg_ids = parent['content'].get('msg_ids', None)
624 msg_ids = parent['content'].get('msg_ids', None)
624 if isinstance(msg_ids, basestring):
625 if isinstance(msg_ids, basestring):
625 msg_ids = [msg_ids]
626 msg_ids = [msg_ids]
626 if not msg_ids:
627 if not msg_ids:
627 self.abort_queues()
628 self.abort_queues()
628 for mid in msg_ids:
629 for mid in msg_ids:
629 self.aborted.add(str(mid))
630 self.aborted.add(str(mid))
630
631
631 content = dict(status='ok')
632 content = dict(status='ok')
632 reply_msg = self.session.send(stream, 'abort_reply', content=content,
633 reply_msg = self.session.send(stream, 'abort_reply', content=content,
633 parent=parent, ident=ident)
634 parent=parent, ident=ident)
634 self.log.debug("%s", reply_msg)
635 self.log.debug("%s", reply_msg)
635
636
636 def clear_request(self, stream, idents, parent):
637 def clear_request(self, stream, idents, parent):
637 """Clear our namespace."""
638 """Clear our namespace."""
638 self.shell.reset(False)
639 self.shell.reset(False)
639 msg = self.session.send(stream, 'clear_reply', ident=idents, parent=parent,
640 msg = self.session.send(stream, 'clear_reply', ident=idents, parent=parent,
640 content = dict(status='ok'))
641 content = dict(status='ok'))
641
642
642
643
643 #---------------------------------------------------------------------------
644 #---------------------------------------------------------------------------
644 # Protected interface
645 # Protected interface
645 #---------------------------------------------------------------------------
646 #---------------------------------------------------------------------------
646
647
647
648
648 def _wrap_exception(self, method=None):
649 def _wrap_exception(self, method=None):
649 # import here, because _wrap_exception is only used in parallel,
650 # import here, because _wrap_exception is only used in parallel,
650 # and parallel has higher min pyzmq version
651 # and parallel has higher min pyzmq version
651 from IPython.parallel.error import wrap_exception
652 from IPython.parallel.error import wrap_exception
652 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method=method)
653 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method=method)
653 content = wrap_exception(e_info)
654 content = wrap_exception(e_info)
654 return content
655 return content
655
656
656 def _topic(self, topic):
657 def _topic(self, topic):
657 """prefixed topic for IOPub messages"""
658 """prefixed topic for IOPub messages"""
658 if self.int_id >= 0:
659 if self.int_id >= 0:
659 base = "engine.%i" % self.int_id
660 base = "engine.%i" % self.int_id
660 else:
661 else:
661 base = "kernel.%s" % self.ident
662 base = "kernel.%s" % self.ident
662
663
663 return py3compat.cast_bytes("%s.%s" % (base, topic))
664 return py3compat.cast_bytes("%s.%s" % (base, topic))
664
665
665 def _abort_queues(self):
666 def _abort_queues(self):
666 for stream in self.shell_streams:
667 for stream in self.shell_streams:
667 if stream:
668 if stream:
668 self._abort_queue(stream)
669 self._abort_queue(stream)
669
670
670 def _abort_queue(self, stream):
671 def _abort_queue(self, stream):
671 poller = zmq.Poller()
672 poller = zmq.Poller()
672 poller.register(stream.socket, zmq.POLLIN)
673 poller.register(stream.socket, zmq.POLLIN)
673 while True:
674 while True:
674 idents,msg = self.session.recv(stream, zmq.NOBLOCK, content=True)
675 idents,msg = self.session.recv(stream, zmq.NOBLOCK, content=True)
675 if msg is None:
676 if msg is None:
676 return
677 return
677
678
678 self.log.info("Aborting:")
679 self.log.info("Aborting:")
679 self.log.info("%s", msg)
680 self.log.info("%s", msg)
680 msg_type = msg['header']['msg_type']
681 msg_type = msg['header']['msg_type']
681 reply_type = msg_type.split('_')[0] + '_reply'
682 reply_type = msg_type.split('_')[0] + '_reply'
682
683
683 status = {'status' : 'aborted'}
684 status = {'status' : 'aborted'}
684 md = {'engine' : self.ident}
685 md = {'engine' : self.ident}
685 md.update(status)
686 md.update(status)
686 reply_msg = self.session.send(stream, reply_type, metadata=md,
687 reply_msg = self.session.send(stream, reply_type, metadata=md,
687 content=status, parent=msg, ident=idents)
688 content=status, parent=msg, ident=idents)
688 self.log.debug("%s", reply_msg)
689 self.log.debug("%s", reply_msg)
689 # We need to wait a bit for requests to come in. This can probably
690 # We need to wait a bit for requests to come in. This can probably
690 # be set shorter for true asynchronous clients.
691 # be set shorter for true asynchronous clients.
691 poller.poll(50)
692 poller.poll(50)
692
693
693
694
694 def _no_raw_input(self):
695 def _no_raw_input(self):
695 """Raise StdinNotImplentedError if active frontend doesn't support
696 """Raise StdinNotImplentedError if active frontend doesn't support
696 stdin."""
697 stdin."""
697 raise StdinNotImplementedError("raw_input was called, but this "
698 raise StdinNotImplementedError("raw_input was called, but this "
698 "frontend does not support stdin.")
699 "frontend does not support stdin.")
699
700
700 def _raw_input(self, prompt, ident, parent):
701 def _raw_input(self, prompt, ident, parent):
701 # Flush output before making the request.
702 # Flush output before making the request.
702 sys.stderr.flush()
703 sys.stderr.flush()
703 sys.stdout.flush()
704 sys.stdout.flush()
704
705
705 # Send the input request.
706 # Send the input request.
706 content = json_clean(dict(prompt=prompt))
707 content = json_clean(dict(prompt=prompt))
707 self.session.send(self.stdin_socket, u'input_request', content, parent,
708 self.session.send(self.stdin_socket, u'input_request', content, parent,
708 ident=ident)
709 ident=ident)
709
710
710 # Await a response.
711 # Await a response.
711 while True:
712 while True:
712 try:
713 try:
713 ident, reply = self.session.recv(self.stdin_socket, 0)
714 ident, reply = self.session.recv(self.stdin_socket, 0)
714 except Exception:
715 except Exception:
715 self.log.warn("Invalid Message:", exc_info=True)
716 self.log.warn("Invalid Message:", exc_info=True)
716 else:
717 else:
717 break
718 break
718 try:
719 try:
719 value = reply['content']['value']
720 value = reply['content']['value']
720 except:
721 except:
721 self.log.error("Got bad raw_input reply: ")
722 self.log.error("Got bad raw_input reply: ")
722 self.log.error("%s", parent)
723 self.log.error("%s", parent)
723 value = ''
724 value = ''
724 if value == '\x04':
725 if value == '\x04':
725 # EOF
726 # EOF
726 raise EOFError
727 raise EOFError
727 return value
728 return value
728
729
729 def _complete(self, msg):
730 def _complete(self, msg):
730 c = msg['content']
731 c = msg['content']
731 try:
732 try:
732 cpos = int(c['cursor_pos'])
733 cpos = int(c['cursor_pos'])
733 except:
734 except:
734 # If we don't get something that we can convert to an integer, at
735 # If we don't get something that we can convert to an integer, at
735 # least attempt the completion guessing the cursor is at the end of
736 # least attempt the completion guessing the cursor is at the end of
736 # the text, if there's any, and otherwise of the line
737 # the text, if there's any, and otherwise of the line
737 cpos = len(c['text'])
738 cpos = len(c['text'])
738 if cpos==0:
739 if cpos==0:
739 cpos = len(c['line'])
740 cpos = len(c['line'])
740 return self.shell.complete(c['text'], c['line'], cpos)
741 return self.shell.complete(c['text'], c['line'], cpos)
741
742
742 def _object_info(self, context):
743 def _object_info(self, context):
743 symbol, leftover = self._symbol_from_context(context)
744 symbol, leftover = self._symbol_from_context(context)
744 if symbol is not None and not leftover:
745 if symbol is not None and not leftover:
745 doc = getattr(symbol, '__doc__', '')
746 doc = getattr(symbol, '__doc__', '')
746 else:
747 else:
747 doc = ''
748 doc = ''
748 object_info = dict(docstring = doc)
749 object_info = dict(docstring = doc)
749 return object_info
750 return object_info
750
751
751 def _symbol_from_context(self, context):
752 def _symbol_from_context(self, context):
752 if not context:
753 if not context:
753 return None, context
754 return None, context
754
755
755 base_symbol_string = context[0]
756 base_symbol_string = context[0]
756 symbol = self.shell.user_ns.get(base_symbol_string, None)
757 symbol = self.shell.user_ns.get(base_symbol_string, None)
757 if symbol is None:
758 if symbol is None:
758 symbol = __builtin__.__dict__.get(base_symbol_string, None)
759 symbol = __builtin__.__dict__.get(base_symbol_string, None)
759 if symbol is None:
760 if symbol is None:
760 return None, context
761 return None, context
761
762
762 context = context[1:]
763 context = context[1:]
763 for i, name in enumerate(context):
764 for i, name in enumerate(context):
764 new_symbol = getattr(symbol, name, None)
765 new_symbol = getattr(symbol, name, None)
765 if new_symbol is None:
766 if new_symbol is None:
766 return symbol, context[i:]
767 return symbol, context[i:]
767 else:
768 else:
768 symbol = new_symbol
769 symbol = new_symbol
769
770
770 return symbol, []
771 return symbol, []
771
772
772 def _at_shutdown(self):
773 def _at_shutdown(self):
773 """Actions taken at shutdown by the kernel, called by python's atexit.
774 """Actions taken at shutdown by the kernel, called by python's atexit.
774 """
775 """
775 # io.rprint("Kernel at_shutdown") # dbg
776 # io.rprint("Kernel at_shutdown") # dbg
776 if self._shutdown_message is not None:
777 if self._shutdown_message is not None:
777 self.session.send(self.iopub_socket, self._shutdown_message, ident=self._topic('shutdown'))
778 self.session.send(self.iopub_socket, self._shutdown_message, ident=self._topic('shutdown'))
778 self.log.debug("%s", self._shutdown_message)
779 self.log.debug("%s", self._shutdown_message)
779 [ s.flush(zmq.POLLOUT) for s in self.shell_streams ]
780 [ s.flush(zmq.POLLOUT) for s in self.shell_streams ]
780
781
781 #-----------------------------------------------------------------------------
782 #-----------------------------------------------------------------------------
782 # Aliases and Flags for the IPKernelApp
783 # Aliases and Flags for the IPKernelApp
783 #-----------------------------------------------------------------------------
784 #-----------------------------------------------------------------------------
784
785
785 flags = dict(kernel_flags)
786 flags = dict(kernel_flags)
786 flags.update(shell_flags)
787 flags.update(shell_flags)
787
788
788 addflag = lambda *args: flags.update(boolean_flag(*args))
789 addflag = lambda *args: flags.update(boolean_flag(*args))
789
790
790 flags['pylab'] = (
791 flags['pylab'] = (
791 {'IPKernelApp' : {'pylab' : 'auto'}},
792 {'IPKernelApp' : {'pylab' : 'auto'}},
792 """Pre-load matplotlib and numpy for interactive use with
793 """Pre-load matplotlib and numpy for interactive use with
793 the default matplotlib backend."""
794 the default matplotlib backend."""
794 )
795 )
795
796
796 aliases = dict(kernel_aliases)
797 aliases = dict(kernel_aliases)
797 aliases.update(shell_aliases)
798 aliases.update(shell_aliases)
798
799
799 #-----------------------------------------------------------------------------
800 #-----------------------------------------------------------------------------
800 # The IPKernelApp class
801 # The IPKernelApp class
801 #-----------------------------------------------------------------------------
802 #-----------------------------------------------------------------------------
802
803
803 class IPKernelApp(KernelApp, InteractiveShellApp):
804 class IPKernelApp(KernelApp, InteractiveShellApp):
804 name = 'ipkernel'
805 name = 'ipkernel'
805
806
806 aliases = Dict(aliases)
807 aliases = Dict(aliases)
807 flags = Dict(flags)
808 flags = Dict(flags)
808 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
809 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
809
810
810 @catch_config_error
811 @catch_config_error
811 def initialize(self, argv=None):
812 def initialize(self, argv=None):
812 super(IPKernelApp, self).initialize(argv)
813 super(IPKernelApp, self).initialize(argv)
813 self.init_path()
814 self.init_path()
814 self.init_shell()
815 self.init_shell()
815 self.init_gui_pylab()
816 self.init_gui_pylab()
816 self.init_extensions()
817 self.init_extensions()
817 self.init_code()
818 self.init_code()
818
819
819 def init_kernel(self):
820 def init_kernel(self):
820
821
821 shell_stream = ZMQStream(self.shell_socket)
822 shell_stream = ZMQStream(self.shell_socket)
822
823
823 kernel = Kernel(config=self.config, session=self.session,
824 kernel = Kernel(config=self.config, session=self.session,
824 shell_streams=[shell_stream],
825 shell_streams=[shell_stream],
825 iopub_socket=self.iopub_socket,
826 iopub_socket=self.iopub_socket,
826 stdin_socket=self.stdin_socket,
827 stdin_socket=self.stdin_socket,
827 log=self.log,
828 log=self.log,
828 profile_dir=self.profile_dir,
829 profile_dir=self.profile_dir,
829 )
830 )
830 self.kernel = kernel
831 self.kernel = kernel
831 kernel.record_ports(self.ports)
832 kernel.record_ports(self.ports)
832 shell = kernel.shell
833 shell = kernel.shell
833
834
834 def init_gui_pylab(self):
835 def init_gui_pylab(self):
835 """Enable GUI event loop integration, taking pylab into account."""
836 """Enable GUI event loop integration, taking pylab into account."""
836
837
837 # Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
838 # Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
838 # to ensure that any exception is printed straight to stderr.
839 # to ensure that any exception is printed straight to stderr.
839 # Normally _showtraceback associates the reply with an execution,
840 # Normally _showtraceback associates the reply with an execution,
840 # which means frontends will never draw it, as this exception
841 # which means frontends will never draw it, as this exception
841 # is not associated with any execute request.
842 # is not associated with any execute request.
842
843
843 shell = self.shell
844 shell = self.shell
844 _showtraceback = shell._showtraceback
845 _showtraceback = shell._showtraceback
845 try:
846 try:
846 # replace pyerr-sending traceback with stderr
847 # replace pyerr-sending traceback with stderr
847 def print_tb(etype, evalue, stb):
848 def print_tb(etype, evalue, stb):
848 print ("GUI event loop or pylab initialization failed",
849 print ("GUI event loop or pylab initialization failed",
849 file=io.stderr)
850 file=io.stderr)
850 print (shell.InteractiveTB.stb2text(stb), file=io.stderr)
851 print (shell.InteractiveTB.stb2text(stb), file=io.stderr)
851 shell._showtraceback = print_tb
852 shell._showtraceback = print_tb
852 InteractiveShellApp.init_gui_pylab(self)
853 InteractiveShellApp.init_gui_pylab(self)
853 finally:
854 finally:
854 shell._showtraceback = _showtraceback
855 shell._showtraceback = _showtraceback
855
856
856 def init_shell(self):
857 def init_shell(self):
857 self.shell = self.kernel.shell
858 self.shell = self.kernel.shell
858 self.shell.configurables.append(self)
859 self.shell.configurables.append(self)
859
860
860
861
861 #-----------------------------------------------------------------------------
862 #-----------------------------------------------------------------------------
862 # Kernel main and launch functions
863 # Kernel main and launch functions
863 #-----------------------------------------------------------------------------
864 #-----------------------------------------------------------------------------
864
865
865 def launch_kernel(*args, **kwargs):
866 def launch_kernel(*args, **kwargs):
866 """Launches a localhost IPython kernel, binding to the specified ports.
867 """Launches a localhost IPython kernel, binding to the specified ports.
867
868
868 This function simply calls entry_point.base_launch_kernel with the right
869 This function simply calls entry_point.base_launch_kernel with the right
869 first command to start an ipkernel. See base_launch_kernel for arguments.
870 first command to start an ipkernel. See base_launch_kernel for arguments.
870
871
871 Returns
872 Returns
872 -------
873 -------
873 A tuple of form:
874 A tuple of form:
874 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
875 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
875 where kernel_process is a Popen object and the ports are integers.
876 where kernel_process is a Popen object and the ports are integers.
876 """
877 """
877 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
878 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
878 *args, **kwargs)
879 *args, **kwargs)
879
880
880
881
881 def embed_kernel(module=None, local_ns=None, **kwargs):
882 def embed_kernel(module=None, local_ns=None, **kwargs):
882 """Embed and start an IPython kernel in a given scope.
883 """Embed and start an IPython kernel in a given scope.
883
884
884 Parameters
885 Parameters
885 ----------
886 ----------
886 module : ModuleType, optional
887 module : ModuleType, optional
887 The module to load into IPython globals (default: caller)
888 The module to load into IPython globals (default: caller)
888 local_ns : dict, optional
889 local_ns : dict, optional
889 The namespace to load into IPython user namespace (default: caller)
890 The namespace to load into IPython user namespace (default: caller)
890
891
891 kwargs : various, optional
892 kwargs : various, optional
892 Further keyword args are relayed to the KernelApp constructor,
893 Further keyword args are relayed to the KernelApp constructor,
893 allowing configuration of the Kernel. Will only have an effect
894 allowing configuration of the Kernel. Will only have an effect
894 on the first embed_kernel call for a given process.
895 on the first embed_kernel call for a given process.
895
896
896 """
897 """
897 # get the app if it exists, or set it up if it doesn't
898 # get the app if it exists, or set it up if it doesn't
898 if IPKernelApp.initialized():
899 if IPKernelApp.initialized():
899 app = IPKernelApp.instance()
900 app = IPKernelApp.instance()
900 else:
901 else:
901 app = IPKernelApp.instance(**kwargs)
902 app = IPKernelApp.instance(**kwargs)
902 app.initialize([])
903 app.initialize([])
903 # Undo unnecessary sys module mangling from init_sys_modules.
904 # Undo unnecessary sys module mangling from init_sys_modules.
904 # This would not be necessary if we could prevent it
905 # This would not be necessary if we could prevent it
905 # in the first place by using a different InteractiveShell
906 # in the first place by using a different InteractiveShell
906 # subclass, as in the regular embed case.
907 # subclass, as in the regular embed case.
907 main = app.kernel.shell._orig_sys_modules_main_mod
908 main = app.kernel.shell._orig_sys_modules_main_mod
908 if main is not None:
909 if main is not None:
909 sys.modules[app.kernel.shell._orig_sys_modules_main_name] = main
910 sys.modules[app.kernel.shell._orig_sys_modules_main_name] = main
910
911
911 # load the calling scope if not given
912 # load the calling scope if not given
912 (caller_module, caller_locals) = extract_module_locals(1)
913 (caller_module, caller_locals) = extract_module_locals(1)
913 if module is None:
914 if module is None:
914 module = caller_module
915 module = caller_module
915 if local_ns is None:
916 if local_ns is None:
916 local_ns = caller_locals
917 local_ns = caller_locals
917
918
918 app.kernel.user_module = module
919 app.kernel.user_module = module
919 app.kernel.user_ns = local_ns
920 app.kernel.user_ns = local_ns
920 app.shell.set_completer_frame()
921 app.shell.set_completer_frame()
921 app.start()
922 app.start()
922
923
923 def main():
924 def main():
924 """Run an IPKernel as an application"""
925 """Run an IPKernel as an application"""
925 app = IPKernelApp.instance()
926 app = IPKernelApp.instance()
926 app.initialize()
927 app.initialize()
927 app.start()
928 app.start()
928
929
929
930
930 if __name__ == '__main__':
931 if __name__ == '__main__':
931 main()
932 main()
@@ -1,1002 +1,1002 b''
1 .. _messaging:
1 .. _messaging:
2
2
3 ======================
3 ======================
4 Messaging in IPython
4 Messaging in IPython
5 ======================
5 ======================
6
6
7
7
8 Introduction
8 Introduction
9 ============
9 ============
10
10
11 This document explains the basic communications design and messaging
11 This document explains the basic communications design and messaging
12 specification for how the various IPython objects interact over a network
12 specification for how the various IPython objects interact over a network
13 transport. The current implementation uses the ZeroMQ_ library for messaging
13 transport. The current implementation uses the ZeroMQ_ library for messaging
14 within and between hosts.
14 within and between hosts.
15
15
16 .. Note::
16 .. Note::
17
17
18 This document should be considered the authoritative description of the
18 This document should be considered the authoritative description of the
19 IPython messaging protocol, and all developers are strongly encouraged to
19 IPython messaging protocol, and all developers are strongly encouraged to
20 keep it updated as the implementation evolves, so that we have a single
20 keep it updated as the implementation evolves, so that we have a single
21 common reference for all protocol details.
21 common reference for all protocol details.
22
22
23 The basic design is explained in the following diagram:
23 The basic design is explained in the following diagram:
24
24
25 .. image:: figs/frontend-kernel.png
25 .. image:: figs/frontend-kernel.png
26 :width: 450px
26 :width: 450px
27 :alt: IPython kernel/frontend messaging architecture.
27 :alt: IPython kernel/frontend messaging architecture.
28 :align: center
28 :align: center
29 :target: ../_images/frontend-kernel.png
29 :target: ../_images/frontend-kernel.png
30
30
31 A single kernel can be simultaneously connected to one or more frontends. The
31 A single kernel can be simultaneously connected to one or more frontends. The
32 kernel has three sockets that serve the following functions:
32 kernel has three sockets that serve the following functions:
33
33
34 1. stdin: this ROUTER socket is connected to all frontends, and it allows
34 1. stdin: this ROUTER socket is connected to all frontends, and it allows
35 the kernel to request input from the active frontend when :func:`raw_input` is called.
35 the kernel to request input from the active frontend when :func:`raw_input` is called.
36 The frontend that executed the code has a DEALER socket that acts as a 'virtual keyboard'
36 The frontend that executed the code has a DEALER socket that acts as a 'virtual keyboard'
37 for the kernel while this communication is happening (illustrated in the
37 for the kernel while this communication is happening (illustrated in the
38 figure by the black outline around the central keyboard). In practice,
38 figure by the black outline around the central keyboard). In practice,
39 frontends may display such kernel requests using a special input widget or
39 frontends may display such kernel requests using a special input widget or
40 otherwise indicating that the user is to type input for the kernel instead
40 otherwise indicating that the user is to type input for the kernel instead
41 of normal commands in the frontend.
41 of normal commands in the frontend.
42
42
43 2. Shell: this single ROUTER socket allows multiple incoming connections from
43 2. Shell: this single ROUTER socket allows multiple incoming connections from
44 frontends, and this is the socket where requests for code execution, object
44 frontends, and this is the socket where requests for code execution, object
45 information, prompts, etc. are made to the kernel by any frontend. The
45 information, prompts, etc. are made to the kernel by any frontend. The
46 communication on this socket is a sequence of request/reply actions from
46 communication on this socket is a sequence of request/reply actions from
47 each frontend and the kernel.
47 each frontend and the kernel.
48
48
49 3. IOPub: this socket is the 'broadcast channel' where the kernel publishes all
49 3. IOPub: this socket is the 'broadcast channel' where the kernel publishes all
50 side effects (stdout, stderr, etc.) as well as the requests coming from any
50 side effects (stdout, stderr, etc.) as well as the requests coming from any
51 client over the shell socket and its own requests on the stdin socket. There
51 client over the shell socket and its own requests on the stdin socket. There
52 are a number of actions in Python which generate side effects: :func:`print`
52 are a number of actions in Python which generate side effects: :func:`print`
53 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
53 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
54 a multi-client scenario, we want all frontends to be able to know what each
54 a multi-client scenario, we want all frontends to be able to know what each
55 other has sent to the kernel (this can be useful in collaborative scenarios,
55 other has sent to the kernel (this can be useful in collaborative scenarios,
56 for example). This socket allows both side effects and the information
56 for example). This socket allows both side effects and the information
57 about communications taking place with one client over the shell channel
57 about communications taking place with one client over the shell channel
58 to be made available to all clients in a uniform manner.
58 to be made available to all clients in a uniform manner.
59
59
60 All messages are tagged with enough information (details below) for clients
60 All messages are tagged with enough information (details below) for clients
61 to know which messages come from their own interaction with the kernel and
61 to know which messages come from their own interaction with the kernel and
62 which ones are from other clients, so they can display each type
62 which ones are from other clients, so they can display each type
63 appropriately.
63 appropriately.
64
64
65 The actual format of the messages allowed on each of these channels is
65 The actual format of the messages allowed on each of these channels is
66 specified below. Messages are dicts of dicts with string keys and values that
66 specified below. Messages are dicts of dicts with string keys and values that
67 are reasonably representable in JSON. Our current implementation uses JSON
67 are reasonably representable in JSON. Our current implementation uses JSON
68 explicitly as its message format, but this shouldn't be considered a permanent
68 explicitly as its message format, but this shouldn't be considered a permanent
69 feature. As we've discovered that JSON has non-trivial performance issues due
69 feature. As we've discovered that JSON has non-trivial performance issues due
70 to excessive copying, we may in the future move to a pure pickle-based raw
70 to excessive copying, we may in the future move to a pure pickle-based raw
71 message format. However, it should be possible to easily convert from the raw
71 message format. However, it should be possible to easily convert from the raw
72 objects to JSON, since we may have non-python clients (e.g. a web frontend).
72 objects to JSON, since we may have non-python clients (e.g. a web frontend).
73 As long as it's easy to make a JSON version of the objects that is a faithful
73 As long as it's easy to make a JSON version of the objects that is a faithful
74 representation of all the data, we can communicate with such clients.
74 representation of all the data, we can communicate with such clients.
75
75
76 .. Note::
76 .. Note::
77
77
78 Not all of these have yet been fully fleshed out, but the key ones are, see
78 Not all of these have yet been fully fleshed out, but the key ones are, see
79 kernel and frontend files for actual implementation details.
79 kernel and frontend files for actual implementation details.
80
80
81 General Message Format
81 General Message Format
82 ======================
82 ======================
83
83
84 A message is defined by the following four-dictionary structure::
84 A message is defined by the following four-dictionary structure::
85
85
86 {
86 {
87 # The message header contains a pair of unique identifiers for the
87 # The message header contains a pair of unique identifiers for the
88 # originating session and the actual message id, in addition to the
88 # originating session and the actual message id, in addition to the
89 # username for the process that generated the message. This is useful in
89 # username for the process that generated the message. This is useful in
90 # collaborative settings where multiple users may be interacting with the
90 # collaborative settings where multiple users may be interacting with the
91 # same kernel simultaneously, so that frontends can label the various
91 # same kernel simultaneously, so that frontends can label the various
92 # messages in a meaningful way.
92 # messages in a meaningful way.
93 'header' : {
93 'header' : {
94 'msg_id' : uuid,
94 'msg_id' : uuid,
95 'username' : str,
95 'username' : str,
96 'session' : uuid
96 'session' : uuid
97 # All recognized message type strings are listed below.
97 # All recognized message type strings are listed below.
98 'msg_type' : str,
98 'msg_type' : str,
99 },
99 },
100
100
101 # In a chain of messages, the header from the parent is copied so that
101 # In a chain of messages, the header from the parent is copied so that
102 # clients can track where messages come from.
102 # clients can track where messages come from.
103 'parent_header' : dict,
103 'parent_header' : dict,
104
104
105 # The actual content of the message must be a dict, whose structure
105 # The actual content of the message must be a dict, whose structure
106 # depends on the message type.
106 # depends on the message type.
107 'content' : dict,
107 'content' : dict,
108
108
109 # Any metadata associated with the message.
109 # Any metadata associated with the message.
110 'metadata' : dict,
110 'metadata' : dict,
111 }
111 }
112
112
113
113
114 Python functional API
114 Python functional API
115 =====================
115 =====================
116
116
117 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
117 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
118 should develop, at a few key points, functional forms of all the requests that
118 should develop, at a few key points, functional forms of all the requests that
119 take arguments in this manner and automatically construct the necessary dict
119 take arguments in this manner and automatically construct the necessary dict
120 for sending.
120 for sending.
121
121
122 In addition, the Python implementation of the message specification extends
122 In addition, the Python implementation of the message specification extends
123 messages upon deserialization to the following form for convenience::
123 messages upon deserialization to the following form for convenience::
124
124
125 {
125 {
126 'header' : dict,
126 'header' : dict,
127 # The msg's unique identifier and type are always stored in the header,
127 # The msg's unique identifier and type are always stored in the header,
128 # but the Python implementation copies them to the top level.
128 # but the Python implementation copies them to the top level.
129 'msg_id' : uuid,
129 'msg_id' : uuid,
130 'msg_type' : str,
130 'msg_type' : str,
131 'parent_header' : dict,
131 'parent_header' : dict,
132 'content' : dict,
132 'content' : dict,
133 'metadata' : dict,
133 'metadata' : dict,
134 }
134 }
135
135
136 All messages sent to or received by any IPython process should have this
136 All messages sent to or received by any IPython process should have this
137 extended structure.
137 extended structure.
138
138
139
139
140 Messages on the shell ROUTER/DEALER sockets
140 Messages on the shell ROUTER/DEALER sockets
141 ===========================================
141 ===========================================
142
142
143 .. _execute:
143 .. _execute:
144
144
145 Execute
145 Execute
146 -------
146 -------
147
147
148 This message type is used by frontends to ask the kernel to execute code on
148 This message type is used by frontends to ask the kernel to execute code on
149 behalf of the user, in a namespace reserved to the user's variables (and thus
149 behalf of the user, in a namespace reserved to the user's variables (and thus
150 separate from the kernel's own internal code and variables).
150 separate from the kernel's own internal code and variables).
151
151
152 Message type: ``execute_request``::
152 Message type: ``execute_request``::
153
153
154 content = {
154 content = {
155 # Source code to be executed by the kernel, one or more lines.
155 # Source code to be executed by the kernel, one or more lines.
156 'code' : str,
156 'code' : str,
157
157
158 # A boolean flag which, if True, signals the kernel to execute
158 # A boolean flag which, if True, signals the kernel to execute
159 # this code as quietly as possible. This means that the kernel
159 # this code as quietly as possible. This means that the kernel
160 # will compile the code with 'exec' instead of 'single' (so
160 # will compile the code with 'exec' instead of 'single' (so
161 # sys.displayhook will not fire), forces store_history to be False,
161 # sys.displayhook will not fire), forces store_history to be False,
162 # and will *not*:
162 # and will *not*:
163 # - broadcast exceptions on the PUB socket
163 # - broadcast exceptions on the PUB socket
164 # - do any logging
164 # - do any logging
165 #
165 #
166 # The default is False.
166 # The default is False.
167 'silent' : bool,
167 'silent' : bool,
168
168
169 # A boolean flag which, if True, signals the kernel to populate history
169 # A boolean flag which, if True, signals the kernel to populate history
170 # The default is True if silent is False. If silent is True, store_history
170 # The default is True if silent is False. If silent is True, store_history
171 # is forced to be False.
171 # is forced to be False.
172 'store_history' : bool,
172 'store_history' : bool,
173
173
174 # A list of variable names from the user's namespace to be retrieved. What
174 # A list of variable names from the user's namespace to be retrieved. What
175 # returns is a JSON string of the variable's repr(), not a python object.
175 # returns is a JSON string of the variable's repr(), not a python object.
176 'user_variables' : list,
176 'user_variables' : list,
177
177
178 # Similarly, a dict mapping names to expressions to be evaluated in the
178 # Similarly, a dict mapping names to expressions to be evaluated in the
179 # user's dict.
179 # user's dict.
180 'user_expressions' : dict,
180 'user_expressions' : dict,
181
181
182 # Some frontends (e.g. the Notebook) do not support stdin requests. If
182 # Some frontends (e.g. the Notebook) do not support stdin requests. If
183 # raw_input is called from code executed from such a frontend, a
183 # raw_input is called from code executed from such a frontend, a
184 # StdinNotImplementedError will be raised.
184 # StdinNotImplementedError will be raised.
185 'allow_stdin' : True,
185 'allow_stdin' : True,
186
186
187 }
187 }
188
188
189 The ``code`` field contains a single string (possibly multiline). The kernel
189 The ``code`` field contains a single string (possibly multiline). The kernel
190 is responsible for splitting this into one or more independent execution blocks
190 is responsible for splitting this into one or more independent execution blocks
191 and deciding whether to compile these in 'single' or 'exec' mode (see below for
191 and deciding whether to compile these in 'single' or 'exec' mode (see below for
192 detailed execution semantics).
192 detailed execution semantics).
193
193
194 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
194 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
195 the notion of a prompt string that allowed arbitrary code to be evaluated, and
195 the notion of a prompt string that allowed arbitrary code to be evaluated, and
196 this was put to good use by many in creating prompts that displayed system
196 this was put to good use by many in creating prompts that displayed system
197 status, path information, and even more esoteric uses like remote instrument
197 status, path information, and even more esoteric uses like remote instrument
198 status aqcuired over the network. But now that IPython has a clean separation
198 status aqcuired over the network. But now that IPython has a clean separation
199 between the kernel and the clients, the kernel has no prompt knowledge; prompts
199 between the kernel and the clients, the kernel has no prompt knowledge; prompts
200 are a frontend-side feature, and it should be even possible for different
200 are a frontend-side feature, and it should be even possible for different
201 frontends to display different prompts while interacting with the same kernel.
201 frontends to display different prompts while interacting with the same kernel.
202
202
203 The kernel now provides the ability to retrieve data from the user's namespace
203 The kernel now provides the ability to retrieve data from the user's namespace
204 after the execution of the main ``code``, thanks to two fields in the
204 after the execution of the main ``code``, thanks to two fields in the
205 ``execute_request`` message:
205 ``execute_request`` message:
206
206
207 - ``user_variables``: If only variables from the user's namespace are needed, a
207 - ``user_variables``: If only variables from the user's namespace are needed, a
208 list of variable names can be passed and a dict with these names as keys and
208 list of variable names can be passed and a dict with these names as keys and
209 their :func:`repr()` as values will be returned.
209 their :func:`repr()` as values will be returned.
210
210
211 - ``user_expressions``: For more complex expressions that require function
211 - ``user_expressions``: For more complex expressions that require function
212 evaluations, a dict can be provided with string keys and arbitrary python
212 evaluations, a dict can be provided with string keys and arbitrary python
213 expressions as values. The return message will contain also a dict with the
213 expressions as values. The return message will contain also a dict with the
214 same keys and the :func:`repr()` of the evaluated expressions as value.
214 same keys and the :func:`repr()` of the evaluated expressions as value.
215
215
216 With this information, frontends can display any status information they wish
216 With this information, frontends can display any status information they wish
217 in the form that best suits each frontend (a status line, a popup, inline for a
217 in the form that best suits each frontend (a status line, a popup, inline for a
218 terminal, etc).
218 terminal, etc).
219
219
220 .. Note::
220 .. Note::
221
221
222 In order to obtain the current execution counter for the purposes of
222 In order to obtain the current execution counter for the purposes of
223 displaying input prompts, frontends simply make an execution request with an
223 displaying input prompts, frontends simply make an execution request with an
224 empty code string and ``silent=True``.
224 empty code string and ``silent=True``.
225
225
226 Execution semantics
226 Execution semantics
227 ~~~~~~~~~~~~~~~~~~~
227 ~~~~~~~~~~~~~~~~~~~
228
228
229 When the silent flag is false, the execution of use code consists of the
229 When the silent flag is false, the execution of use code consists of the
230 following phases (in silent mode, only the ``code`` field is executed):
230 following phases (in silent mode, only the ``code`` field is executed):
231
231
232 1. Run the ``pre_runcode_hook``.
232 1. Run the ``pre_runcode_hook``.
233
233
234 2. Execute the ``code`` field, see below for details.
234 2. Execute the ``code`` field, see below for details.
235
235
236 3. If #2 succeeds, compute ``user_variables`` and ``user_expressions`` are
236 3. If #2 succeeds, compute ``user_variables`` and ``user_expressions`` are
237 computed. This ensures that any error in the latter don't harm the main
237 computed. This ensures that any error in the latter don't harm the main
238 code execution.
238 code execution.
239
239
240 4. Call any method registered with :meth:`register_post_execute`.
240 4. Call any method registered with :meth:`register_post_execute`.
241
241
242 .. warning::
242 .. warning::
243
243
244 The API for running code before/after the main code block is likely to
244 The API for running code before/after the main code block is likely to
245 change soon. Both the ``pre_runcode_hook`` and the
245 change soon. Both the ``pre_runcode_hook`` and the
246 :meth:`register_post_execute` are susceptible to modification, as we find a
246 :meth:`register_post_execute` are susceptible to modification, as we find a
247 consistent model for both.
247 consistent model for both.
248
248
249 To understand how the ``code`` field is executed, one must know that Python
249 To understand how the ``code`` field is executed, one must know that Python
250 code can be compiled in one of three modes (controlled by the ``mode`` argument
250 code can be compiled in one of three modes (controlled by the ``mode`` argument
251 to the :func:`compile` builtin):
251 to the :func:`compile` builtin):
252
252
253 *single*
253 *single*
254 Valid for a single interactive statement (though the source can contain
254 Valid for a single interactive statement (though the source can contain
255 multiple lines, such as a for loop). When compiled in this mode, the
255 multiple lines, such as a for loop). When compiled in this mode, the
256 generated bytecode contains special instructions that trigger the calling of
256 generated bytecode contains special instructions that trigger the calling of
257 :func:`sys.displayhook` for any expression in the block that returns a value.
257 :func:`sys.displayhook` for any expression in the block that returns a value.
258 This means that a single statement can actually produce multiple calls to
258 This means that a single statement can actually produce multiple calls to
259 :func:`sys.displayhook`, if for example it contains a loop where each
259 :func:`sys.displayhook`, if for example it contains a loop where each
260 iteration computes an unassigned expression would generate 10 calls::
260 iteration computes an unassigned expression would generate 10 calls::
261
261
262 for i in range(10):
262 for i in range(10):
263 i**2
263 i**2
264
264
265 *exec*
265 *exec*
266 An arbitrary amount of source code, this is how modules are compiled.
266 An arbitrary amount of source code, this is how modules are compiled.
267 :func:`sys.displayhook` is *never* implicitly called.
267 :func:`sys.displayhook` is *never* implicitly called.
268
268
269 *eval*
269 *eval*
270 A single expression that returns a value. :func:`sys.displayhook` is *never*
270 A single expression that returns a value. :func:`sys.displayhook` is *never*
271 implicitly called.
271 implicitly called.
272
272
273
273
274 The ``code`` field is split into individual blocks each of which is valid for
274 The ``code`` field is split into individual blocks each of which is valid for
275 execution in 'single' mode, and then:
275 execution in 'single' mode, and then:
276
276
277 - If there is only a single block: it is executed in 'single' mode.
277 - If there is only a single block: it is executed in 'single' mode.
278
278
279 - If there is more than one block:
279 - If there is more than one block:
280
280
281 * if the last one is a single line long, run all but the last in 'exec' mode
281 * if the last one is a single line long, run all but the last in 'exec' mode
282 and the very last one in 'single' mode. This makes it easy to type simple
282 and the very last one in 'single' mode. This makes it easy to type simple
283 expressions at the end to see computed values.
283 expressions at the end to see computed values.
284
284
285 * if the last one is no more than two lines long, run all but the last in
285 * if the last one is no more than two lines long, run all but the last in
286 'exec' mode and the very last one in 'single' mode. This makes it easy to
286 'exec' mode and the very last one in 'single' mode. This makes it easy to
287 type simple expressions at the end to see computed values. - otherwise
287 type simple expressions at the end to see computed values. - otherwise
288 (last one is also multiline), run all in 'exec' mode
288 (last one is also multiline), run all in 'exec' mode
289
289
290 * otherwise (last one is also multiline), run all in 'exec' mode as a single
290 * otherwise (last one is also multiline), run all in 'exec' mode as a single
291 unit.
291 unit.
292
292
293 Any error in retrieving the ``user_variables`` or evaluating the
293 Any error in retrieving the ``user_variables`` or evaluating the
294 ``user_expressions`` will result in a simple error message in the return fields
294 ``user_expressions`` will result in a simple error message in the return fields
295 of the form::
295 of the form::
296
296
297 [ERROR] ExceptionType: Exception message
297 [ERROR] ExceptionType: Exception message
298
298
299 The user can simply send the same variable name or expression for evaluation to
299 The user can simply send the same variable name or expression for evaluation to
300 see a regular traceback.
300 see a regular traceback.
301
301
302 Errors in any registered post_execute functions are also reported similarly,
302 Errors in any registered post_execute functions are also reported similarly,
303 and the failing function is removed from the post_execution set so that it does
303 and the failing function is removed from the post_execution set so that it does
304 not continue triggering failures.
304 not continue triggering failures.
305
305
306 Upon completion of the execution request, the kernel *always* sends a reply,
306 Upon completion of the execution request, the kernel *always* sends a reply,
307 with a status code indicating what happened and additional data depending on
307 with a status code indicating what happened and additional data depending on
308 the outcome. See :ref:`below <execution_results>` for the possible return
308 the outcome. See :ref:`below <execution_results>` for the possible return
309 codes and associated data.
309 codes and associated data.
310
310
311
311
312 Execution counter (old prompt number)
312 Execution counter (old prompt number)
313 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
313 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
314
314
315 The kernel has a single, monotonically increasing counter of all execution
315 The kernel has a single, monotonically increasing counter of all execution
316 requests that are made with ``store_history=True``. This counter is used to populate
316 requests that are made with ``store_history=True``. This counter is used to populate
317 the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will likely want to
317 the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will likely want to
318 display it in some form to the user, which will typically (but not necessarily)
318 display it in some form to the user, which will typically (but not necessarily)
319 be done in the prompts. The value of this counter will be returned as the
319 be done in the prompts. The value of this counter will be returned as the
320 ``execution_count`` field of all ``execute_reply`` messages.
320 ``execution_count`` field of all ``execute_reply`` messages.
321
321
322 .. _execution_results:
322 .. _execution_results:
323
323
324 Execution results
324 Execution results
325 ~~~~~~~~~~~~~~~~~
325 ~~~~~~~~~~~~~~~~~
326
326
327 Message type: ``execute_reply``::
327 Message type: ``execute_reply``::
328
328
329 content = {
329 content = {
330 # One of: 'ok' OR 'error' OR 'abort'
330 # One of: 'ok' OR 'error' OR 'abort'
331 'status' : str,
331 'status' : str,
332
332
333 # The global kernel counter that increases by one with each request that
333 # The global kernel counter that increases by one with each request that
334 # stores history. This will typically be used by clients to display
334 # stores history. This will typically be used by clients to display
335 # prompt numbers to the user. If the request did not store history, this will
335 # prompt numbers to the user. If the request did not store history, this will
336 # be the current value of the counter in the kernel.
336 # be the current value of the counter in the kernel.
337 'execution_count' : int,
337 'execution_count' : int,
338 }
338 }
339
339
340 When status is 'ok', the following extra fields are present::
340 When status is 'ok', the following extra fields are present::
341
341
342 {
342 {
343 # 'payload' will be a list of payload dicts.
343 # 'payload' will be a list of payload dicts.
344 # Each execution payload is a dict with string keys that may have been
344 # Each execution payload is a dict with string keys that may have been
345 # produced by the code being executed. It is retrieved by the kernel at
345 # produced by the code being executed. It is retrieved by the kernel at
346 # the end of the execution and sent back to the front end, which can take
346 # the end of the execution and sent back to the front end, which can take
347 # action on it as needed. See main text for further details.
347 # action on it as needed. See main text for further details.
348 'payload' : list(dict),
348 'payload' : list(dict),
349
349
350 # Results for the user_variables and user_expressions.
350 # Results for the user_variables and user_expressions.
351 'user_variables' : dict,
351 'user_variables' : dict,
352 'user_expressions' : dict,
352 'user_expressions' : dict,
353 }
353 }
354
354
355 .. admonition:: Execution payloads
355 .. admonition:: Execution payloads
356
356
357 The notion of an 'execution payload' is different from a return value of a
357 The notion of an 'execution payload' is different from a return value of a
358 given set of code, which normally is just displayed on the pyout stream
358 given set of code, which normally is just displayed on the pyout stream
359 through the PUB socket. The idea of a payload is to allow special types of
359 through the PUB socket. The idea of a payload is to allow special types of
360 code, typically magics, to populate a data container in the IPython kernel
360 code, typically magics, to populate a data container in the IPython kernel
361 that will be shipped back to the caller via this channel. The kernel
361 that will be shipped back to the caller via this channel. The kernel
362 has an API for this in the PayloadManager::
362 has an API for this in the PayloadManager::
363
363
364 ip.payload_manager.write_payload(payload_dict)
364 ip.payload_manager.write_payload(payload_dict)
365
365
366 which appends a dictionary to the list of payloads.
366 which appends a dictionary to the list of payloads.
367
367
368
368
369 When status is 'error', the following extra fields are present::
369 When status is 'error', the following extra fields are present::
370
370
371 {
371 {
372 'ename' : str, # Exception name, as a string
372 'ename' : str, # Exception name, as a string
373 'evalue' : str, # Exception value, as a string
373 'evalue' : str, # Exception value, as a string
374
374
375 # The traceback will contain a list of frames, represented each as a
375 # The traceback will contain a list of frames, represented each as a
376 # string. For now we'll stick to the existing design of ultraTB, which
376 # string. For now we'll stick to the existing design of ultraTB, which
377 # controls exception level of detail statefully. But eventually we'll
377 # controls exception level of detail statefully. But eventually we'll
378 # want to grow into a model where more information is collected and
378 # want to grow into a model where more information is collected and
379 # packed into the traceback object, with clients deciding how little or
379 # packed into the traceback object, with clients deciding how little or
380 # how much of it to unpack. But for now, let's start with a simple list
380 # how much of it to unpack. But for now, let's start with a simple list
381 # of strings, since that requires only minimal changes to ultratb as
381 # of strings, since that requires only minimal changes to ultratb as
382 # written.
382 # written.
383 'traceback' : list,
383 'traceback' : list,
384 }
384 }
385
385
386
386
387 When status is 'abort', there are for now no additional data fields. This
387 When status is 'abort', there are for now no additional data fields. This
388 happens when the kernel was interrupted by a signal.
388 happens when the kernel was interrupted by a signal.
389
389
390 Kernel attribute access
390 Kernel attribute access
391 -----------------------
391 -----------------------
392
392
393 .. warning::
393 .. warning::
394
394
395 This part of the messaging spec is not actually implemented in the kernel
395 This part of the messaging spec is not actually implemented in the kernel
396 yet.
396 yet.
397
397
398 While this protocol does not specify full RPC access to arbitrary methods of
398 While this protocol does not specify full RPC access to arbitrary methods of
399 the kernel object, the kernel does allow read (and in some cases write) access
399 the kernel object, the kernel does allow read (and in some cases write) access
400 to certain attributes.
400 to certain attributes.
401
401
402 The policy for which attributes can be read is: any attribute of the kernel, or
402 The policy for which attributes can be read is: any attribute of the kernel, or
403 its sub-objects, that belongs to a :class:`Configurable` object and has been
403 its sub-objects, that belongs to a :class:`Configurable` object and has been
404 declared at the class-level with Traits validation, is in principle accessible
404 declared at the class-level with Traits validation, is in principle accessible
405 as long as its name does not begin with a leading underscore. The attribute
405 as long as its name does not begin with a leading underscore. The attribute
406 itself will have metadata indicating whether it allows remote read and/or write
406 itself will have metadata indicating whether it allows remote read and/or write
407 access. The message spec follows for attribute read and write requests.
407 access. The message spec follows for attribute read and write requests.
408
408
409 Message type: ``getattr_request``::
409 Message type: ``getattr_request``::
410
410
411 content = {
411 content = {
412 # The (possibly dotted) name of the attribute
412 # The (possibly dotted) name of the attribute
413 'name' : str,
413 'name' : str,
414 }
414 }
415
415
416 When a ``getattr_request`` fails, there are two possible error types:
416 When a ``getattr_request`` fails, there are two possible error types:
417
417
418 - AttributeError: this type of error was raised when trying to access the
418 - AttributeError: this type of error was raised when trying to access the
419 given name by the kernel itself. This means that the attribute likely
419 given name by the kernel itself. This means that the attribute likely
420 doesn't exist.
420 doesn't exist.
421
421
422 - AccessError: the attribute exists but its value is not readable remotely.
422 - AccessError: the attribute exists but its value is not readable remotely.
423
423
424
424
425 Message type: ``getattr_reply``::
425 Message type: ``getattr_reply``::
426
426
427 content = {
427 content = {
428 # One of ['ok', 'AttributeError', 'AccessError'].
428 # One of ['ok', 'AttributeError', 'AccessError'].
429 'status' : str,
429 'status' : str,
430 # If status is 'ok', a JSON object.
430 # If status is 'ok', a JSON object.
431 'value' : object,
431 'value' : object,
432 }
432 }
433
433
434 Message type: ``setattr_request``::
434 Message type: ``setattr_request``::
435
435
436 content = {
436 content = {
437 # The (possibly dotted) name of the attribute
437 # The (possibly dotted) name of the attribute
438 'name' : str,
438 'name' : str,
439
439
440 # A JSON-encoded object, that will be validated by the Traits
440 # A JSON-encoded object, that will be validated by the Traits
441 # information in the kernel
441 # information in the kernel
442 'value' : object,
442 'value' : object,
443 }
443 }
444
444
445 When a ``setattr_request`` fails, there are also two possible error types with
445 When a ``setattr_request`` fails, there are also two possible error types with
446 similar meanings as those of the ``getattr_request`` case, but for writing.
446 similar meanings as those of the ``getattr_request`` case, but for writing.
447
447
448 Message type: ``setattr_reply``::
448 Message type: ``setattr_reply``::
449
449
450 content = {
450 content = {
451 # One of ['ok', 'AttributeError', 'AccessError'].
451 # One of ['ok', 'AttributeError', 'AccessError'].
452 'status' : str,
452 'status' : str,
453 }
453 }
454
454
455
455
456
456
457 Object information
457 Object information
458 ------------------
458 ------------------
459
459
460 One of IPython's most used capabilities is the introspection of Python objects
460 One of IPython's most used capabilities is the introspection of Python objects
461 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
461 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
462 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
462 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
463 enough that it warrants an explicit message type, especially because frontends
463 enough that it warrants an explicit message type, especially because frontends
464 may want to get object information in response to user keystrokes (like Tab or
464 may want to get object information in response to user keystrokes (like Tab or
465 F1) besides from the user explicitly typing code like ``x??``.
465 F1) besides from the user explicitly typing code like ``x??``.
466
466
467 Message type: ``object_info_request``::
467 Message type: ``object_info_request``::
468
468
469 content = {
469 content = {
470 # The (possibly dotted) name of the object to be searched in all
470 # The (possibly dotted) name of the object to be searched in all
471 # relevant namespaces
471 # relevant namespaces
472 'name' : str,
472 'name' : str,
473
473
474 # The level of detail desired. The default (0) is equivalent to typing
474 # The level of detail desired. The default (0) is equivalent to typing
475 # 'x?' at the prompt, 1 is equivalent to 'x??'.
475 # 'x?' at the prompt, 1 is equivalent to 'x??'.
476 'detail_level' : int,
476 'detail_level' : int,
477 }
477 }
478
478
479 The returned information will be a dictionary with keys very similar to the
479 The returned information will be a dictionary with keys very similar to the
480 field names that IPython prints at the terminal.
480 field names that IPython prints at the terminal.
481
481
482 Message type: ``object_info_reply``::
482 Message type: ``object_info_reply``::
483
483
484 content = {
484 content = {
485 # The name the object was requested under
485 # The name the object was requested under
486 'name' : str,
486 'name' : str,
487
487
488 # Boolean flag indicating whether the named object was found or not. If
488 # Boolean flag indicating whether the named object was found or not. If
489 # it's false, all other fields will be empty.
489 # it's false, all other fields will be empty.
490 'found' : bool,
490 'found' : bool,
491
491
492 # Flags for magics and system aliases
492 # Flags for magics and system aliases
493 'ismagic' : bool,
493 'ismagic' : bool,
494 'isalias' : bool,
494 'isalias' : bool,
495
495
496 # The name of the namespace where the object was found ('builtin',
496 # The name of the namespace where the object was found ('builtin',
497 # 'magics', 'alias', 'interactive', etc.)
497 # 'magics', 'alias', 'interactive', etc.)
498 'namespace' : str,
498 'namespace' : str,
499
499
500 # The type name will be type.__name__ for normal Python objects, but it
500 # The type name will be type.__name__ for normal Python objects, but it
501 # can also be a string like 'Magic function' or 'System alias'
501 # can also be a string like 'Magic function' or 'System alias'
502 'type_name' : str,
502 'type_name' : str,
503
503
504 # The string form of the object, possibly truncated for length if
504 # The string form of the object, possibly truncated for length if
505 # detail_level is 0
505 # detail_level is 0
506 'string_form' : str,
506 'string_form' : str,
507
507
508 # For objects with a __class__ attribute this will be set
508 # For objects with a __class__ attribute this will be set
509 'base_class' : str,
509 'base_class' : str,
510
510
511 # For objects with a __len__ attribute this will be set
511 # For objects with a __len__ attribute this will be set
512 'length' : int,
512 'length' : int,
513
513
514 # If the object is a function, class or method whose file we can find,
514 # If the object is a function, class or method whose file we can find,
515 # we give its full path
515 # we give its full path
516 'file' : str,
516 'file' : str,
517
517
518 # For pure Python callable objects, we can reconstruct the object
518 # For pure Python callable objects, we can reconstruct the object
519 # definition line which provides its call signature. For convenience this
519 # definition line which provides its call signature. For convenience this
520 # is returned as a single 'definition' field, but below the raw parts that
520 # is returned as a single 'definition' field, but below the raw parts that
521 # compose it are also returned as the argspec field.
521 # compose it are also returned as the argspec field.
522 'definition' : str,
522 'definition' : str,
523
523
524 # The individual parts that together form the definition string. Clients
524 # The individual parts that together form the definition string. Clients
525 # with rich display capabilities may use this to provide a richer and more
525 # with rich display capabilities may use this to provide a richer and more
526 # precise representation of the definition line (e.g. by highlighting
526 # precise representation of the definition line (e.g. by highlighting
527 # arguments based on the user's cursor position). For non-callable
527 # arguments based on the user's cursor position). For non-callable
528 # objects, this field is empty.
528 # objects, this field is empty.
529 'argspec' : { # The names of all the arguments
529 'argspec' : { # The names of all the arguments
530 args : list,
530 args : list,
531 # The name of the varargs (*args), if any
531 # The name of the varargs (*args), if any
532 varargs : str,
532 varargs : str,
533 # The name of the varkw (**kw), if any
533 # The name of the varkw (**kw), if any
534 varkw : str,
534 varkw : str,
535 # The values (as strings) of all default arguments. Note
535 # The values (as strings) of all default arguments. Note
536 # that these must be matched *in reverse* with the 'args'
536 # that these must be matched *in reverse* with the 'args'
537 # list above, since the first positional args have no default
537 # list above, since the first positional args have no default
538 # value at all.
538 # value at all.
539 defaults : list,
539 defaults : list,
540 },
540 },
541
541
542 # For instances, provide the constructor signature (the definition of
542 # For instances, provide the constructor signature (the definition of
543 # the __init__ method):
543 # the __init__ method):
544 'init_definition' : str,
544 'init_definition' : str,
545
545
546 # Docstrings: for any object (function, method, module, package) with a
546 # Docstrings: for any object (function, method, module, package) with a
547 # docstring, we show it. But in addition, we may provide additional
547 # docstring, we show it. But in addition, we may provide additional
548 # docstrings. For example, for instances we will show the constructor
548 # docstrings. For example, for instances we will show the constructor
549 # and class docstrings as well, if available.
549 # and class docstrings as well, if available.
550 'docstring' : str,
550 'docstring' : str,
551
551
552 # For instances, provide the constructor and class docstrings
552 # For instances, provide the constructor and class docstrings
553 'init_docstring' : str,
553 'init_docstring' : str,
554 'class_docstring' : str,
554 'class_docstring' : str,
555
555
556 # If it's a callable object whose call method has a separate docstring and
556 # If it's a callable object whose call method has a separate docstring and
557 # definition line:
557 # definition line:
558 'call_def' : str,
558 'call_def' : str,
559 'call_docstring' : str,
559 'call_docstring' : str,
560
560
561 # If detail_level was 1, we also try to find the source code that
561 # If detail_level was 1, we also try to find the source code that
562 # defines the object, if possible. The string 'None' will indicate
562 # defines the object, if possible. The string 'None' will indicate
563 # that no source was found.
563 # that no source was found.
564 'source' : str,
564 'source' : str,
565 }
565 }
566
566
567
567
568 Complete
568 Complete
569 --------
569 --------
570
570
571 Message type: ``complete_request``::
571 Message type: ``complete_request``::
572
572
573 content = {
573 content = {
574 # The text to be completed, such as 'a.is'
574 # The text to be completed, such as 'a.is'
575 'text' : str,
575 'text' : str,
576
576
577 # The full line, such as 'print a.is'. This allows completers to
577 # The full line, such as 'print a.is'. This allows completers to
578 # make decisions that may require information about more than just the
578 # make decisions that may require information about more than just the
579 # current word.
579 # current word.
580 'line' : str,
580 'line' : str,
581
581
582 # The entire block of text where the line is. This may be useful in the
582 # The entire block of text where the line is. This may be useful in the
583 # case of multiline completions where more context may be needed. Note: if
583 # case of multiline completions where more context may be needed. Note: if
584 # in practice this field proves unnecessary, remove it to lighten the
584 # in practice this field proves unnecessary, remove it to lighten the
585 # messages.
585 # messages.
586
586
587 'block' : str,
587 'block' : str,
588
588
589 # The position of the cursor where the user hit 'TAB' on the line.
589 # The position of the cursor where the user hit 'TAB' on the line.
590 'cursor_pos' : int,
590 'cursor_pos' : int,
591 }
591 }
592
592
593 Message type: ``complete_reply``::
593 Message type: ``complete_reply``::
594
594
595 content = {
595 content = {
596 # The list of all matches to the completion request, such as
596 # The list of all matches to the completion request, such as
597 # ['a.isalnum', 'a.isalpha'] for the above example.
597 # ['a.isalnum', 'a.isalpha'] for the above example.
598 'matches' : list
598 'matches' : list
599 }
599 }
600
600
601
601
602 History
602 History
603 -------
603 -------
604
604
605 For clients to explicitly request history from a kernel. The kernel has all
605 For clients to explicitly request history from a kernel. The kernel has all
606 the actual execution history stored in a single location, so clients can
606 the actual execution history stored in a single location, so clients can
607 request it from the kernel when needed.
607 request it from the kernel when needed.
608
608
609 Message type: ``history_request``::
609 Message type: ``history_request``::
610
610
611 content = {
611 content = {
612
612
613 # If True, also return output history in the resulting dict.
613 # If True, also return output history in the resulting dict.
614 'output' : bool,
614 'output' : bool,
615
615
616 # If True, return the raw input history, else the transformed input.
616 # If True, return the raw input history, else the transformed input.
617 'raw' : bool,
617 'raw' : bool,
618
618
619 # So far, this can be 'range', 'tail' or 'search'.
619 # So far, this can be 'range', 'tail' or 'search'.
620 'hist_access_type' : str,
620 'hist_access_type' : str,
621
621
622 # If hist_access_type is 'range', get a range of input cells. session can
622 # If hist_access_type is 'range', get a range of input cells. session can
623 # be a positive session number, or a negative number to count back from
623 # be a positive session number, or a negative number to count back from
624 # the current session.
624 # the current session.
625 'session' : int,
625 'session' : int,
626 # start and stop are line numbers within that session.
626 # start and stop are line numbers within that session.
627 'start' : int,
627 'start' : int,
628 'stop' : int,
628 'stop' : int,
629
629
630 # If hist_access_type is 'tail', get the last n cells.
630 # If hist_access_type is 'tail' or 'search', get the last n cells.
631 'n' : int,
631 'n' : int,
632
632
633 # If hist_access_type is 'search', get cells matching the specified glob
633 # If hist_access_type is 'search', get cells matching the specified glob
634 # pattern (with * and ? as wildcards).
634 # pattern (with * and ? as wildcards).
635 'pattern' : str,
635 'pattern' : str,
636
636
637 }
637 }
638
638
639 Message type: ``history_reply``::
639 Message type: ``history_reply``::
640
640
641 content = {
641 content = {
642 # A list of 3 tuples, either:
642 # A list of 3 tuples, either:
643 # (session, line_number, input) or
643 # (session, line_number, input) or
644 # (session, line_number, (input, output)),
644 # (session, line_number, (input, output)),
645 # depending on whether output was False or True, respectively.
645 # depending on whether output was False or True, respectively.
646 'history' : list,
646 'history' : list,
647 }
647 }
648
648
649
649
650 Connect
650 Connect
651 -------
651 -------
652
652
653 When a client connects to the request/reply socket of the kernel, it can issue
653 When a client connects to the request/reply socket of the kernel, it can issue
654 a connect request to get basic information about the kernel, such as the ports
654 a connect request to get basic information about the kernel, such as the ports
655 the other ZeroMQ sockets are listening on. This allows clients to only have
655 the other ZeroMQ sockets are listening on. This allows clients to only have
656 to know about a single port (the shell channel) to connect to a kernel.
656 to know about a single port (the shell channel) to connect to a kernel.
657
657
658 Message type: ``connect_request``::
658 Message type: ``connect_request``::
659
659
660 content = {
660 content = {
661 }
661 }
662
662
663 Message type: ``connect_reply``::
663 Message type: ``connect_reply``::
664
664
665 content = {
665 content = {
666 'shell_port' : int # The port the shell ROUTER socket is listening on.
666 'shell_port' : int # The port the shell ROUTER socket is listening on.
667 'iopub_port' : int # The port the PUB socket is listening on.
667 'iopub_port' : int # The port the PUB socket is listening on.
668 'stdin_port' : int # The port the stdin ROUTER socket is listening on.
668 'stdin_port' : int # The port the stdin ROUTER socket is listening on.
669 'hb_port' : int # The port the heartbeat socket is listening on.
669 'hb_port' : int # The port the heartbeat socket is listening on.
670 }
670 }
671
671
672
672
673
673
674 Kernel shutdown
674 Kernel shutdown
675 ---------------
675 ---------------
676
676
677 The clients can request the kernel to shut itself down; this is used in
677 The clients can request the kernel to shut itself down; this is used in
678 multiple cases:
678 multiple cases:
679
679
680 - when the user chooses to close the client application via a menu or window
680 - when the user chooses to close the client application via a menu or window
681 control.
681 control.
682 - when the user types 'exit' or 'quit' (or their uppercase magic equivalents).
682 - when the user types 'exit' or 'quit' (or their uppercase magic equivalents).
683 - when the user chooses a GUI method (like the 'Ctrl-C' shortcut in the
683 - when the user chooses a GUI method (like the 'Ctrl-C' shortcut in the
684 IPythonQt client) to force a kernel restart to get a clean kernel without
684 IPythonQt client) to force a kernel restart to get a clean kernel without
685 losing client-side state like history or inlined figures.
685 losing client-side state like history or inlined figures.
686
686
687 The client sends a shutdown request to the kernel, and once it receives the
687 The client sends a shutdown request to the kernel, and once it receives the
688 reply message (which is otherwise empty), it can assume that the kernel has
688 reply message (which is otherwise empty), it can assume that the kernel has
689 completed shutdown safely.
689 completed shutdown safely.
690
690
691 Upon their own shutdown, client applications will typically execute a last
691 Upon their own shutdown, client applications will typically execute a last
692 minute sanity check and forcefully terminate any kernel that is still alive, to
692 minute sanity check and forcefully terminate any kernel that is still alive, to
693 avoid leaving stray processes in the user's machine.
693 avoid leaving stray processes in the user's machine.
694
694
695 For both shutdown request and reply, there is no actual content that needs to
695 For both shutdown request and reply, there is no actual content that needs to
696 be sent, so the content dict is empty.
696 be sent, so the content dict is empty.
697
697
698 Message type: ``shutdown_request``::
698 Message type: ``shutdown_request``::
699
699
700 content = {
700 content = {
701 'restart' : bool # whether the shutdown is final, or precedes a restart
701 'restart' : bool # whether the shutdown is final, or precedes a restart
702 }
702 }
703
703
704 Message type: ``shutdown_reply``::
704 Message type: ``shutdown_reply``::
705
705
706 content = {
706 content = {
707 'restart' : bool # whether the shutdown is final, or precedes a restart
707 'restart' : bool # whether the shutdown is final, or precedes a restart
708 }
708 }
709
709
710 .. Note::
710 .. Note::
711
711
712 When the clients detect a dead kernel thanks to inactivity on the heartbeat
712 When the clients detect a dead kernel thanks to inactivity on the heartbeat
713 socket, they simply send a forceful process termination signal, since a dead
713 socket, they simply send a forceful process termination signal, since a dead
714 process is unlikely to respond in any useful way to messages.
714 process is unlikely to respond in any useful way to messages.
715
715
716
716
717 Messages on the PUB/SUB socket
717 Messages on the PUB/SUB socket
718 ==============================
718 ==============================
719
719
720 Streams (stdout, stderr, etc)
720 Streams (stdout, stderr, etc)
721 ------------------------------
721 ------------------------------
722
722
723 Message type: ``stream``::
723 Message type: ``stream``::
724
724
725 content = {
725 content = {
726 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
726 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
727 'name' : str,
727 'name' : str,
728
728
729 # The data is an arbitrary string to be written to that stream
729 # The data is an arbitrary string to be written to that stream
730 'data' : str,
730 'data' : str,
731 }
731 }
732
732
733 When a kernel receives a raw_input call, it should also broadcast it on the pub
733 When a kernel receives a raw_input call, it should also broadcast it on the pub
734 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
734 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
735 to monitor/display kernel interactions and possibly replay them to their user
735 to monitor/display kernel interactions and possibly replay them to their user
736 or otherwise expose them.
736 or otherwise expose them.
737
737
738 Display Data
738 Display Data
739 ------------
739 ------------
740
740
741 This type of message is used to bring back data that should be diplayed (text,
741 This type of message is used to bring back data that should be diplayed (text,
742 html, svg, etc.) in the frontends. This data is published to all frontends.
742 html, svg, etc.) in the frontends. This data is published to all frontends.
743 Each message can have multiple representations of the data; it is up to the
743 Each message can have multiple representations of the data; it is up to the
744 frontend to decide which to use and how. A single message should contain all
744 frontend to decide which to use and how. A single message should contain all
745 possible representations of the same information. Each representation should
745 possible representations of the same information. Each representation should
746 be a JSON'able data structure, and should be a valid MIME type.
746 be a JSON'able data structure, and should be a valid MIME type.
747
747
748 Some questions remain about this design:
748 Some questions remain about this design:
749
749
750 * Do we use this message type for pyout/displayhook? Probably not, because
750 * Do we use this message type for pyout/displayhook? Probably not, because
751 the displayhook also has to handle the Out prompt display. On the other hand
751 the displayhook also has to handle the Out prompt display. On the other hand
752 we could put that information into the metadata secion.
752 we could put that information into the metadata secion.
753
753
754 Message type: ``display_data``::
754 Message type: ``display_data``::
755
755
756 content = {
756 content = {
757
757
758 # Who create the data
758 # Who create the data
759 'source' : str,
759 'source' : str,
760
760
761 # The data dict contains key/value pairs, where the kids are MIME
761 # The data dict contains key/value pairs, where the kids are MIME
762 # types and the values are the raw data of the representation in that
762 # types and the values are the raw data of the representation in that
763 # format. The data dict must minimally contain the ``text/plain``
763 # format. The data dict must minimally contain the ``text/plain``
764 # MIME type which is used as a backup representation.
764 # MIME type which is used as a backup representation.
765 'data' : dict,
765 'data' : dict,
766
766
767 # Any metadata that describes the data
767 # Any metadata that describes the data
768 'metadata' : dict
768 'metadata' : dict
769 }
769 }
770
770
771
771
772 Raw Data Publication
772 Raw Data Publication
773 --------------------
773 --------------------
774
774
775 ``display_data`` lets you publish *representations* of data, such as images and html.
775 ``display_data`` lets you publish *representations* of data, such as images and html.
776 This ``data_pub`` message lets you publish *actual raw data*, sent via message buffers.
776 This ``data_pub`` message lets you publish *actual raw data*, sent via message buffers.
777
777
778 data_pub messages are constructed via the :func:`IPython.lib.datapub.publish_data` function:
778 data_pub messages are constructed via the :func:`IPython.lib.datapub.publish_data` function:
779
779
780 .. sourcecode:: python
780 .. sourcecode:: python
781
781
782 from IPython.zmq.datapub import publish_data
782 from IPython.zmq.datapub import publish_data
783 ns = dict(x=my_array)
783 ns = dict(x=my_array)
784 publish_data(ns)
784 publish_data(ns)
785
785
786
786
787 Message type: ``data_pub``::
787 Message type: ``data_pub``::
788
788
789 content = {
789 content = {
790 # the keys of the data dict, after it has been unserialized
790 # the keys of the data dict, after it has been unserialized
791 keys = ['a', 'b']
791 keys = ['a', 'b']
792 }
792 }
793 # the namespace dict will be serialized in the message buffers,
793 # the namespace dict will be serialized in the message buffers,
794 # which will have a length of at least one
794 # which will have a length of at least one
795 buffers = ['pdict', ...]
795 buffers = ['pdict', ...]
796
796
797
797
798 The interpretation of a sequence of data_pub messages for a given parent request should be
798 The interpretation of a sequence of data_pub messages for a given parent request should be
799 to update a single namespace with subsequent results.
799 to update a single namespace with subsequent results.
800
800
801 .. note::
801 .. note::
802
802
803 No frontends directly handle data_pub messages at this time.
803 No frontends directly handle data_pub messages at this time.
804 It is currently only used by the client/engines in :mod:`IPython.parallel`,
804 It is currently only used by the client/engines in :mod:`IPython.parallel`,
805 where engines may publish *data* to the Client,
805 where engines may publish *data* to the Client,
806 of which the Client can then publish *representations* via ``display_data``
806 of which the Client can then publish *representations* via ``display_data``
807 to various frontends.
807 to various frontends.
808
808
809 Python inputs
809 Python inputs
810 -------------
810 -------------
811
811
812 These messages are the re-broadcast of the ``execute_request``.
812 These messages are the re-broadcast of the ``execute_request``.
813
813
814 Message type: ``pyin``::
814 Message type: ``pyin``::
815
815
816 content = {
816 content = {
817 'code' : str, # Source code to be executed, one or more lines
817 'code' : str, # Source code to be executed, one or more lines
818
818
819 # The counter for this execution is also provided so that clients can
819 # The counter for this execution is also provided so that clients can
820 # display it, since IPython automatically creates variables called _iN
820 # display it, since IPython automatically creates variables called _iN
821 # (for input prompt In[N]).
821 # (for input prompt In[N]).
822 'execution_count' : int
822 'execution_count' : int
823 }
823 }
824
824
825 Python outputs
825 Python outputs
826 --------------
826 --------------
827
827
828 When Python produces output from code that has been compiled in with the
828 When Python produces output from code that has been compiled in with the
829 'single' flag to :func:`compile`, any expression that produces a value (such as
829 'single' flag to :func:`compile`, any expression that produces a value (such as
830 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
830 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
831 this value whatever it wants. The default behavior of ``sys.displayhook`` in
831 this value whatever it wants. The default behavior of ``sys.displayhook`` in
832 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
832 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
833 the value as long as it is not ``None`` (which isn't printed at all). In our
833 the value as long as it is not ``None`` (which isn't printed at all). In our
834 case, the kernel instantiates as ``sys.displayhook`` an object which has
834 case, the kernel instantiates as ``sys.displayhook`` an object which has
835 similar behavior, but which instead of printing to stdout, broadcasts these
835 similar behavior, but which instead of printing to stdout, broadcasts these
836 values as ``pyout`` messages for clients to display appropriately.
836 values as ``pyout`` messages for clients to display appropriately.
837
837
838 IPython's displayhook can handle multiple simultaneous formats depending on its
838 IPython's displayhook can handle multiple simultaneous formats depending on its
839 configuration. The default pretty-printed repr text is always given with the
839 configuration. The default pretty-printed repr text is always given with the
840 ``data`` entry in this message. Any other formats are provided in the
840 ``data`` entry in this message. Any other formats are provided in the
841 ``extra_formats`` list. Frontends are free to display any or all of these
841 ``extra_formats`` list. Frontends are free to display any or all of these
842 according to its capabilities. ``extra_formats`` list contains 3-tuples of an ID
842 according to its capabilities. ``extra_formats`` list contains 3-tuples of an ID
843 string, a type string, and the data. The ID is unique to the formatter
843 string, a type string, and the data. The ID is unique to the formatter
844 implementation that created the data. Frontends will typically ignore the ID
844 implementation that created the data. Frontends will typically ignore the ID
845 unless if it has requested a particular formatter. The type string tells the
845 unless if it has requested a particular formatter. The type string tells the
846 frontend how to interpret the data. It is often, but not always a MIME type.
846 frontend how to interpret the data. It is often, but not always a MIME type.
847 Frontends should ignore types that it does not understand. The data itself is
847 Frontends should ignore types that it does not understand. The data itself is
848 any JSON object and depends on the format. It is often, but not always a string.
848 any JSON object and depends on the format. It is often, but not always a string.
849
849
850 Message type: ``pyout``::
850 Message type: ``pyout``::
851
851
852 content = {
852 content = {
853
853
854 # The counter for this execution is also provided so that clients can
854 # The counter for this execution is also provided so that clients can
855 # display it, since IPython automatically creates variables called _N
855 # display it, since IPython automatically creates variables called _N
856 # (for prompt N).
856 # (for prompt N).
857 'execution_count' : int,
857 'execution_count' : int,
858
858
859 # The data dict contains key/value pairs, where the kids are MIME
859 # The data dict contains key/value pairs, where the kids are MIME
860 # types and the values are the raw data of the representation in that
860 # types and the values are the raw data of the representation in that
861 # format. The data dict must minimally contain the ``text/plain``
861 # format. The data dict must minimally contain the ``text/plain``
862 # MIME type which is used as a backup representation.
862 # MIME type which is used as a backup representation.
863 'data' : dict,
863 'data' : dict,
864
864
865 }
865 }
866
866
867 Python errors
867 Python errors
868 -------------
868 -------------
869
869
870 When an error occurs during code execution
870 When an error occurs during code execution
871
871
872 Message type: ``pyerr``::
872 Message type: ``pyerr``::
873
873
874 content = {
874 content = {
875 # Similar content to the execute_reply messages for the 'error' case,
875 # Similar content to the execute_reply messages for the 'error' case,
876 # except the 'status' field is omitted.
876 # except the 'status' field is omitted.
877 }
877 }
878
878
879 Kernel status
879 Kernel status
880 -------------
880 -------------
881
881
882 This message type is used by frontends to monitor the status of the kernel.
882 This message type is used by frontends to monitor the status of the kernel.
883
883
884 Message type: ``status``::
884 Message type: ``status``::
885
885
886 content = {
886 content = {
887 # When the kernel starts to execute code, it will enter the 'busy'
887 # When the kernel starts to execute code, it will enter the 'busy'
888 # state and when it finishes, it will enter the 'idle' state.
888 # state and when it finishes, it will enter the 'idle' state.
889 execution_state : ('busy', 'idle')
889 execution_state : ('busy', 'idle')
890 }
890 }
891
891
892 Kernel crashes
892 Kernel crashes
893 --------------
893 --------------
894
894
895 When the kernel has an unexpected exception, caught by the last-resort
895 When the kernel has an unexpected exception, caught by the last-resort
896 sys.excepthook, we should broadcast the crash handler's output before exiting.
896 sys.excepthook, we should broadcast the crash handler's output before exiting.
897 This will allow clients to notice that a kernel died, inform the user and
897 This will allow clients to notice that a kernel died, inform the user and
898 propose further actions.
898 propose further actions.
899
899
900 Message type: ``crash``::
900 Message type: ``crash``::
901
901
902 content = {
902 content = {
903 # Similarly to the 'error' case for execute_reply messages, this will
903 # Similarly to the 'error' case for execute_reply messages, this will
904 # contain ename, etype and traceback fields.
904 # contain ename, etype and traceback fields.
905
905
906 # An additional field with supplementary information such as where to
906 # An additional field with supplementary information such as where to
907 # send the crash message
907 # send the crash message
908 'info' : str,
908 'info' : str,
909 }
909 }
910
910
911
911
912 Future ideas
912 Future ideas
913 ------------
913 ------------
914
914
915 Other potential message types, currently unimplemented, listed below as ideas.
915 Other potential message types, currently unimplemented, listed below as ideas.
916
916
917 Message type: ``file``::
917 Message type: ``file``::
918
918
919 content = {
919 content = {
920 'path' : 'cool.jpg',
920 'path' : 'cool.jpg',
921 'mimetype' : str,
921 'mimetype' : str,
922 'data' : str,
922 'data' : str,
923 }
923 }
924
924
925
925
926 Messages on the stdin ROUTER/DEALER sockets
926 Messages on the stdin ROUTER/DEALER sockets
927 ===========================================
927 ===========================================
928
928
929 This is a socket where the request/reply pattern goes in the opposite direction:
929 This is a socket where the request/reply pattern goes in the opposite direction:
930 from the kernel to a *single* frontend, and its purpose is to allow
930 from the kernel to a *single* frontend, and its purpose is to allow
931 ``raw_input`` and similar operations that read from ``sys.stdin`` on the kernel
931 ``raw_input`` and similar operations that read from ``sys.stdin`` on the kernel
932 to be fulfilled by the client. The request should be made to the frontend that
932 to be fulfilled by the client. The request should be made to the frontend that
933 made the execution request that prompted ``raw_input`` to be called. For now we
933 made the execution request that prompted ``raw_input`` to be called. For now we
934 will keep these messages as simple as possible, since they only mean to convey
934 will keep these messages as simple as possible, since they only mean to convey
935 the ``raw_input(prompt)`` call.
935 the ``raw_input(prompt)`` call.
936
936
937 Message type: ``input_request``::
937 Message type: ``input_request``::
938
938
939 content = { 'prompt' : str }
939 content = { 'prompt' : str }
940
940
941 Message type: ``input_reply``::
941 Message type: ``input_reply``::
942
942
943 content = { 'value' : str }
943 content = { 'value' : str }
944
944
945 .. Note::
945 .. Note::
946
946
947 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
947 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
948 practice the kernel should behave like an interactive program. When a
948 practice the kernel should behave like an interactive program. When a
949 program is opened on the console, the keyboard effectively takes over the
949 program is opened on the console, the keyboard effectively takes over the
950 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
950 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
951 Since the IPython kernel effectively behaves like a console program (albeit
951 Since the IPython kernel effectively behaves like a console program (albeit
952 one whose "keyboard" is actually living in a separate process and
952 one whose "keyboard" is actually living in a separate process and
953 transported over the zmq connection), raw ``stdin`` isn't expected to be
953 transported over the zmq connection), raw ``stdin`` isn't expected to be
954 available.
954 available.
955
955
956
956
957 Heartbeat for kernels
957 Heartbeat for kernels
958 =====================
958 =====================
959
959
960 Initially we had considered using messages like those above over ZMQ for a
960 Initially we had considered using messages like those above over ZMQ for a
961 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
961 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
962 alive at all, even if it may be busy executing user code). But this has the
962 alive at all, even if it may be busy executing user code). But this has the
963 problem that if the kernel is locked inside extension code, it wouldn't execute
963 problem that if the kernel is locked inside extension code, it wouldn't execute
964 the python heartbeat code. But it turns out that we can implement a basic
964 the python heartbeat code. But it turns out that we can implement a basic
965 heartbeat with pure ZMQ, without using any Python messaging at all.
965 heartbeat with pure ZMQ, without using any Python messaging at all.
966
966
967 The monitor sends out a single zmq message (right now, it is a str of the
967 The monitor sends out a single zmq message (right now, it is a str of the
968 monitor's lifetime in seconds), and gets the same message right back, prefixed
968 monitor's lifetime in seconds), and gets the same message right back, prefixed
969 with the zmq identity of the DEALER socket in the heartbeat process. This can be
969 with the zmq identity of the DEALER socket in the heartbeat process. This can be
970 a uuid, or even a full message, but there doesn't seem to be a need for packing
970 a uuid, or even a full message, but there doesn't seem to be a need for packing
971 up a message when the sender and receiver are the exact same Python object.
971 up a message when the sender and receiver are the exact same Python object.
972
972
973 The model is this::
973 The model is this::
974
974
975 monitor.send(str(self.lifetime)) # '1.2345678910'
975 monitor.send(str(self.lifetime)) # '1.2345678910'
976
976
977 and the monitor receives some number of messages of the form::
977 and the monitor receives some number of messages of the form::
978
978
979 ['uuid-abcd-dead-beef', '1.2345678910']
979 ['uuid-abcd-dead-beef', '1.2345678910']
980
980
981 where the first part is the zmq.IDENTITY of the heart's DEALER on the engine, and
981 where the first part is the zmq.IDENTITY of the heart's DEALER on the engine, and
982 the rest is the message sent by the monitor. No Python code ever has any
982 the rest is the message sent by the monitor. No Python code ever has any
983 access to the message between the monitor's send, and the monitor's recv.
983 access to the message between the monitor's send, and the monitor's recv.
984
984
985
985
986 ToDo
986 ToDo
987 ====
987 ====
988
988
989 Missing things include:
989 Missing things include:
990
990
991 * Important: finish thinking through the payload concept and API.
991 * Important: finish thinking through the payload concept and API.
992
992
993 * Important: ensure that we have a good solution for magics like %edit. It's
993 * Important: ensure that we have a good solution for magics like %edit. It's
994 likely that with the payload concept we can build a full solution, but not
994 likely that with the payload concept we can build a full solution, but not
995 100% clear yet.
995 100% clear yet.
996
996
997 * Finishing the details of the heartbeat protocol.
997 * Finishing the details of the heartbeat protocol.
998
998
999 * Signal handling: specify what kind of information kernel should broadcast (or
999 * Signal handling: specify what kind of information kernel should broadcast (or
1000 not) when it receives signals.
1000 not) when it receives signals.
1001
1001
1002 .. include:: ../links.rst
1002 .. include:: ../links.rst
General Comments 0
You need to be logged in to leave comments. Login now