##// END OF EJS Templates
Fix import of pylabtools that I missed yesterday.
Fernando Perez -
Show More
@@ -1,635 +1,635 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
25
26 # System library imports.
26 # System library imports.
27 import zmq
27 import zmq
28
28
29 # Local imports.
29 # Local imports.
30 from IPython.core import pylabtools
30 from IPython.config.configurable import Configurable
31 from IPython.config.configurable import Configurable
31 from IPython.config.application import boolean_flag, catch_config_error
32 from IPython.config.application import boolean_flag, catch_config_error
32 from IPython.core.application import ProfileDir
33 from IPython.core.application import ProfileDir
33 from IPython.core.error import StdinNotImplementedError
34 from IPython.core.error import StdinNotImplementedError
34 from IPython.core.shellapp import (
35 from IPython.core.shellapp import (
35 InteractiveShellApp, shell_flags, shell_aliases
36 InteractiveShellApp, shell_flags, shell_aliases
36 )
37 )
37 from IPython.utils import io
38 from IPython.utils import io
38 from IPython.utils import py3compat
39 from IPython.utils import py3compat
39 from IPython.utils.jsonutil import json_clean
40 from IPython.utils.jsonutil import json_clean
40 from IPython.lib import pylabtools
41 from IPython.utils.traitlets import (
41 from IPython.utils.traitlets import (
42 Any, Instance, Float, Dict, CaselessStrEnum
42 Any, Instance, Float, Dict, CaselessStrEnum
43 )
43 )
44
44
45 from entry_point import base_launch_kernel
45 from entry_point import base_launch_kernel
46 from kernelapp import KernelApp, kernel_flags, kernel_aliases
46 from kernelapp import KernelApp, kernel_flags, kernel_aliases
47 from session import Session, Message
47 from session import Session, Message
48 from zmqshell import ZMQInteractiveShell
48 from zmqshell import ZMQInteractiveShell
49
49
50
50
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52 # Main kernel class
52 # Main kernel class
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54
54
55 class Kernel(Configurable):
55 class Kernel(Configurable):
56
56
57 #---------------------------------------------------------------------------
57 #---------------------------------------------------------------------------
58 # Kernel interface
58 # Kernel interface
59 #---------------------------------------------------------------------------
59 #---------------------------------------------------------------------------
60
60
61 # attribute to override with a GUI
61 # attribute to override with a GUI
62 eventloop = Any(None)
62 eventloop = Any(None)
63
63
64 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
64 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
65 session = Instance(Session)
65 session = Instance(Session)
66 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
66 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
67 shell_socket = Instance('zmq.Socket')
67 shell_socket = Instance('zmq.Socket')
68 iopub_socket = Instance('zmq.Socket')
68 iopub_socket = Instance('zmq.Socket')
69 stdin_socket = Instance('zmq.Socket')
69 stdin_socket = Instance('zmq.Socket')
70 log = Instance(logging.Logger)
70 log = Instance(logging.Logger)
71
71
72 # Private interface
72 # Private interface
73
73
74 # Time to sleep after flushing the stdout/err buffers in each execute
74 # Time to sleep after flushing the stdout/err buffers in each execute
75 # cycle. While this introduces a hard limit on the minimal latency of the
75 # cycle. While this introduces a hard limit on the minimal latency of the
76 # execute cycle, it helps prevent output synchronization problems for
76 # execute cycle, it helps prevent output synchronization problems for
77 # clients.
77 # clients.
78 # Units are in seconds. The minimum zmq latency on local host is probably
78 # Units are in seconds. The minimum zmq latency on local host is probably
79 # ~150 microseconds, set this to 500us for now. We may need to increase it
79 # ~150 microseconds, set this to 500us for now. We may need to increase it
80 # a little if it's not enough after more interactive testing.
80 # a little if it's not enough after more interactive testing.
81 _execute_sleep = Float(0.0005, config=True)
81 _execute_sleep = Float(0.0005, config=True)
82
82
83 # Frequency of the kernel's event loop.
83 # Frequency of the kernel's event loop.
84 # Units are in seconds, kernel subclasses for GUI toolkits may need to
84 # Units are in seconds, kernel subclasses for GUI toolkits may need to
85 # adapt to milliseconds.
85 # adapt to milliseconds.
86 _poll_interval = Float(0.05, config=True)
86 _poll_interval = Float(0.05, config=True)
87
87
88 # If the shutdown was requested over the network, we leave here the
88 # If the shutdown was requested over the network, we leave here the
89 # necessary reply message so it can be sent by our registered atexit
89 # necessary reply message so it can be sent by our registered atexit
90 # handler. This ensures that the reply is only sent to clients truly at
90 # handler. This ensures that the reply is only sent to clients truly at
91 # the end of our shutdown process (which happens after the underlying
91 # the end of our shutdown process (which happens after the underlying
92 # IPython shell's own shutdown).
92 # IPython shell's own shutdown).
93 _shutdown_message = None
93 _shutdown_message = None
94
94
95 # This is a dict of port number that the kernel is listening on. It is set
95 # This is a dict of port number that the kernel is listening on. It is set
96 # by record_ports and used by connect_request.
96 # by record_ports and used by connect_request.
97 _recorded_ports = Dict()
97 _recorded_ports = Dict()
98
98
99
99
100
100
101 def __init__(self, **kwargs):
101 def __init__(self, **kwargs):
102 super(Kernel, self).__init__(**kwargs)
102 super(Kernel, self).__init__(**kwargs)
103
103
104 # Before we even start up the shell, register *first* our exit handlers
104 # Before we even start up the shell, register *first* our exit handlers
105 # so they come before the shell's
105 # so they come before the shell's
106 atexit.register(self._at_shutdown)
106 atexit.register(self._at_shutdown)
107
107
108 # Initialize the InteractiveShell subclass
108 # Initialize the InteractiveShell subclass
109 self.shell = ZMQInteractiveShell.instance(config=self.config,
109 self.shell = ZMQInteractiveShell.instance(config=self.config,
110 profile_dir = self.profile_dir,
110 profile_dir = self.profile_dir,
111 )
111 )
112 self.shell.displayhook.session = self.session
112 self.shell.displayhook.session = self.session
113 self.shell.displayhook.pub_socket = self.iopub_socket
113 self.shell.displayhook.pub_socket = self.iopub_socket
114 self.shell.display_pub.session = self.session
114 self.shell.display_pub.session = self.session
115 self.shell.display_pub.pub_socket = self.iopub_socket
115 self.shell.display_pub.pub_socket = self.iopub_socket
116
116
117 # TMP - hack while developing
117 # TMP - hack while developing
118 self.shell._reply_content = None
118 self.shell._reply_content = None
119
119
120 # Build dict of handlers for message types
120 # Build dict of handlers for message types
121 msg_types = [ 'execute_request', 'complete_request',
121 msg_types = [ 'execute_request', 'complete_request',
122 'object_info_request', 'history_request',
122 'object_info_request', 'history_request',
123 'connect_request', 'shutdown_request']
123 'connect_request', 'shutdown_request']
124 self.handlers = {}
124 self.handlers = {}
125 for msg_type in msg_types:
125 for msg_type in msg_types:
126 self.handlers[msg_type] = getattr(self, msg_type)
126 self.handlers[msg_type] = getattr(self, msg_type)
127
127
128 def do_one_iteration(self):
128 def do_one_iteration(self):
129 """Do one iteration of the kernel's evaluation loop.
129 """Do one iteration of the kernel's evaluation loop.
130 """
130 """
131 try:
131 try:
132 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
132 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
133 except Exception:
133 except Exception:
134 self.log.warn("Invalid Message:", exc_info=True)
134 self.log.warn("Invalid Message:", exc_info=True)
135 return
135 return
136 if msg is None:
136 if msg is None:
137 return
137 return
138
138
139 msg_type = msg['header']['msg_type']
139 msg_type = msg['header']['msg_type']
140
140
141 # This assert will raise in versions of zeromq 2.0.7 and lesser.
141 # This assert will raise in versions of zeromq 2.0.7 and lesser.
142 # We now require 2.0.8 or above, so we can uncomment for safety.
142 # We now require 2.0.8 or above, so we can uncomment for safety.
143 # print(ident,msg, file=sys.__stdout__)
143 # print(ident,msg, file=sys.__stdout__)
144 assert ident is not None, "Missing message part."
144 assert ident is not None, "Missing message part."
145
145
146 # Print some info about this message and leave a '--->' marker, so it's
146 # Print some info about this message and leave a '--->' marker, so it's
147 # easier to trace visually the message chain when debugging. Each
147 # easier to trace visually the message chain when debugging. Each
148 # handler prints its message at the end.
148 # handler prints its message at the end.
149 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
149 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
150 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
150 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
151
151
152 # Find and call actual handler for message
152 # Find and call actual handler for message
153 handler = self.handlers.get(msg_type, None)
153 handler = self.handlers.get(msg_type, None)
154 if handler is None:
154 if handler is None:
155 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
155 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
156 else:
156 else:
157 handler(ident, msg)
157 handler(ident, msg)
158
158
159 # Check whether we should exit, in case the incoming message set the
159 # Check whether we should exit, in case the incoming message set the
160 # exit flag on
160 # exit flag on
161 if self.shell.exit_now:
161 if self.shell.exit_now:
162 self.log.debug('\nExiting IPython kernel...')
162 self.log.debug('\nExiting IPython kernel...')
163 # We do a normal, clean exit, which allows any actions registered
163 # We do a normal, clean exit, which allows any actions registered
164 # via atexit (such as history saving) to take place.
164 # via atexit (such as history saving) to take place.
165 sys.exit(0)
165 sys.exit(0)
166
166
167
167
168 def start(self):
168 def start(self):
169 """ Start the kernel main loop.
169 """ Start the kernel main loop.
170 """
170 """
171 poller = zmq.Poller()
171 poller = zmq.Poller()
172 poller.register(self.shell_socket, zmq.POLLIN)
172 poller.register(self.shell_socket, zmq.POLLIN)
173 # loop while self.eventloop has not been overridden
173 # loop while self.eventloop has not been overridden
174 while self.eventloop is None:
174 while self.eventloop is None:
175 try:
175 try:
176 # scale by extra factor of 10, because there is no
176 # scale by extra factor of 10, because there is no
177 # reason for this to be anything less than ~ 0.1s
177 # reason for this to be anything less than ~ 0.1s
178 # since it is a real poller and will respond
178 # since it is a real poller and will respond
179 # to events immediately
179 # to events immediately
180
180
181 # double nested try/except, to properly catch KeyboardInterrupt
181 # double nested try/except, to properly catch KeyboardInterrupt
182 # due to pyzmq Issue #130
182 # due to pyzmq Issue #130
183 try:
183 try:
184 poller.poll(10*1000*self._poll_interval)
184 poller.poll(10*1000*self._poll_interval)
185 self.do_one_iteration()
185 self.do_one_iteration()
186 except:
186 except:
187 raise
187 raise
188 except KeyboardInterrupt:
188 except KeyboardInterrupt:
189 # Ctrl-C shouldn't crash the kernel
189 # Ctrl-C shouldn't crash the kernel
190 io.raw_print("KeyboardInterrupt caught in kernel")
190 io.raw_print("KeyboardInterrupt caught in kernel")
191 if self.eventloop is not None:
191 if self.eventloop is not None:
192 try:
192 try:
193 self.eventloop(self)
193 self.eventloop(self)
194 except KeyboardInterrupt:
194 except KeyboardInterrupt:
195 # Ctrl-C shouldn't crash the kernel
195 # Ctrl-C shouldn't crash the kernel
196 io.raw_print("KeyboardInterrupt caught in kernel")
196 io.raw_print("KeyboardInterrupt caught in kernel")
197
197
198
198
199 def record_ports(self, ports):
199 def record_ports(self, ports):
200 """Record the ports that this kernel is using.
200 """Record the ports that this kernel is using.
201
201
202 The creator of the Kernel instance must call this methods if they
202 The creator of the Kernel instance must call this methods if they
203 want the :meth:`connect_request` method to return the port numbers.
203 want the :meth:`connect_request` method to return the port numbers.
204 """
204 """
205 self._recorded_ports = ports
205 self._recorded_ports = ports
206
206
207 #---------------------------------------------------------------------------
207 #---------------------------------------------------------------------------
208 # Kernel request handlers
208 # Kernel request handlers
209 #---------------------------------------------------------------------------
209 #---------------------------------------------------------------------------
210
210
211 def _publish_pyin(self, code, parent):
211 def _publish_pyin(self, code, parent):
212 """Publish the code request on the pyin stream."""
212 """Publish the code request on the pyin stream."""
213
213
214 self.session.send(self.iopub_socket, u'pyin', {u'code':code},
214 self.session.send(self.iopub_socket, u'pyin', {u'code':code},
215 parent=parent)
215 parent=parent)
216
216
217 def execute_request(self, ident, parent):
217 def execute_request(self, ident, parent):
218
218
219 self.session.send(self.iopub_socket,
219 self.session.send(self.iopub_socket,
220 u'status',
220 u'status',
221 {u'execution_state':u'busy'},
221 {u'execution_state':u'busy'},
222 parent=parent )
222 parent=parent )
223
223
224 try:
224 try:
225 content = parent[u'content']
225 content = parent[u'content']
226 code = content[u'code']
226 code = content[u'code']
227 silent = content[u'silent']
227 silent = content[u'silent']
228 except:
228 except:
229 self.log.error("Got bad msg: ")
229 self.log.error("Got bad msg: ")
230 self.log.error(str(Message(parent)))
230 self.log.error(str(Message(parent)))
231 return
231 return
232
232
233 shell = self.shell # we'll need this a lot here
233 shell = self.shell # we'll need this a lot here
234
234
235 # Replace raw_input. Note that is not sufficient to replace
235 # Replace raw_input. Note that is not sufficient to replace
236 # raw_input in the user namespace.
236 # raw_input in the user namespace.
237 if content.get('allow_stdin', False):
237 if content.get('allow_stdin', False):
238 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
238 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
239 else:
239 else:
240 raw_input = lambda prompt='' : self._no_raw_input()
240 raw_input = lambda prompt='' : self._no_raw_input()
241
241
242 if py3compat.PY3:
242 if py3compat.PY3:
243 __builtin__.input = raw_input
243 __builtin__.input = raw_input
244 else:
244 else:
245 __builtin__.raw_input = raw_input
245 __builtin__.raw_input = raw_input
246
246
247 # Set the parent message of the display hook and out streams.
247 # Set the parent message of the display hook and out streams.
248 shell.displayhook.set_parent(parent)
248 shell.displayhook.set_parent(parent)
249 shell.display_pub.set_parent(parent)
249 shell.display_pub.set_parent(parent)
250 sys.stdout.set_parent(parent)
250 sys.stdout.set_parent(parent)
251 sys.stderr.set_parent(parent)
251 sys.stderr.set_parent(parent)
252
252
253 # Re-broadcast our input for the benefit of listening clients, and
253 # Re-broadcast our input for the benefit of listening clients, and
254 # start computing output
254 # start computing output
255 if not silent:
255 if not silent:
256 self._publish_pyin(code, parent)
256 self._publish_pyin(code, parent)
257
257
258 reply_content = {}
258 reply_content = {}
259 try:
259 try:
260 if silent:
260 if silent:
261 # run_code uses 'exec' mode, so no displayhook will fire, and it
261 # run_code uses 'exec' mode, so no displayhook will fire, and it
262 # doesn't call logging or history manipulations. Print
262 # doesn't call logging or history manipulations. Print
263 # statements in that code will obviously still execute.
263 # statements in that code will obviously still execute.
264 shell.run_code(code)
264 shell.run_code(code)
265 else:
265 else:
266 # FIXME: the shell calls the exception handler itself.
266 # FIXME: the shell calls the exception handler itself.
267 shell.run_cell(code, store_history=True)
267 shell.run_cell(code, store_history=True)
268 except:
268 except:
269 status = u'error'
269 status = u'error'
270 # FIXME: this code right now isn't being used yet by default,
270 # FIXME: this code right now isn't being used yet by default,
271 # because the run_cell() call above directly fires off exception
271 # because the run_cell() call above directly fires off exception
272 # reporting. This code, therefore, is only active in the scenario
272 # reporting. This code, therefore, is only active in the scenario
273 # where runlines itself has an unhandled exception. We need to
273 # where runlines itself has an unhandled exception. We need to
274 # uniformize this, for all exception construction to come from a
274 # uniformize this, for all exception construction to come from a
275 # single location in the codbase.
275 # single location in the codbase.
276 etype, evalue, tb = sys.exc_info()
276 etype, evalue, tb = sys.exc_info()
277 tb_list = traceback.format_exception(etype, evalue, tb)
277 tb_list = traceback.format_exception(etype, evalue, tb)
278 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
278 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
279 else:
279 else:
280 status = u'ok'
280 status = u'ok'
281
281
282 reply_content[u'status'] = status
282 reply_content[u'status'] = status
283
283
284 # Return the execution counter so clients can display prompts
284 # Return the execution counter so clients can display prompts
285 reply_content['execution_count'] = shell.execution_count -1
285 reply_content['execution_count'] = shell.execution_count -1
286
286
287 # FIXME - fish exception info out of shell, possibly left there by
287 # FIXME - fish exception info out of shell, possibly left there by
288 # runlines. We'll need to clean up this logic later.
288 # runlines. We'll need to clean up this logic later.
289 if shell._reply_content is not None:
289 if shell._reply_content is not None:
290 reply_content.update(shell._reply_content)
290 reply_content.update(shell._reply_content)
291 # reset after use
291 # reset after use
292 shell._reply_content = None
292 shell._reply_content = None
293
293
294 # At this point, we can tell whether the main code execution succeeded
294 # At this point, we can tell whether the main code execution succeeded
295 # or not. If it did, we proceed to evaluate user_variables/expressions
295 # or not. If it did, we proceed to evaluate user_variables/expressions
296 if reply_content['status'] == 'ok':
296 if reply_content['status'] == 'ok':
297 reply_content[u'user_variables'] = \
297 reply_content[u'user_variables'] = \
298 shell.user_variables(content[u'user_variables'])
298 shell.user_variables(content[u'user_variables'])
299 reply_content[u'user_expressions'] = \
299 reply_content[u'user_expressions'] = \
300 shell.user_expressions(content[u'user_expressions'])
300 shell.user_expressions(content[u'user_expressions'])
301 else:
301 else:
302 # If there was an error, don't even try to compute variables or
302 # If there was an error, don't even try to compute variables or
303 # expressions
303 # expressions
304 reply_content[u'user_variables'] = {}
304 reply_content[u'user_variables'] = {}
305 reply_content[u'user_expressions'] = {}
305 reply_content[u'user_expressions'] = {}
306
306
307 # Payloads should be retrieved regardless of outcome, so we can both
307 # Payloads should be retrieved regardless of outcome, so we can both
308 # recover partial output (that could have been generated early in a
308 # recover partial output (that could have been generated early in a
309 # block, before an error) and clear the payload system always.
309 # block, before an error) and clear the payload system always.
310 reply_content[u'payload'] = shell.payload_manager.read_payload()
310 reply_content[u'payload'] = shell.payload_manager.read_payload()
311 # Be agressive about clearing the payload because we don't want
311 # Be agressive about clearing the payload because we don't want
312 # it to sit in memory until the next execute_request comes in.
312 # it to sit in memory until the next execute_request comes in.
313 shell.payload_manager.clear_payload()
313 shell.payload_manager.clear_payload()
314
314
315 # Flush output before sending the reply.
315 # Flush output before sending the reply.
316 sys.stdout.flush()
316 sys.stdout.flush()
317 sys.stderr.flush()
317 sys.stderr.flush()
318 # FIXME: on rare occasions, the flush doesn't seem to make it to the
318 # FIXME: on rare occasions, the flush doesn't seem to make it to the
319 # clients... This seems to mitigate the problem, but we definitely need
319 # clients... This seems to mitigate the problem, but we definitely need
320 # to better understand what's going on.
320 # to better understand what's going on.
321 if self._execute_sleep:
321 if self._execute_sleep:
322 time.sleep(self._execute_sleep)
322 time.sleep(self._execute_sleep)
323
323
324 # Send the reply.
324 # Send the reply.
325 reply_content = json_clean(reply_content)
325 reply_content = json_clean(reply_content)
326 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
326 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
327 reply_content, parent, ident=ident)
327 reply_content, parent, ident=ident)
328 self.log.debug(str(reply_msg))
328 self.log.debug(str(reply_msg))
329
329
330 if reply_msg['content']['status'] == u'error':
330 if reply_msg['content']['status'] == u'error':
331 self._abort_queue()
331 self._abort_queue()
332
332
333 self.session.send(self.iopub_socket,
333 self.session.send(self.iopub_socket,
334 u'status',
334 u'status',
335 {u'execution_state':u'idle'},
335 {u'execution_state':u'idle'},
336 parent=parent )
336 parent=parent )
337
337
338 def complete_request(self, ident, parent):
338 def complete_request(self, ident, parent):
339 txt, matches = self._complete(parent)
339 txt, matches = self._complete(parent)
340 matches = {'matches' : matches,
340 matches = {'matches' : matches,
341 'matched_text' : txt,
341 'matched_text' : txt,
342 'status' : 'ok'}
342 'status' : 'ok'}
343 matches = json_clean(matches)
343 matches = json_clean(matches)
344 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
344 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
345 matches, parent, ident)
345 matches, parent, ident)
346 self.log.debug(str(completion_msg))
346 self.log.debug(str(completion_msg))
347
347
348 def object_info_request(self, ident, parent):
348 def object_info_request(self, ident, parent):
349 object_info = self.shell.object_inspect(parent['content']['oname'])
349 object_info = self.shell.object_inspect(parent['content']['oname'])
350 # Before we send this object over, we scrub it for JSON usage
350 # Before we send this object over, we scrub it for JSON usage
351 oinfo = json_clean(object_info)
351 oinfo = json_clean(object_info)
352 msg = self.session.send(self.shell_socket, 'object_info_reply',
352 msg = self.session.send(self.shell_socket, 'object_info_reply',
353 oinfo, parent, ident)
353 oinfo, parent, ident)
354 self.log.debug(msg)
354 self.log.debug(msg)
355
355
356 def history_request(self, ident, parent):
356 def history_request(self, ident, parent):
357 # We need to pull these out, as passing **kwargs doesn't work with
357 # We need to pull these out, as passing **kwargs doesn't work with
358 # unicode keys before Python 2.6.5.
358 # unicode keys before Python 2.6.5.
359 hist_access_type = parent['content']['hist_access_type']
359 hist_access_type = parent['content']['hist_access_type']
360 raw = parent['content']['raw']
360 raw = parent['content']['raw']
361 output = parent['content']['output']
361 output = parent['content']['output']
362 if hist_access_type == 'tail':
362 if hist_access_type == 'tail':
363 n = parent['content']['n']
363 n = parent['content']['n']
364 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
364 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
365 include_latest=True)
365 include_latest=True)
366
366
367 elif hist_access_type == 'range':
367 elif hist_access_type == 'range':
368 session = parent['content']['session']
368 session = parent['content']['session']
369 start = parent['content']['start']
369 start = parent['content']['start']
370 stop = parent['content']['stop']
370 stop = parent['content']['stop']
371 hist = self.shell.history_manager.get_range(session, start, stop,
371 hist = self.shell.history_manager.get_range(session, start, stop,
372 raw=raw, output=output)
372 raw=raw, output=output)
373
373
374 elif hist_access_type == 'search':
374 elif hist_access_type == 'search':
375 pattern = parent['content']['pattern']
375 pattern = parent['content']['pattern']
376 hist = self.shell.history_manager.search(pattern, raw=raw,
376 hist = self.shell.history_manager.search(pattern, raw=raw,
377 output=output)
377 output=output)
378
378
379 else:
379 else:
380 hist = []
380 hist = []
381 content = {'history' : list(hist)}
381 content = {'history' : list(hist)}
382 content = json_clean(content)
382 content = json_clean(content)
383 msg = self.session.send(self.shell_socket, 'history_reply',
383 msg = self.session.send(self.shell_socket, 'history_reply',
384 content, parent, ident)
384 content, parent, ident)
385 self.log.debug(str(msg))
385 self.log.debug(str(msg))
386
386
387 def connect_request(self, ident, parent):
387 def connect_request(self, ident, parent):
388 if self._recorded_ports is not None:
388 if self._recorded_ports is not None:
389 content = self._recorded_ports.copy()
389 content = self._recorded_ports.copy()
390 else:
390 else:
391 content = {}
391 content = {}
392 msg = self.session.send(self.shell_socket, 'connect_reply',
392 msg = self.session.send(self.shell_socket, 'connect_reply',
393 content, parent, ident)
393 content, parent, ident)
394 self.log.debug(msg)
394 self.log.debug(msg)
395
395
396 def shutdown_request(self, ident, parent):
396 def shutdown_request(self, ident, parent):
397 self.shell.exit_now = True
397 self.shell.exit_now = True
398 self._shutdown_message = self.session.msg(u'shutdown_reply',
398 self._shutdown_message = self.session.msg(u'shutdown_reply',
399 parent['content'], parent)
399 parent['content'], parent)
400 sys.exit(0)
400 sys.exit(0)
401
401
402 #---------------------------------------------------------------------------
402 #---------------------------------------------------------------------------
403 # Protected interface
403 # Protected interface
404 #---------------------------------------------------------------------------
404 #---------------------------------------------------------------------------
405
405
406 def _abort_queue(self):
406 def _abort_queue(self):
407 while True:
407 while True:
408 try:
408 try:
409 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
409 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
410 except Exception:
410 except Exception:
411 self.log.warn("Invalid Message:", exc_info=True)
411 self.log.warn("Invalid Message:", exc_info=True)
412 continue
412 continue
413 if msg is None:
413 if msg is None:
414 break
414 break
415 else:
415 else:
416 assert ident is not None, \
416 assert ident is not None, \
417 "Unexpected missing message part."
417 "Unexpected missing message part."
418
418
419 self.log.debug("Aborting:\n"+str(Message(msg)))
419 self.log.debug("Aborting:\n"+str(Message(msg)))
420 msg_type = msg['header']['msg_type']
420 msg_type = msg['header']['msg_type']
421 reply_type = msg_type.split('_')[0] + '_reply'
421 reply_type = msg_type.split('_')[0] + '_reply'
422 reply_msg = self.session.send(self.shell_socket, reply_type,
422 reply_msg = self.session.send(self.shell_socket, reply_type,
423 {'status' : 'aborted'}, msg, ident=ident)
423 {'status' : 'aborted'}, msg, ident=ident)
424 self.log.debug(reply_msg)
424 self.log.debug(reply_msg)
425 # We need to wait a bit for requests to come in. This can probably
425 # We need to wait a bit for requests to come in. This can probably
426 # be set shorter for true asynchronous clients.
426 # be set shorter for true asynchronous clients.
427 time.sleep(0.1)
427 time.sleep(0.1)
428
428
429 def _no_raw_input(self):
429 def _no_raw_input(self):
430 """Raise StdinNotImplentedError if active frontend doesn't support
430 """Raise StdinNotImplentedError if active frontend doesn't support
431 stdin."""
431 stdin."""
432 raise StdinNotImplementedError("raw_input was called, but this "
432 raise StdinNotImplementedError("raw_input was called, but this "
433 "frontend does not support stdin.")
433 "frontend does not support stdin.")
434
434
435 def _raw_input(self, prompt, ident, parent):
435 def _raw_input(self, prompt, ident, parent):
436 # Flush output before making the request.
436 # Flush output before making the request.
437 sys.stderr.flush()
437 sys.stderr.flush()
438 sys.stdout.flush()
438 sys.stdout.flush()
439
439
440 # Send the input request.
440 # Send the input request.
441 content = json_clean(dict(prompt=prompt))
441 content = json_clean(dict(prompt=prompt))
442 self.session.send(self.stdin_socket, u'input_request', content, parent,
442 self.session.send(self.stdin_socket, u'input_request', content, parent,
443 ident=ident)
443 ident=ident)
444
444
445 # Await a response.
445 # Await a response.
446 while True:
446 while True:
447 try:
447 try:
448 ident, reply = self.session.recv(self.stdin_socket, 0)
448 ident, reply = self.session.recv(self.stdin_socket, 0)
449 except Exception:
449 except Exception:
450 self.log.warn("Invalid Message:", exc_info=True)
450 self.log.warn("Invalid Message:", exc_info=True)
451 else:
451 else:
452 break
452 break
453 try:
453 try:
454 value = reply['content']['value']
454 value = reply['content']['value']
455 except:
455 except:
456 self.log.error("Got bad raw_input reply: ")
456 self.log.error("Got bad raw_input reply: ")
457 self.log.error(str(Message(parent)))
457 self.log.error(str(Message(parent)))
458 value = ''
458 value = ''
459 return value
459 return value
460
460
461 def _complete(self, msg):
461 def _complete(self, msg):
462 c = msg['content']
462 c = msg['content']
463 try:
463 try:
464 cpos = int(c['cursor_pos'])
464 cpos = int(c['cursor_pos'])
465 except:
465 except:
466 # If we don't get something that we can convert to an integer, at
466 # If we don't get something that we can convert to an integer, at
467 # least attempt the completion guessing the cursor is at the end of
467 # least attempt the completion guessing the cursor is at the end of
468 # the text, if there's any, and otherwise of the line
468 # the text, if there's any, and otherwise of the line
469 cpos = len(c['text'])
469 cpos = len(c['text'])
470 if cpos==0:
470 if cpos==0:
471 cpos = len(c['line'])
471 cpos = len(c['line'])
472 return self.shell.complete(c['text'], c['line'], cpos)
472 return self.shell.complete(c['text'], c['line'], cpos)
473
473
474 def _object_info(self, context):
474 def _object_info(self, context):
475 symbol, leftover = self._symbol_from_context(context)
475 symbol, leftover = self._symbol_from_context(context)
476 if symbol is not None and not leftover:
476 if symbol is not None and not leftover:
477 doc = getattr(symbol, '__doc__', '')
477 doc = getattr(symbol, '__doc__', '')
478 else:
478 else:
479 doc = ''
479 doc = ''
480 object_info = dict(docstring = doc)
480 object_info = dict(docstring = doc)
481 return object_info
481 return object_info
482
482
483 def _symbol_from_context(self, context):
483 def _symbol_from_context(self, context):
484 if not context:
484 if not context:
485 return None, context
485 return None, context
486
486
487 base_symbol_string = context[0]
487 base_symbol_string = context[0]
488 symbol = self.shell.user_ns.get(base_symbol_string, None)
488 symbol = self.shell.user_ns.get(base_symbol_string, None)
489 if symbol is None:
489 if symbol is None:
490 symbol = __builtin__.__dict__.get(base_symbol_string, None)
490 symbol = __builtin__.__dict__.get(base_symbol_string, None)
491 if symbol is None:
491 if symbol is None:
492 return None, context
492 return None, context
493
493
494 context = context[1:]
494 context = context[1:]
495 for i, name in enumerate(context):
495 for i, name in enumerate(context):
496 new_symbol = getattr(symbol, name, None)
496 new_symbol = getattr(symbol, name, None)
497 if new_symbol is None:
497 if new_symbol is None:
498 return symbol, context[i:]
498 return symbol, context[i:]
499 else:
499 else:
500 symbol = new_symbol
500 symbol = new_symbol
501
501
502 return symbol, []
502 return symbol, []
503
503
504 def _at_shutdown(self):
504 def _at_shutdown(self):
505 """Actions taken at shutdown by the kernel, called by python's atexit.
505 """Actions taken at shutdown by the kernel, called by python's atexit.
506 """
506 """
507 # io.rprint("Kernel at_shutdown") # dbg
507 # io.rprint("Kernel at_shutdown") # dbg
508 if self._shutdown_message is not None:
508 if self._shutdown_message is not None:
509 self.session.send(self.shell_socket, self._shutdown_message)
509 self.session.send(self.shell_socket, self._shutdown_message)
510 self.session.send(self.iopub_socket, self._shutdown_message)
510 self.session.send(self.iopub_socket, self._shutdown_message)
511 self.log.debug(str(self._shutdown_message))
511 self.log.debug(str(self._shutdown_message))
512 # A very short sleep to give zmq time to flush its message buffers
512 # A very short sleep to give zmq time to flush its message buffers
513 # before Python truly shuts down.
513 # before Python truly shuts down.
514 time.sleep(0.01)
514 time.sleep(0.01)
515
515
516 #-----------------------------------------------------------------------------
516 #-----------------------------------------------------------------------------
517 # Aliases and Flags for the IPKernelApp
517 # Aliases and Flags for the IPKernelApp
518 #-----------------------------------------------------------------------------
518 #-----------------------------------------------------------------------------
519
519
520 flags = dict(kernel_flags)
520 flags = dict(kernel_flags)
521 flags.update(shell_flags)
521 flags.update(shell_flags)
522
522
523 addflag = lambda *args: flags.update(boolean_flag(*args))
523 addflag = lambda *args: flags.update(boolean_flag(*args))
524
524
525 flags['pylab'] = (
525 flags['pylab'] = (
526 {'IPKernelApp' : {'pylab' : 'auto'}},
526 {'IPKernelApp' : {'pylab' : 'auto'}},
527 """Pre-load matplotlib and numpy for interactive use with
527 """Pre-load matplotlib and numpy for interactive use with
528 the default matplotlib backend."""
528 the default matplotlib backend."""
529 )
529 )
530
530
531 aliases = dict(kernel_aliases)
531 aliases = dict(kernel_aliases)
532 aliases.update(shell_aliases)
532 aliases.update(shell_aliases)
533
533
534 # it's possible we don't want short aliases for *all* of these:
534 # it's possible we don't want short aliases for *all* of these:
535 aliases.update(dict(
535 aliases.update(dict(
536 pylab='IPKernelApp.pylab',
536 pylab='IPKernelApp.pylab',
537 ))
537 ))
538
538
539 #-----------------------------------------------------------------------------
539 #-----------------------------------------------------------------------------
540 # The IPKernelApp class
540 # The IPKernelApp class
541 #-----------------------------------------------------------------------------
541 #-----------------------------------------------------------------------------
542
542
543 class IPKernelApp(KernelApp, InteractiveShellApp):
543 class IPKernelApp(KernelApp, InteractiveShellApp):
544 name = 'ipkernel'
544 name = 'ipkernel'
545
545
546 aliases = Dict(aliases)
546 aliases = Dict(aliases)
547 flags = Dict(flags)
547 flags = Dict(flags)
548 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
548 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
549 # configurables
549 # configurables
550 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
550 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
551 config=True,
551 config=True,
552 help="""Pre-load matplotlib and numpy for interactive use,
552 help="""Pre-load matplotlib and numpy for interactive use,
553 selecting a particular matplotlib backend and loop integration.
553 selecting a particular matplotlib backend and loop integration.
554 """
554 """
555 )
555 )
556
556
557 @catch_config_error
557 @catch_config_error
558 def initialize(self, argv=None):
558 def initialize(self, argv=None):
559 super(IPKernelApp, self).initialize(argv)
559 super(IPKernelApp, self).initialize(argv)
560 self.init_shell()
560 self.init_shell()
561 self.init_extensions()
561 self.init_extensions()
562 self.init_code()
562 self.init_code()
563
563
564 def init_kernel(self):
564 def init_kernel(self):
565
565
566 kernel = Kernel(config=self.config, session=self.session,
566 kernel = Kernel(config=self.config, session=self.session,
567 shell_socket=self.shell_socket,
567 shell_socket=self.shell_socket,
568 iopub_socket=self.iopub_socket,
568 iopub_socket=self.iopub_socket,
569 stdin_socket=self.stdin_socket,
569 stdin_socket=self.stdin_socket,
570 log=self.log,
570 log=self.log,
571 profile_dir=self.profile_dir,
571 profile_dir=self.profile_dir,
572 )
572 )
573 self.kernel = kernel
573 self.kernel = kernel
574 kernel.record_ports(self.ports)
574 kernel.record_ports(self.ports)
575 shell = kernel.shell
575 shell = kernel.shell
576 if self.pylab:
576 if self.pylab:
577 try:
577 try:
578 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
578 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
579 shell.enable_pylab(gui, import_all=self.pylab_import_all)
579 shell.enable_pylab(gui, import_all=self.pylab_import_all)
580 except Exception:
580 except Exception:
581 self.log.error("Pylab initialization failed", exc_info=True)
581 self.log.error("Pylab initialization failed", exc_info=True)
582 # print exception straight to stdout, because normally
582 # print exception straight to stdout, because normally
583 # _showtraceback associates the reply with an execution,
583 # _showtraceback associates the reply with an execution,
584 # which means frontends will never draw it, as this exception
584 # which means frontends will never draw it, as this exception
585 # is not associated with any execute request.
585 # is not associated with any execute request.
586
586
587 # replace pyerr-sending traceback with stdout
587 # replace pyerr-sending traceback with stdout
588 _showtraceback = shell._showtraceback
588 _showtraceback = shell._showtraceback
589 def print_tb(etype, evalue, stb):
589 def print_tb(etype, evalue, stb):
590 print ("Error initializing pylab, pylab mode will not "
590 print ("Error initializing pylab, pylab mode will not "
591 "be active", file=io.stderr)
591 "be active", file=io.stderr)
592 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
592 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
593 shell._showtraceback = print_tb
593 shell._showtraceback = print_tb
594
594
595 # send the traceback over stdout
595 # send the traceback over stdout
596 shell.showtraceback(tb_offset=0)
596 shell.showtraceback(tb_offset=0)
597
597
598 # restore proper _showtraceback method
598 # restore proper _showtraceback method
599 shell._showtraceback = _showtraceback
599 shell._showtraceback = _showtraceback
600
600
601
601
602 def init_shell(self):
602 def init_shell(self):
603 self.shell = self.kernel.shell
603 self.shell = self.kernel.shell
604 self.shell.configurables.append(self)
604 self.shell.configurables.append(self)
605
605
606
606
607 #-----------------------------------------------------------------------------
607 #-----------------------------------------------------------------------------
608 # Kernel main and launch functions
608 # Kernel main and launch functions
609 #-----------------------------------------------------------------------------
609 #-----------------------------------------------------------------------------
610
610
611 def launch_kernel(*args, **kwargs):
611 def launch_kernel(*args, **kwargs):
612 """Launches a localhost IPython kernel, binding to the specified ports.
612 """Launches a localhost IPython kernel, binding to the specified ports.
613
613
614 This function simply calls entry_point.base_launch_kernel with the right
614 This function simply calls entry_point.base_launch_kernel with the right
615 first command to start an ipkernel. See base_launch_kernel for arguments.
615 first command to start an ipkernel. See base_launch_kernel for arguments.
616
616
617 Returns
617 Returns
618 -------
618 -------
619 A tuple of form:
619 A tuple of form:
620 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
620 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
621 where kernel_process is a Popen object and the ports are integers.
621 where kernel_process is a Popen object and the ports are integers.
622 """
622 """
623 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
623 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
624 *args, **kwargs)
624 *args, **kwargs)
625
625
626
626
627 def main():
627 def main():
628 """Run an IPKernel as an application"""
628 """Run an IPKernel as an application"""
629 app = IPKernelApp.instance()
629 app = IPKernelApp.instance()
630 app.initialize()
630 app.initialize()
631 app.start()
631 app.start()
632
632
633
633
634 if __name__ == '__main__':
634 if __name__ == '__main__':
635 main()
635 main()
@@ -1,513 +1,512 b''
1 """A ZMQ-based subclass of InteractiveShell.
1 """A ZMQ-based subclass of InteractiveShell.
2
2
3 This code is meant to ease the refactoring of the base InteractiveShell into
3 This code is meant to ease the refactoring of the base InteractiveShell into
4 something with a cleaner architecture for 2-process use, without actually
4 something with a cleaner architecture for 2-process use, without actually
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 we subclass and override what we want to fix. Once this is working well, we
6 we subclass and override what we want to fix. Once this is working well, we
7 can go back to the base class and refactor the code for a cleaner inheritance
7 can go back to the base class and refactor the code for a cleaner inheritance
8 implementation that doesn't rely on so much monkeypatching.
8 implementation that doesn't rely on so much monkeypatching.
9
9
10 But this lets us maintain a fully working IPython as we develop the new
10 But this lets us maintain a fully working IPython as we develop the new
11 machinery. This should thus be thought of as scaffolding.
11 machinery. This should thus be thought of as scaffolding.
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 # Stdlib
18 # Stdlib
19 import inspect
19 import inspect
20 import os
20 import os
21 import sys
21 import sys
22 from subprocess import Popen, PIPE
22 from subprocess import Popen, PIPE
23
23
24 # Our own
24 # Our own
25 from IPython.core.interactiveshell import (
25 from IPython.core.interactiveshell import (
26 InteractiveShell, InteractiveShellABC
26 InteractiveShell, InteractiveShellABC
27 )
27 )
28 from IPython.core import page
28 from IPython.core import page, pylabtools
29 from IPython.core.autocall import ZMQExitAutocall
29 from IPython.core.autocall import ZMQExitAutocall
30 from IPython.core.displaypub import DisplayPublisher
30 from IPython.core.displaypub import DisplayPublisher
31 from IPython.core.macro import Macro
31 from IPython.core.macro import Macro
32 from IPython.core.magic import MacroToEdit
32 from IPython.core.magic import MacroToEdit
33 from IPython.core.payloadpage import install_payload_page
33 from IPython.core.payloadpage import install_payload_page
34 from IPython.lib import pylabtools
35 from IPython.lib.kernel import (
34 from IPython.lib.kernel import (
36 get_connection_file, get_connection_info, connect_qtconsole
35 get_connection_file, get_connection_info, connect_qtconsole
37 )
36 )
38 from IPython.utils import io
37 from IPython.utils import io
39 from IPython.utils.jsonutil import json_clean
38 from IPython.utils.jsonutil import json_clean
40 from IPython.utils.path import get_py_filename
39 from IPython.utils.path import get_py_filename
41 from IPython.utils.process import arg_split
40 from IPython.utils.process import arg_split
42 from IPython.utils.traitlets import Instance, Type, Dict, CBool
41 from IPython.utils.traitlets import Instance, Type, Dict, CBool
43 from IPython.utils.warn import warn, error
42 from IPython.utils.warn import warn, error
44 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
43 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
45 from IPython.zmq.session import extract_header
44 from IPython.zmq.session import extract_header
46 from session import Session
45 from session import Session
47
46
48 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
49 # Globals and side-effects
48 # Globals and side-effects
50 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
51
50
52 # Install the payload version of page.
51 # Install the payload version of page.
53 install_payload_page()
52 install_payload_page()
54
53
55 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
56 # Functions and classes
55 # Functions and classes
57 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
58
57
59 class ZMQDisplayPublisher(DisplayPublisher):
58 class ZMQDisplayPublisher(DisplayPublisher):
60 """A display publisher that publishes data using a ZeroMQ PUB socket."""
59 """A display publisher that publishes data using a ZeroMQ PUB socket."""
61
60
62 session = Instance(Session)
61 session = Instance(Session)
63 pub_socket = Instance('zmq.Socket')
62 pub_socket = Instance('zmq.Socket')
64 parent_header = Dict({})
63 parent_header = Dict({})
65
64
66 def set_parent(self, parent):
65 def set_parent(self, parent):
67 """Set the parent for outbound messages."""
66 """Set the parent for outbound messages."""
68 self.parent_header = extract_header(parent)
67 self.parent_header = extract_header(parent)
69
68
70 def publish(self, source, data, metadata=None):
69 def publish(self, source, data, metadata=None):
71 if metadata is None:
70 if metadata is None:
72 metadata = {}
71 metadata = {}
73 self._validate_data(source, data, metadata)
72 self._validate_data(source, data, metadata)
74 content = {}
73 content = {}
75 content['source'] = source
74 content['source'] = source
76 _encode_binary(data)
75 _encode_binary(data)
77 content['data'] = data
76 content['data'] = data
78 content['metadata'] = metadata
77 content['metadata'] = metadata
79 self.session.send(
78 self.session.send(
80 self.pub_socket, u'display_data', json_clean(content),
79 self.pub_socket, u'display_data', json_clean(content),
81 parent=self.parent_header
80 parent=self.parent_header
82 )
81 )
83
82
84 def clear_output(self, stdout=True, stderr=True, other=True):
83 def clear_output(self, stdout=True, stderr=True, other=True):
85 content = dict(stdout=stdout, stderr=stderr, other=other)
84 content = dict(stdout=stdout, stderr=stderr, other=other)
86 self.session.send(
85 self.session.send(
87 self.pub_socket, u'clear_output', content,
86 self.pub_socket, u'clear_output', content,
88 parent=self.parent_header
87 parent=self.parent_header
89 )
88 )
90
89
91 class ZMQInteractiveShell(InteractiveShell):
90 class ZMQInteractiveShell(InteractiveShell):
92 """A subclass of InteractiveShell for ZMQ."""
91 """A subclass of InteractiveShell for ZMQ."""
93
92
94 displayhook_class = Type(ZMQShellDisplayHook)
93 displayhook_class = Type(ZMQShellDisplayHook)
95 display_pub_class = Type(ZMQDisplayPublisher)
94 display_pub_class = Type(ZMQDisplayPublisher)
96
95
97 # Override the traitlet in the parent class, because there's no point using
96 # Override the traitlet in the parent class, because there's no point using
98 # readline for the kernel. Can be removed when the readline code is moved
97 # readline for the kernel. Can be removed when the readline code is moved
99 # to the terminal frontend.
98 # to the terminal frontend.
100 colors_force = CBool(True)
99 colors_force = CBool(True)
101 readline_use = CBool(False)
100 readline_use = CBool(False)
102 # autoindent has no meaning in a zmqshell, and attempting to enable it
101 # autoindent has no meaning in a zmqshell, and attempting to enable it
103 # will print a warning in the absence of readline.
102 # will print a warning in the absence of readline.
104 autoindent = CBool(False)
103 autoindent = CBool(False)
105
104
106 exiter = Instance(ZMQExitAutocall)
105 exiter = Instance(ZMQExitAutocall)
107 def _exiter_default(self):
106 def _exiter_default(self):
108 return ZMQExitAutocall(self)
107 return ZMQExitAutocall(self)
109
108
110 keepkernel_on_exit = None
109 keepkernel_on_exit = None
111
110
112 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
111 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
113 # interactive input being read; we provide event loop support in ipkernel
112 # interactive input being read; we provide event loop support in ipkernel
114 from .eventloops import enable_gui
113 from .eventloops import enable_gui
115 enable_gui = staticmethod(enable_gui)
114 enable_gui = staticmethod(enable_gui)
116
115
117 def init_environment(self):
116 def init_environment(self):
118 """Configure the user's environment.
117 """Configure the user's environment.
119
118
120 """
119 """
121 env = os.environ
120 env = os.environ
122 # These two ensure 'ls' produces nice coloring on BSD-derived systems
121 # These two ensure 'ls' produces nice coloring on BSD-derived systems
123 env['TERM'] = 'xterm-color'
122 env['TERM'] = 'xterm-color'
124 env['CLICOLOR'] = '1'
123 env['CLICOLOR'] = '1'
125 # Since normal pagers don't work at all (over pexpect we don't have
124 # Since normal pagers don't work at all (over pexpect we don't have
126 # single-key control of the subprocess), try to disable paging in
125 # single-key control of the subprocess), try to disable paging in
127 # subprocesses as much as possible.
126 # subprocesses as much as possible.
128 env['PAGER'] = 'cat'
127 env['PAGER'] = 'cat'
129 env['GIT_PAGER'] = 'cat'
128 env['GIT_PAGER'] = 'cat'
130
129
131 def auto_rewrite_input(self, cmd):
130 def auto_rewrite_input(self, cmd):
132 """Called to show the auto-rewritten input for autocall and friends.
131 """Called to show the auto-rewritten input for autocall and friends.
133
132
134 FIXME: this payload is currently not correctly processed by the
133 FIXME: this payload is currently not correctly processed by the
135 frontend.
134 frontend.
136 """
135 """
137 new = self.displayhook.prompt1.auto_rewrite() + cmd
136 new = self.displayhook.prompt1.auto_rewrite() + cmd
138 payload = dict(
137 payload = dict(
139 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
138 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
140 transformed_input=new,
139 transformed_input=new,
141 )
140 )
142 self.payload_manager.write_payload(payload)
141 self.payload_manager.write_payload(payload)
143
142
144 def ask_exit(self):
143 def ask_exit(self):
145 """Engage the exit actions."""
144 """Engage the exit actions."""
146 payload = dict(
145 payload = dict(
147 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
146 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
148 exit=True,
147 exit=True,
149 keepkernel=self.keepkernel_on_exit,
148 keepkernel=self.keepkernel_on_exit,
150 )
149 )
151 self.payload_manager.write_payload(payload)
150 self.payload_manager.write_payload(payload)
152
151
153 def _showtraceback(self, etype, evalue, stb):
152 def _showtraceback(self, etype, evalue, stb):
154
153
155 exc_content = {
154 exc_content = {
156 u'traceback' : stb,
155 u'traceback' : stb,
157 u'ename' : unicode(etype.__name__),
156 u'ename' : unicode(etype.__name__),
158 u'evalue' : unicode(evalue)
157 u'evalue' : unicode(evalue)
159 }
158 }
160
159
161 dh = self.displayhook
160 dh = self.displayhook
162 # Send exception info over pub socket for other clients than the caller
161 # Send exception info over pub socket for other clients than the caller
163 # to pick up
162 # to pick up
164 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header)
163 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header)
165
164
166 # FIXME - Hack: store exception info in shell object. Right now, the
165 # FIXME - Hack: store exception info in shell object. Right now, the
167 # caller is reading this info after the fact, we need to fix this logic
166 # caller is reading this info after the fact, we need to fix this logic
168 # to remove this hack. Even uglier, we need to store the error status
167 # to remove this hack. Even uglier, we need to store the error status
169 # here, because in the main loop, the logic that sets it is being
168 # here, because in the main loop, the logic that sets it is being
170 # skipped because runlines swallows the exceptions.
169 # skipped because runlines swallows the exceptions.
171 exc_content[u'status'] = u'error'
170 exc_content[u'status'] = u'error'
172 self._reply_content = exc_content
171 self._reply_content = exc_content
173 # /FIXME
172 # /FIXME
174
173
175 return exc_content
174 return exc_content
176
175
177 #------------------------------------------------------------------------
176 #------------------------------------------------------------------------
178 # Magic overrides
177 # Magic overrides
179 #------------------------------------------------------------------------
178 #------------------------------------------------------------------------
180 # Once the base class stops inheriting from magic, this code needs to be
179 # Once the base class stops inheriting from magic, this code needs to be
181 # moved into a separate machinery as well. For now, at least isolate here
180 # moved into a separate machinery as well. For now, at least isolate here
182 # the magics which this class needs to implement differently from the base
181 # the magics which this class needs to implement differently from the base
183 # class, or that are unique to it.
182 # class, or that are unique to it.
184
183
185 def magic_doctest_mode(self,parameter_s=''):
184 def magic_doctest_mode(self,parameter_s=''):
186 """Toggle doctest mode on and off.
185 """Toggle doctest mode on and off.
187
186
188 This mode is intended to make IPython behave as much as possible like a
187 This mode is intended to make IPython behave as much as possible like a
189 plain Python shell, from the perspective of how its prompts, exceptions
188 plain Python shell, from the perspective of how its prompts, exceptions
190 and output look. This makes it easy to copy and paste parts of a
189 and output look. This makes it easy to copy and paste parts of a
191 session into doctests. It does so by:
190 session into doctests. It does so by:
192
191
193 - Changing the prompts to the classic ``>>>`` ones.
192 - Changing the prompts to the classic ``>>>`` ones.
194 - Changing the exception reporting mode to 'Plain'.
193 - Changing the exception reporting mode to 'Plain'.
195 - Disabling pretty-printing of output.
194 - Disabling pretty-printing of output.
196
195
197 Note that IPython also supports the pasting of code snippets that have
196 Note that IPython also supports the pasting of code snippets that have
198 leading '>>>' and '...' prompts in them. This means that you can paste
197 leading '>>>' and '...' prompts in them. This means that you can paste
199 doctests from files or docstrings (even if they have leading
198 doctests from files or docstrings (even if they have leading
200 whitespace), and the code will execute correctly. You can then use
199 whitespace), and the code will execute correctly. You can then use
201 '%history -t' to see the translated history; this will give you the
200 '%history -t' to see the translated history; this will give you the
202 input after removal of all the leading prompts and whitespace, which
201 input after removal of all the leading prompts and whitespace, which
203 can be pasted back into an editor.
202 can be pasted back into an editor.
204
203
205 With these features, you can switch into this mode easily whenever you
204 With these features, you can switch into this mode easily whenever you
206 need to do testing and changes to doctests, without having to leave
205 need to do testing and changes to doctests, without having to leave
207 your existing IPython session.
206 your existing IPython session.
208 """
207 """
209
208
210 from IPython.utils.ipstruct import Struct
209 from IPython.utils.ipstruct import Struct
211
210
212 # Shorthands
211 # Shorthands
213 shell = self.shell
212 shell = self.shell
214 disp_formatter = self.shell.display_formatter
213 disp_formatter = self.shell.display_formatter
215 ptformatter = disp_formatter.formatters['text/plain']
214 ptformatter = disp_formatter.formatters['text/plain']
216 # dstore is a data store kept in the instance metadata bag to track any
215 # dstore is a data store kept in the instance metadata bag to track any
217 # changes we make, so we can undo them later.
216 # changes we make, so we can undo them later.
218 dstore = shell.meta.setdefault('doctest_mode', Struct())
217 dstore = shell.meta.setdefault('doctest_mode', Struct())
219 save_dstore = dstore.setdefault
218 save_dstore = dstore.setdefault
220
219
221 # save a few values we'll need to recover later
220 # save a few values we'll need to recover later
222 mode = save_dstore('mode', False)
221 mode = save_dstore('mode', False)
223 save_dstore('rc_pprint', ptformatter.pprint)
222 save_dstore('rc_pprint', ptformatter.pprint)
224 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
223 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
225 save_dstore('xmode', shell.InteractiveTB.mode)
224 save_dstore('xmode', shell.InteractiveTB.mode)
226
225
227 if mode == False:
226 if mode == False:
228 # turn on
227 # turn on
229 ptformatter.pprint = False
228 ptformatter.pprint = False
230 disp_formatter.plain_text_only = True
229 disp_formatter.plain_text_only = True
231 shell.magic_xmode('Plain')
230 shell.magic_xmode('Plain')
232 else:
231 else:
233 # turn off
232 # turn off
234 ptformatter.pprint = dstore.rc_pprint
233 ptformatter.pprint = dstore.rc_pprint
235 disp_formatter.plain_text_only = dstore.rc_plain_text_only
234 disp_formatter.plain_text_only = dstore.rc_plain_text_only
236 shell.magic_xmode(dstore.xmode)
235 shell.magic_xmode(dstore.xmode)
237
236
238 # Store new mode and inform on console
237 # Store new mode and inform on console
239 dstore.mode = bool(1-int(mode))
238 dstore.mode = bool(1-int(mode))
240 mode_label = ['OFF','ON'][dstore.mode]
239 mode_label = ['OFF','ON'][dstore.mode]
241 print('Doctest mode is:', mode_label)
240 print('Doctest mode is:', mode_label)
242
241
243 # Send the payload back so that clients can modify their prompt display
242 # Send the payload back so that clients can modify their prompt display
244 payload = dict(
243 payload = dict(
245 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
244 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
246 mode=dstore.mode)
245 mode=dstore.mode)
247 self.payload_manager.write_payload(payload)
246 self.payload_manager.write_payload(payload)
248
247
249 def magic_edit(self,parameter_s='',last_call=['','']):
248 def magic_edit(self,parameter_s='',last_call=['','']):
250 """Bring up an editor and execute the resulting code.
249 """Bring up an editor and execute the resulting code.
251
250
252 Usage:
251 Usage:
253 %edit [options] [args]
252 %edit [options] [args]
254
253
255 %edit runs an external text editor. You will need to set the command for
254 %edit runs an external text editor. You will need to set the command for
256 this editor via the ``TerminalInteractiveShell.editor`` option in your
255 this editor via the ``TerminalInteractiveShell.editor`` option in your
257 configuration file before it will work.
256 configuration file before it will work.
258
257
259 This command allows you to conveniently edit multi-line code right in
258 This command allows you to conveniently edit multi-line code right in
260 your IPython session.
259 your IPython session.
261
260
262 If called without arguments, %edit opens up an empty editor with a
261 If called without arguments, %edit opens up an empty editor with a
263 temporary file and will execute the contents of this file when you
262 temporary file and will execute the contents of this file when you
264 close it (don't forget to save it!).
263 close it (don't forget to save it!).
265
264
266
265
267 Options:
266 Options:
268
267
269 -n <number>: open the editor at a specified line number. By default,
268 -n <number>: open the editor at a specified line number. By default,
270 the IPython editor hook uses the unix syntax 'editor +N filename', but
269 the IPython editor hook uses the unix syntax 'editor +N filename', but
271 you can configure this by providing your own modified hook if your
270 you can configure this by providing your own modified hook if your
272 favorite editor supports line-number specifications with a different
271 favorite editor supports line-number specifications with a different
273 syntax.
272 syntax.
274
273
275 -p: this will call the editor with the same data as the previous time
274 -p: this will call the editor with the same data as the previous time
276 it was used, regardless of how long ago (in your current session) it
275 it was used, regardless of how long ago (in your current session) it
277 was.
276 was.
278
277
279 -r: use 'raw' input. This option only applies to input taken from the
278 -r: use 'raw' input. This option only applies to input taken from the
280 user's history. By default, the 'processed' history is used, so that
279 user's history. By default, the 'processed' history is used, so that
281 magics are loaded in their transformed version to valid Python. If
280 magics are loaded in their transformed version to valid Python. If
282 this option is given, the raw input as typed as the command line is
281 this option is given, the raw input as typed as the command line is
283 used instead. When you exit the editor, it will be executed by
282 used instead. When you exit the editor, it will be executed by
284 IPython's own processor.
283 IPython's own processor.
285
284
286 -x: do not execute the edited code immediately upon exit. This is
285 -x: do not execute the edited code immediately upon exit. This is
287 mainly useful if you are editing programs which need to be called with
286 mainly useful if you are editing programs which need to be called with
288 command line arguments, which you can then do using %run.
287 command line arguments, which you can then do using %run.
289
288
290
289
291 Arguments:
290 Arguments:
292
291
293 If arguments are given, the following possibilites exist:
292 If arguments are given, the following possibilites exist:
294
293
295 - The arguments are numbers or pairs of colon-separated numbers (like
294 - The arguments are numbers or pairs of colon-separated numbers (like
296 1 4:8 9). These are interpreted as lines of previous input to be
295 1 4:8 9). These are interpreted as lines of previous input to be
297 loaded into the editor. The syntax is the same of the %macro command.
296 loaded into the editor. The syntax is the same of the %macro command.
298
297
299 - If the argument doesn't start with a number, it is evaluated as a
298 - If the argument doesn't start with a number, it is evaluated as a
300 variable and its contents loaded into the editor. You can thus edit
299 variable and its contents loaded into the editor. You can thus edit
301 any string which contains python code (including the result of
300 any string which contains python code (including the result of
302 previous edits).
301 previous edits).
303
302
304 - If the argument is the name of an object (other than a string),
303 - If the argument is the name of an object (other than a string),
305 IPython will try to locate the file where it was defined and open the
304 IPython will try to locate the file where it was defined and open the
306 editor at the point where it is defined. You can use `%edit function`
305 editor at the point where it is defined. You can use `%edit function`
307 to load an editor exactly at the point where 'function' is defined,
306 to load an editor exactly at the point where 'function' is defined,
308 edit it and have the file be executed automatically.
307 edit it and have the file be executed automatically.
309
308
310 If the object is a macro (see %macro for details), this opens up your
309 If the object is a macro (see %macro for details), this opens up your
311 specified editor with a temporary file containing the macro's data.
310 specified editor with a temporary file containing the macro's data.
312 Upon exit, the macro is reloaded with the contents of the file.
311 Upon exit, the macro is reloaded with the contents of the file.
313
312
314 Note: opening at an exact line is only supported under Unix, and some
313 Note: opening at an exact line is only supported under Unix, and some
315 editors (like kedit and gedit up to Gnome 2.8) do not understand the
314 editors (like kedit and gedit up to Gnome 2.8) do not understand the
316 '+NUMBER' parameter necessary for this feature. Good editors like
315 '+NUMBER' parameter necessary for this feature. Good editors like
317 (X)Emacs, vi, jed, pico and joe all do.
316 (X)Emacs, vi, jed, pico and joe all do.
318
317
319 - If the argument is not found as a variable, IPython will look for a
318 - If the argument is not found as a variable, IPython will look for a
320 file with that name (adding .py if necessary) and load it into the
319 file with that name (adding .py if necessary) and load it into the
321 editor. It will execute its contents with execfile() when you exit,
320 editor. It will execute its contents with execfile() when you exit,
322 loading any code in the file into your interactive namespace.
321 loading any code in the file into your interactive namespace.
323
322
324 After executing your code, %edit will return as output the code you
323 After executing your code, %edit will return as output the code you
325 typed in the editor (except when it was an existing file). This way
324 typed in the editor (except when it was an existing file). This way
326 you can reload the code in further invocations of %edit as a variable,
325 you can reload the code in further invocations of %edit as a variable,
327 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
326 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
328 the output.
327 the output.
329
328
330 Note that %edit is also available through the alias %ed.
329 Note that %edit is also available through the alias %ed.
331
330
332 This is an example of creating a simple function inside the editor and
331 This is an example of creating a simple function inside the editor and
333 then modifying it. First, start up the editor:
332 then modifying it. First, start up the editor:
334
333
335 In [1]: ed
334 In [1]: ed
336 Editing... done. Executing edited code...
335 Editing... done. Executing edited code...
337 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
336 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
338
337
339 We can then call the function foo():
338 We can then call the function foo():
340
339
341 In [2]: foo()
340 In [2]: foo()
342 foo() was defined in an editing session
341 foo() was defined in an editing session
343
342
344 Now we edit foo. IPython automatically loads the editor with the
343 Now we edit foo. IPython automatically loads the editor with the
345 (temporary) file where foo() was previously defined:
344 (temporary) file where foo() was previously defined:
346
345
347 In [3]: ed foo
346 In [3]: ed foo
348 Editing... done. Executing edited code...
347 Editing... done. Executing edited code...
349
348
350 And if we call foo() again we get the modified version:
349 And if we call foo() again we get the modified version:
351
350
352 In [4]: foo()
351 In [4]: foo()
353 foo() has now been changed!
352 foo() has now been changed!
354
353
355 Here is an example of how to edit a code snippet successive
354 Here is an example of how to edit a code snippet successive
356 times. First we call the editor:
355 times. First we call the editor:
357
356
358 In [5]: ed
357 In [5]: ed
359 Editing... done. Executing edited code...
358 Editing... done. Executing edited code...
360 hello
359 hello
361 Out[5]: "print 'hello'n"
360 Out[5]: "print 'hello'n"
362
361
363 Now we call it again with the previous output (stored in _):
362 Now we call it again with the previous output (stored in _):
364
363
365 In [6]: ed _
364 In [6]: ed _
366 Editing... done. Executing edited code...
365 Editing... done. Executing edited code...
367 hello world
366 hello world
368 Out[6]: "print 'hello world'n"
367 Out[6]: "print 'hello world'n"
369
368
370 Now we call it with the output #8 (stored in _8, also as Out[8]):
369 Now we call it with the output #8 (stored in _8, also as Out[8]):
371
370
372 In [7]: ed _8
371 In [7]: ed _8
373 Editing... done. Executing edited code...
372 Editing... done. Executing edited code...
374 hello again
373 hello again
375 Out[7]: "print 'hello again'n"
374 Out[7]: "print 'hello again'n"
376 """
375 """
377
376
378 opts,args = self.parse_options(parameter_s,'prn:')
377 opts,args = self.parse_options(parameter_s,'prn:')
379
378
380 try:
379 try:
381 filename, lineno, _ = self._find_edit_target(args, opts, last_call)
380 filename, lineno, _ = self._find_edit_target(args, opts, last_call)
382 except MacroToEdit as e:
381 except MacroToEdit as e:
383 # TODO: Implement macro editing over 2 processes.
382 # TODO: Implement macro editing over 2 processes.
384 print("Macro editing not yet implemented in 2-process model.")
383 print("Macro editing not yet implemented in 2-process model.")
385 return
384 return
386
385
387 # Make sure we send to the client an absolute path, in case the working
386 # Make sure we send to the client an absolute path, in case the working
388 # directory of client and kernel don't match
387 # directory of client and kernel don't match
389 filename = os.path.abspath(filename)
388 filename = os.path.abspath(filename)
390
389
391 payload = {
390 payload = {
392 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
391 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
393 'filename' : filename,
392 'filename' : filename,
394 'line_number' : lineno
393 'line_number' : lineno
395 }
394 }
396 self.payload_manager.write_payload(payload)
395 self.payload_manager.write_payload(payload)
397
396
398 # A few magics that are adapted to the specifics of using pexpect and a
397 # A few magics that are adapted to the specifics of using pexpect and a
399 # remote terminal
398 # remote terminal
400
399
401 def magic_clear(self, arg_s):
400 def magic_clear(self, arg_s):
402 """Clear the terminal."""
401 """Clear the terminal."""
403 if os.name == 'posix':
402 if os.name == 'posix':
404 self.shell.system("clear")
403 self.shell.system("clear")
405 else:
404 else:
406 self.shell.system("cls")
405 self.shell.system("cls")
407
406
408 if os.name == 'nt':
407 if os.name == 'nt':
409 # This is the usual name in windows
408 # This is the usual name in windows
410 magic_cls = magic_clear
409 magic_cls = magic_clear
411
410
412 # Terminal pagers won't work over pexpect, but we do have our own pager
411 # Terminal pagers won't work over pexpect, but we do have our own pager
413
412
414 def magic_less(self, arg_s):
413 def magic_less(self, arg_s):
415 """Show a file through the pager.
414 """Show a file through the pager.
416
415
417 Files ending in .py are syntax-highlighted."""
416 Files ending in .py are syntax-highlighted."""
418 cont = open(arg_s).read()
417 cont = open(arg_s).read()
419 if arg_s.endswith('.py'):
418 if arg_s.endswith('.py'):
420 cont = self.shell.pycolorize(cont)
419 cont = self.shell.pycolorize(cont)
421 page.page(cont)
420 page.page(cont)
422
421
423 magic_more = magic_less
422 magic_more = magic_less
424
423
425 # Man calls a pager, so we also need to redefine it
424 # Man calls a pager, so we also need to redefine it
426 if os.name == 'posix':
425 if os.name == 'posix':
427 def magic_man(self, arg_s):
426 def magic_man(self, arg_s):
428 """Find the man page for the given command and display in pager."""
427 """Find the man page for the given command and display in pager."""
429 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
428 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
430 split=False))
429 split=False))
431
430
432 # FIXME: this is specific to the GUI, so we should let the gui app load
431 # FIXME: this is specific to the GUI, so we should let the gui app load
433 # magics at startup that are only for the gui. Once the gui app has proper
432 # magics at startup that are only for the gui. Once the gui app has proper
434 # profile and configuration management, we can have it initialize a kernel
433 # profile and configuration management, we can have it initialize a kernel
435 # with a special config file that provides these.
434 # with a special config file that provides these.
436 def magic_guiref(self, arg_s):
435 def magic_guiref(self, arg_s):
437 """Show a basic reference about the GUI console."""
436 """Show a basic reference about the GUI console."""
438 from IPython.core.usage import gui_reference
437 from IPython.core.usage import gui_reference
439 page.page(gui_reference, auto_html=True)
438 page.page(gui_reference, auto_html=True)
440
439
441 def magic_connect_info(self, arg_s):
440 def magic_connect_info(self, arg_s):
442 """Print information for connecting other clients to this kernel
441 """Print information for connecting other clients to this kernel
443
442
444 It will print the contents of this session's connection file, as well as
443 It will print the contents of this session's connection file, as well as
445 shortcuts for local clients.
444 shortcuts for local clients.
446
445
447 In the simplest case, when called from the most recently launched kernel,
446 In the simplest case, when called from the most recently launched kernel,
448 secondary clients can be connected, simply with:
447 secondary clients can be connected, simply with:
449
448
450 $> ipython <app> --existing
449 $> ipython <app> --existing
451
450
452 """
451 """
453
452
454 from IPython.core.application import BaseIPythonApplication as BaseIPApp
453 from IPython.core.application import BaseIPythonApplication as BaseIPApp
455
454
456 if BaseIPApp.initialized():
455 if BaseIPApp.initialized():
457 app = BaseIPApp.instance()
456 app = BaseIPApp.instance()
458 security_dir = app.profile_dir.security_dir
457 security_dir = app.profile_dir.security_dir
459 profile = app.profile
458 profile = app.profile
460 else:
459 else:
461 profile = 'default'
460 profile = 'default'
462 security_dir = ''
461 security_dir = ''
463
462
464 try:
463 try:
465 connection_file = get_connection_file()
464 connection_file = get_connection_file()
466 info = get_connection_info(unpack=False)
465 info = get_connection_info(unpack=False)
467 except Exception as e:
466 except Exception as e:
468 error("Could not get connection info: %r" % e)
467 error("Could not get connection info: %r" % e)
469 return
468 return
470
469
471 # add profile flag for non-default profile
470 # add profile flag for non-default profile
472 profile_flag = "--profile %s" % profile if profile != 'default' else ""
471 profile_flag = "--profile %s" % profile if profile != 'default' else ""
473
472
474 # if it's in the security dir, truncate to basename
473 # if it's in the security dir, truncate to basename
475 if security_dir == os.path.dirname(connection_file):
474 if security_dir == os.path.dirname(connection_file):
476 connection_file = os.path.basename(connection_file)
475 connection_file = os.path.basename(connection_file)
477
476
478
477
479 print (info + '\n')
478 print (info + '\n')
480 print ("Paste the above JSON into a file, and connect with:\n"
479 print ("Paste the above JSON into a file, and connect with:\n"
481 " $> ipython <app> --existing <file>\n"
480 " $> ipython <app> --existing <file>\n"
482 "or, if you are local, you can connect with just:\n"
481 "or, if you are local, you can connect with just:\n"
483 " $> ipython <app> --existing {0} {1}\n"
482 " $> ipython <app> --existing {0} {1}\n"
484 "or even just:\n"
483 "or even just:\n"
485 " $> ipython <app> --existing {1}\n"
484 " $> ipython <app> --existing {1}\n"
486 "if this is the most recent IPython session you have started.".format(
485 "if this is the most recent IPython session you have started.".format(
487 connection_file, profile_flag
486 connection_file, profile_flag
488 )
487 )
489 )
488 )
490
489
491 def magic_qtconsole(self, arg_s):
490 def magic_qtconsole(self, arg_s):
492 """Open a qtconsole connected to this kernel.
491 """Open a qtconsole connected to this kernel.
493
492
494 Useful for connecting a qtconsole to running notebooks, for better
493 Useful for connecting a qtconsole to running notebooks, for better
495 debugging.
494 debugging.
496 """
495 """
497 try:
496 try:
498 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
497 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
499 except Exception as e:
498 except Exception as e:
500 error("Could not start qtconsole: %r" % e)
499 error("Could not start qtconsole: %r" % e)
501 return
500 return
502
501
503 def set_next_input(self, text):
502 def set_next_input(self, text):
504 """Send the specified text to the frontend to be presented at the next
503 """Send the specified text to the frontend to be presented at the next
505 input cell."""
504 input cell."""
506 payload = dict(
505 payload = dict(
507 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
506 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
508 text=text
507 text=text
509 )
508 )
510 self.payload_manager.write_payload(payload)
509 self.payload_manager.write_payload(payload)
511
510
512
511
513 InteractiveShellABC.register(ZMQInteractiveShell)
512 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now