##// END OF EJS Templates
Protect zmqshell against non-unicode safe exceptions....
Thomas Kluyver -
Show More
@@ -1,559 +1,581 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 os
19 import os
20 import sys
20 import sys
21 import time
21 import time
22
22
23 # System library imports
23 # System library imports
24 from zmq.eventloop import ioloop
24 from zmq.eventloop import ioloop
25
25
26 # Our own
26 # Our own
27 from IPython.core.interactiveshell import (
27 from IPython.core.interactiveshell import (
28 InteractiveShell, InteractiveShellABC
28 InteractiveShell, InteractiveShellABC
29 )
29 )
30 from IPython.core import page
30 from IPython.core import page
31 from IPython.core.autocall import ZMQExitAutocall
31 from IPython.core.autocall import ZMQExitAutocall
32 from IPython.core.displaypub import DisplayPublisher
32 from IPython.core.displaypub import DisplayPublisher
33 from IPython.core.magics import MacroToEdit, CodeMagics
33 from IPython.core.magics import MacroToEdit, CodeMagics
34 from IPython.core.magic import magics_class, line_magic, Magics
34 from IPython.core.magic import magics_class, line_magic, Magics
35 from IPython.core.payloadpage import install_payload_page
35 from IPython.core.payloadpage import install_payload_page
36 from IPython.lib.kernel import (
36 from IPython.lib.kernel import (
37 get_connection_file, get_connection_info, connect_qtconsole
37 get_connection_file, get_connection_info, connect_qtconsole
38 )
38 )
39 from IPython.testing.skipdoctest import skip_doctest
39 from IPython.testing.skipdoctest import skip_doctest
40 from IPython.utils import io
40 from IPython.utils import io
41 from IPython.utils.jsonutil import json_clean
41 from IPython.utils.jsonutil import json_clean
42 from IPython.utils.process import arg_split
42 from IPython.utils.process import arg_split
43 from IPython.utils import py3compat
43 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes
44 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes
44 from IPython.utils.warn import warn, error
45 from IPython.utils.warn import warn, error
45 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
46 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
46 from IPython.zmq.session import extract_header
47 from IPython.zmq.session import extract_header
47 from session import Session
48 from session import Session
48
49
49 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
50 # Functions and classes
51 # Functions and classes
51 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
52
53
53 class ZMQDisplayPublisher(DisplayPublisher):
54 class ZMQDisplayPublisher(DisplayPublisher):
54 """A display publisher that publishes data using a ZeroMQ PUB socket."""
55 """A display publisher that publishes data using a ZeroMQ PUB socket."""
55
56
56 session = Instance(Session)
57 session = Instance(Session)
57 pub_socket = Instance('zmq.Socket')
58 pub_socket = Instance('zmq.Socket')
58 parent_header = Dict({})
59 parent_header = Dict({})
59 topic = CBytes(b'displaypub')
60 topic = CBytes(b'displaypub')
60
61
61 def set_parent(self, parent):
62 def set_parent(self, parent):
62 """Set the parent for outbound messages."""
63 """Set the parent for outbound messages."""
63 self.parent_header = extract_header(parent)
64 self.parent_header = extract_header(parent)
64
65
65 def _flush_streams(self):
66 def _flush_streams(self):
66 """flush IO Streams prior to display"""
67 """flush IO Streams prior to display"""
67 sys.stdout.flush()
68 sys.stdout.flush()
68 sys.stderr.flush()
69 sys.stderr.flush()
69
70
70 def publish(self, source, data, metadata=None):
71 def publish(self, source, data, metadata=None):
71 self._flush_streams()
72 self._flush_streams()
72 if metadata is None:
73 if metadata is None:
73 metadata = {}
74 metadata = {}
74 self._validate_data(source, data, metadata)
75 self._validate_data(source, data, metadata)
75 content = {}
76 content = {}
76 content['source'] = source
77 content['source'] = source
77 content['data'] = _encode_binary(data)
78 content['data'] = _encode_binary(data)
78 content['metadata'] = metadata
79 content['metadata'] = metadata
79 self.session.send(
80 self.session.send(
80 self.pub_socket, u'display_data', json_clean(content),
81 self.pub_socket, u'display_data', json_clean(content),
81 parent=self.parent_header, ident=self.topic,
82 parent=self.parent_header, ident=self.topic,
82 )
83 )
83
84
84 def clear_output(self, stdout=True, stderr=True, other=True):
85 def clear_output(self, stdout=True, stderr=True, other=True):
85 content = dict(stdout=stdout, stderr=stderr, other=other)
86 content = dict(stdout=stdout, stderr=stderr, other=other)
86
87
87 if stdout:
88 if stdout:
88 print('\r', file=sys.stdout, end='')
89 print('\r', file=sys.stdout, end='')
89 if stderr:
90 if stderr:
90 print('\r', file=sys.stderr, end='')
91 print('\r', file=sys.stderr, end='')
91
92
92 self._flush_streams()
93 self._flush_streams()
93
94
94 self.session.send(
95 self.session.send(
95 self.pub_socket, u'clear_output', content,
96 self.pub_socket, u'clear_output', content,
96 parent=self.parent_header, ident=self.topic,
97 parent=self.parent_header, ident=self.topic,
97 )
98 )
98
99
99 @magics_class
100 @magics_class
100 class KernelMagics(Magics):
101 class KernelMagics(Magics):
101 #------------------------------------------------------------------------
102 #------------------------------------------------------------------------
102 # Magic overrides
103 # Magic overrides
103 #------------------------------------------------------------------------
104 #------------------------------------------------------------------------
104 # Once the base class stops inheriting from magic, this code needs to be
105 # Once the base class stops inheriting from magic, this code needs to be
105 # moved into a separate machinery as well. For now, at least isolate here
106 # moved into a separate machinery as well. For now, at least isolate here
106 # the magics which this class needs to implement differently from the base
107 # the magics which this class needs to implement differently from the base
107 # class, or that are unique to it.
108 # class, or that are unique to it.
108
109
109 @line_magic
110 @line_magic
110 def doctest_mode(self, parameter_s=''):
111 def doctest_mode(self, parameter_s=''):
111 """Toggle doctest mode on and off.
112 """Toggle doctest mode on and off.
112
113
113 This mode is intended to make IPython behave as much as possible like a
114 This mode is intended to make IPython behave as much as possible like a
114 plain Python shell, from the perspective of how its prompts, exceptions
115 plain Python shell, from the perspective of how its prompts, exceptions
115 and output look. This makes it easy to copy and paste parts of a
116 and output look. This makes it easy to copy and paste parts of a
116 session into doctests. It does so by:
117 session into doctests. It does so by:
117
118
118 - Changing the prompts to the classic ``>>>`` ones.
119 - Changing the prompts to the classic ``>>>`` ones.
119 - Changing the exception reporting mode to 'Plain'.
120 - Changing the exception reporting mode to 'Plain'.
120 - Disabling pretty-printing of output.
121 - Disabling pretty-printing of output.
121
122
122 Note that IPython also supports the pasting of code snippets that have
123 Note that IPython also supports the pasting of code snippets that have
123 leading '>>>' and '...' prompts in them. This means that you can paste
124 leading '>>>' and '...' prompts in them. This means that you can paste
124 doctests from files or docstrings (even if they have leading
125 doctests from files or docstrings (even if they have leading
125 whitespace), and the code will execute correctly. You can then use
126 whitespace), and the code will execute correctly. You can then use
126 '%history -t' to see the translated history; this will give you the
127 '%history -t' to see the translated history; this will give you the
127 input after removal of all the leading prompts and whitespace, which
128 input after removal of all the leading prompts and whitespace, which
128 can be pasted back into an editor.
129 can be pasted back into an editor.
129
130
130 With these features, you can switch into this mode easily whenever you
131 With these features, you can switch into this mode easily whenever you
131 need to do testing and changes to doctests, without having to leave
132 need to do testing and changes to doctests, without having to leave
132 your existing IPython session.
133 your existing IPython session.
133 """
134 """
134
135
135 from IPython.utils.ipstruct import Struct
136 from IPython.utils.ipstruct import Struct
136
137
137 # Shorthands
138 # Shorthands
138 shell = self.shell
139 shell = self.shell
139 disp_formatter = self.shell.display_formatter
140 disp_formatter = self.shell.display_formatter
140 ptformatter = disp_formatter.formatters['text/plain']
141 ptformatter = disp_formatter.formatters['text/plain']
141 # dstore is a data store kept in the instance metadata bag to track any
142 # dstore is a data store kept in the instance metadata bag to track any
142 # changes we make, so we can undo them later.
143 # changes we make, so we can undo them later.
143 dstore = shell.meta.setdefault('doctest_mode', Struct())
144 dstore = shell.meta.setdefault('doctest_mode', Struct())
144 save_dstore = dstore.setdefault
145 save_dstore = dstore.setdefault
145
146
146 # save a few values we'll need to recover later
147 # save a few values we'll need to recover later
147 mode = save_dstore('mode', False)
148 mode = save_dstore('mode', False)
148 save_dstore('rc_pprint', ptformatter.pprint)
149 save_dstore('rc_pprint', ptformatter.pprint)
149 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
150 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
150 save_dstore('xmode', shell.InteractiveTB.mode)
151 save_dstore('xmode', shell.InteractiveTB.mode)
151
152
152 if mode == False:
153 if mode == False:
153 # turn on
154 # turn on
154 ptformatter.pprint = False
155 ptformatter.pprint = False
155 disp_formatter.plain_text_only = True
156 disp_formatter.plain_text_only = True
156 shell.magic('xmode Plain')
157 shell.magic('xmode Plain')
157 else:
158 else:
158 # turn off
159 # turn off
159 ptformatter.pprint = dstore.rc_pprint
160 ptformatter.pprint = dstore.rc_pprint
160 disp_formatter.plain_text_only = dstore.rc_plain_text_only
161 disp_formatter.plain_text_only = dstore.rc_plain_text_only
161 shell.magic("xmode " + dstore.xmode)
162 shell.magic("xmode " + dstore.xmode)
162
163
163 # Store new mode and inform on console
164 # Store new mode and inform on console
164 dstore.mode = bool(1-int(mode))
165 dstore.mode = bool(1-int(mode))
165 mode_label = ['OFF','ON'][dstore.mode]
166 mode_label = ['OFF','ON'][dstore.mode]
166 print('Doctest mode is:', mode_label)
167 print('Doctest mode is:', mode_label)
167
168
168 # Send the payload back so that clients can modify their prompt display
169 # Send the payload back so that clients can modify their prompt display
169 payload = dict(
170 payload = dict(
170 source='IPython.zmq.zmqshell.ZMQInteractiveShell.doctest_mode',
171 source='IPython.zmq.zmqshell.ZMQInteractiveShell.doctest_mode',
171 mode=dstore.mode)
172 mode=dstore.mode)
172 shell.payload_manager.write_payload(payload)
173 shell.payload_manager.write_payload(payload)
173
174
174
175
175 _find_edit_target = CodeMagics._find_edit_target
176 _find_edit_target = CodeMagics._find_edit_target
176
177
177 @skip_doctest
178 @skip_doctest
178 @line_magic
179 @line_magic
179 def edit(self, parameter_s='', last_call=['','']):
180 def edit(self, parameter_s='', last_call=['','']):
180 """Bring up an editor and execute the resulting code.
181 """Bring up an editor and execute the resulting code.
181
182
182 Usage:
183 Usage:
183 %edit [options] [args]
184 %edit [options] [args]
184
185
185 %edit runs an external text editor. You will need to set the command for
186 %edit runs an external text editor. You will need to set the command for
186 this editor via the ``TerminalInteractiveShell.editor`` option in your
187 this editor via the ``TerminalInteractiveShell.editor`` option in your
187 configuration file before it will work.
188 configuration file before it will work.
188
189
189 This command allows you to conveniently edit multi-line code right in
190 This command allows you to conveniently edit multi-line code right in
190 your IPython session.
191 your IPython session.
191
192
192 If called without arguments, %edit opens up an empty editor with a
193 If called without arguments, %edit opens up an empty editor with a
193 temporary file and will execute the contents of this file when you
194 temporary file and will execute the contents of this file when you
194 close it (don't forget to save it!).
195 close it (don't forget to save it!).
195
196
196
197
197 Options:
198 Options:
198
199
199 -n <number>: open the editor at a specified line number. By default,
200 -n <number>: open the editor at a specified line number. By default,
200 the IPython editor hook uses the unix syntax 'editor +N filename', but
201 the IPython editor hook uses the unix syntax 'editor +N filename', but
201 you can configure this by providing your own modified hook if your
202 you can configure this by providing your own modified hook if your
202 favorite editor supports line-number specifications with a different
203 favorite editor supports line-number specifications with a different
203 syntax.
204 syntax.
204
205
205 -p: this will call the editor with the same data as the previous time
206 -p: this will call the editor with the same data as the previous time
206 it was used, regardless of how long ago (in your current session) it
207 it was used, regardless of how long ago (in your current session) it
207 was.
208 was.
208
209
209 -r: use 'raw' input. This option only applies to input taken from the
210 -r: use 'raw' input. This option only applies to input taken from the
210 user's history. By default, the 'processed' history is used, so that
211 user's history. By default, the 'processed' history is used, so that
211 magics are loaded in their transformed version to valid Python. If
212 magics are loaded in their transformed version to valid Python. If
212 this option is given, the raw input as typed as the command line is
213 this option is given, the raw input as typed as the command line is
213 used instead. When you exit the editor, it will be executed by
214 used instead. When you exit the editor, it will be executed by
214 IPython's own processor.
215 IPython's own processor.
215
216
216 -x: do not execute the edited code immediately upon exit. This is
217 -x: do not execute the edited code immediately upon exit. This is
217 mainly useful if you are editing programs which need to be called with
218 mainly useful if you are editing programs which need to be called with
218 command line arguments, which you can then do using %run.
219 command line arguments, which you can then do using %run.
219
220
220
221
221 Arguments:
222 Arguments:
222
223
223 If arguments are given, the following possibilites exist:
224 If arguments are given, the following possibilites exist:
224
225
225 - The arguments are numbers or pairs of colon-separated numbers (like
226 - The arguments are numbers or pairs of colon-separated numbers (like
226 1 4:8 9). These are interpreted as lines of previous input to be
227 1 4:8 9). These are interpreted as lines of previous input to be
227 loaded into the editor. The syntax is the same of the %macro command.
228 loaded into the editor. The syntax is the same of the %macro command.
228
229
229 - If the argument doesn't start with a number, it is evaluated as a
230 - If the argument doesn't start with a number, it is evaluated as a
230 variable and its contents loaded into the editor. You can thus edit
231 variable and its contents loaded into the editor. You can thus edit
231 any string which contains python code (including the result of
232 any string which contains python code (including the result of
232 previous edits).
233 previous edits).
233
234
234 - If the argument is the name of an object (other than a string),
235 - If the argument is the name of an object (other than a string),
235 IPython will try to locate the file where it was defined and open the
236 IPython will try to locate the file where it was defined and open the
236 editor at the point where it is defined. You can use `%edit function`
237 editor at the point where it is defined. You can use `%edit function`
237 to load an editor exactly at the point where 'function' is defined,
238 to load an editor exactly at the point where 'function' is defined,
238 edit it and have the file be executed automatically.
239 edit it and have the file be executed automatically.
239
240
240 If the object is a macro (see %macro for details), this opens up your
241 If the object is a macro (see %macro for details), this opens up your
241 specified editor with a temporary file containing the macro's data.
242 specified editor with a temporary file containing the macro's data.
242 Upon exit, the macro is reloaded with the contents of the file.
243 Upon exit, the macro is reloaded with the contents of the file.
243
244
244 Note: opening at an exact line is only supported under Unix, and some
245 Note: opening at an exact line is only supported under Unix, and some
245 editors (like kedit and gedit up to Gnome 2.8) do not understand the
246 editors (like kedit and gedit up to Gnome 2.8) do not understand the
246 '+NUMBER' parameter necessary for this feature. Good editors like
247 '+NUMBER' parameter necessary for this feature. Good editors like
247 (X)Emacs, vi, jed, pico and joe all do.
248 (X)Emacs, vi, jed, pico and joe all do.
248
249
249 - If the argument is not found as a variable, IPython will look for a
250 - If the argument is not found as a variable, IPython will look for a
250 file with that name (adding .py if necessary) and load it into the
251 file with that name (adding .py if necessary) and load it into the
251 editor. It will execute its contents with execfile() when you exit,
252 editor. It will execute its contents with execfile() when you exit,
252 loading any code in the file into your interactive namespace.
253 loading any code in the file into your interactive namespace.
253
254
254 After executing your code, %edit will return as output the code you
255 After executing your code, %edit will return as output the code you
255 typed in the editor (except when it was an existing file). This way
256 typed in the editor (except when it was an existing file). This way
256 you can reload the code in further invocations of %edit as a variable,
257 you can reload the code in further invocations of %edit as a variable,
257 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
258 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
258 the output.
259 the output.
259
260
260 Note that %edit is also available through the alias %ed.
261 Note that %edit is also available through the alias %ed.
261
262
262 This is an example of creating a simple function inside the editor and
263 This is an example of creating a simple function inside the editor and
263 then modifying it. First, start up the editor:
264 then modifying it. First, start up the editor:
264
265
265 In [1]: ed
266 In [1]: ed
266 Editing... done. Executing edited code...
267 Editing... done. Executing edited code...
267 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
268 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
268
269
269 We can then call the function foo():
270 We can then call the function foo():
270
271
271 In [2]: foo()
272 In [2]: foo()
272 foo() was defined in an editing session
273 foo() was defined in an editing session
273
274
274 Now we edit foo. IPython automatically loads the editor with the
275 Now we edit foo. IPython automatically loads the editor with the
275 (temporary) file where foo() was previously defined:
276 (temporary) file where foo() was previously defined:
276
277
277 In [3]: ed foo
278 In [3]: ed foo
278 Editing... done. Executing edited code...
279 Editing... done. Executing edited code...
279
280
280 And if we call foo() again we get the modified version:
281 And if we call foo() again we get the modified version:
281
282
282 In [4]: foo()
283 In [4]: foo()
283 foo() has now been changed!
284 foo() has now been changed!
284
285
285 Here is an example of how to edit a code snippet successive
286 Here is an example of how to edit a code snippet successive
286 times. First we call the editor:
287 times. First we call the editor:
287
288
288 In [5]: ed
289 In [5]: ed
289 Editing... done. Executing edited code...
290 Editing... done. Executing edited code...
290 hello
291 hello
291 Out[5]: "print 'hello'n"
292 Out[5]: "print 'hello'n"
292
293
293 Now we call it again with the previous output (stored in _):
294 Now we call it again with the previous output (stored in _):
294
295
295 In [6]: ed _
296 In [6]: ed _
296 Editing... done. Executing edited code...
297 Editing... done. Executing edited code...
297 hello world
298 hello world
298 Out[6]: "print 'hello world'n"
299 Out[6]: "print 'hello world'n"
299
300
300 Now we call it with the output #8 (stored in _8, also as Out[8]):
301 Now we call it with the output #8 (stored in _8, also as Out[8]):
301
302
302 In [7]: ed _8
303 In [7]: ed _8
303 Editing... done. Executing edited code...
304 Editing... done. Executing edited code...
304 hello again
305 hello again
305 Out[7]: "print 'hello again'n"
306 Out[7]: "print 'hello again'n"
306 """
307 """
307
308
308 opts,args = self.parse_options(parameter_s,'prn:')
309 opts,args = self.parse_options(parameter_s,'prn:')
309
310
310 try:
311 try:
311 filename, lineno, _ = CodeMagics._find_edit_target(self.shell, args, opts, last_call)
312 filename, lineno, _ = CodeMagics._find_edit_target(self.shell, args, opts, last_call)
312 except MacroToEdit as e:
313 except MacroToEdit as e:
313 # TODO: Implement macro editing over 2 processes.
314 # TODO: Implement macro editing over 2 processes.
314 print("Macro editing not yet implemented in 2-process model.")
315 print("Macro editing not yet implemented in 2-process model.")
315 return
316 return
316
317
317 # Make sure we send to the client an absolute path, in case the working
318 # Make sure we send to the client an absolute path, in case the working
318 # directory of client and kernel don't match
319 # directory of client and kernel don't match
319 filename = os.path.abspath(filename)
320 filename = os.path.abspath(filename)
320
321
321 payload = {
322 payload = {
322 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
323 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
323 'filename' : filename,
324 'filename' : filename,
324 'line_number' : lineno
325 'line_number' : lineno
325 }
326 }
326 self.shell.payload_manager.write_payload(payload)
327 self.shell.payload_manager.write_payload(payload)
327
328
328 # A few magics that are adapted to the specifics of using pexpect and a
329 # A few magics that are adapted to the specifics of using pexpect and a
329 # remote terminal
330 # remote terminal
330
331
331 @line_magic
332 @line_magic
332 def clear(self, arg_s):
333 def clear(self, arg_s):
333 """Clear the terminal."""
334 """Clear the terminal."""
334 if os.name == 'posix':
335 if os.name == 'posix':
335 self.shell.system("clear")
336 self.shell.system("clear")
336 else:
337 else:
337 self.shell.system("cls")
338 self.shell.system("cls")
338
339
339 if os.name == 'nt':
340 if os.name == 'nt':
340 # This is the usual name in windows
341 # This is the usual name in windows
341 cls = line_magic('cls')(clear)
342 cls = line_magic('cls')(clear)
342
343
343 # Terminal pagers won't work over pexpect, but we do have our own pager
344 # Terminal pagers won't work over pexpect, but we do have our own pager
344
345
345 @line_magic
346 @line_magic
346 def less(self, arg_s):
347 def less(self, arg_s):
347 """Show a file through the pager.
348 """Show a file through the pager.
348
349
349 Files ending in .py are syntax-highlighted."""
350 Files ending in .py are syntax-highlighted."""
350 cont = open(arg_s).read()
351 cont = open(arg_s).read()
351 if arg_s.endswith('.py'):
352 if arg_s.endswith('.py'):
352 cont = self.shell.pycolorize(cont)
353 cont = self.shell.pycolorize(cont)
353 page.page(cont)
354 page.page(cont)
354
355
355 more = line_magic('more')(less)
356 more = line_magic('more')(less)
356
357
357 # Man calls a pager, so we also need to redefine it
358 # Man calls a pager, so we also need to redefine it
358 if os.name == 'posix':
359 if os.name == 'posix':
359 @line_magic
360 @line_magic
360 def man(self, arg_s):
361 def man(self, arg_s):
361 """Find the man page for the given command and display in pager."""
362 """Find the man page for the given command and display in pager."""
362 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
363 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
363 split=False))
364 split=False))
364
365
365 @line_magic
366 @line_magic
366 def connect_info(self, arg_s):
367 def connect_info(self, arg_s):
367 """Print information for connecting other clients to this kernel
368 """Print information for connecting other clients to this kernel
368
369
369 It will print the contents of this session's connection file, as well as
370 It will print the contents of this session's connection file, as well as
370 shortcuts for local clients.
371 shortcuts for local clients.
371
372
372 In the simplest case, when called from the most recently launched kernel,
373 In the simplest case, when called from the most recently launched kernel,
373 secondary clients can be connected, simply with:
374 secondary clients can be connected, simply with:
374
375
375 $> ipython <app> --existing
376 $> ipython <app> --existing
376
377
377 """
378 """
378
379
379 from IPython.core.application import BaseIPythonApplication as BaseIPApp
380 from IPython.core.application import BaseIPythonApplication as BaseIPApp
380
381
381 if BaseIPApp.initialized():
382 if BaseIPApp.initialized():
382 app = BaseIPApp.instance()
383 app = BaseIPApp.instance()
383 security_dir = app.profile_dir.security_dir
384 security_dir = app.profile_dir.security_dir
384 profile = app.profile
385 profile = app.profile
385 else:
386 else:
386 profile = 'default'
387 profile = 'default'
387 security_dir = ''
388 security_dir = ''
388
389
389 try:
390 try:
390 connection_file = get_connection_file()
391 connection_file = get_connection_file()
391 info = get_connection_info(unpack=False)
392 info = get_connection_info(unpack=False)
392 except Exception as e:
393 except Exception as e:
393 error("Could not get connection info: %r" % e)
394 error("Could not get connection info: %r" % e)
394 return
395 return
395
396
396 # add profile flag for non-default profile
397 # add profile flag for non-default profile
397 profile_flag = "--profile %s" % profile if profile != 'default' else ""
398 profile_flag = "--profile %s" % profile if profile != 'default' else ""
398
399
399 # if it's in the security dir, truncate to basename
400 # if it's in the security dir, truncate to basename
400 if security_dir == os.path.dirname(connection_file):
401 if security_dir == os.path.dirname(connection_file):
401 connection_file = os.path.basename(connection_file)
402 connection_file = os.path.basename(connection_file)
402
403
403
404
404 print (info + '\n')
405 print (info + '\n')
405 print ("Paste the above JSON into a file, and connect with:\n"
406 print ("Paste the above JSON into a file, and connect with:\n"
406 " $> ipython <app> --existing <file>\n"
407 " $> ipython <app> --existing <file>\n"
407 "or, if you are local, you can connect with just:\n"
408 "or, if you are local, you can connect with just:\n"
408 " $> ipython <app> --existing {0} {1}\n"
409 " $> ipython <app> --existing {0} {1}\n"
409 "or even just:\n"
410 "or even just:\n"
410 " $> ipython <app> --existing {1}\n"
411 " $> ipython <app> --existing {1}\n"
411 "if this is the most recent IPython session you have started.".format(
412 "if this is the most recent IPython session you have started.".format(
412 connection_file, profile_flag
413 connection_file, profile_flag
413 )
414 )
414 )
415 )
415
416
416 @line_magic
417 @line_magic
417 def qtconsole(self, arg_s):
418 def qtconsole(self, arg_s):
418 """Open a qtconsole connected to this kernel.
419 """Open a qtconsole connected to this kernel.
419
420
420 Useful for connecting a qtconsole to running notebooks, for better
421 Useful for connecting a qtconsole to running notebooks, for better
421 debugging.
422 debugging.
422 """
423 """
423
424
424 # %qtconsole should imply bind_kernel for engines:
425 # %qtconsole should imply bind_kernel for engines:
425 try:
426 try:
426 from IPython.parallel import bind_kernel
427 from IPython.parallel import bind_kernel
427 except ImportError:
428 except ImportError:
428 # technically possible, because parallel has higher pyzmq min-version
429 # technically possible, because parallel has higher pyzmq min-version
429 pass
430 pass
430 else:
431 else:
431 bind_kernel()
432 bind_kernel()
432
433
433 try:
434 try:
434 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
435 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
435 except Exception as e:
436 except Exception as e:
436 error("Could not start qtconsole: %r" % e)
437 error("Could not start qtconsole: %r" % e)
437 return
438 return
438
439
440 def safe_unicode(e):
441 """unicode(e) with various fallbacks. Used for exceptions, which may not be
442 safe to call unicode() on.
443 """
444 try:
445 return unicode(e)
446 except UnicodeError:
447 pass
448
449 try:
450 return py3compat.str_to_unicode(str(e))
451 except UnicodeError:
452 pass
453
454 try:
455 return py3compat.str_to_unicode(repr(e))
456 except UnicodeError:
457 pass
458
459 return u'Unrecoverably corrupt evalue'
460
439
461
440 class ZMQInteractiveShell(InteractiveShell):
462 class ZMQInteractiveShell(InteractiveShell):
441 """A subclass of InteractiveShell for ZMQ."""
463 """A subclass of InteractiveShell for ZMQ."""
442
464
443 displayhook_class = Type(ZMQShellDisplayHook)
465 displayhook_class = Type(ZMQShellDisplayHook)
444 display_pub_class = Type(ZMQDisplayPublisher)
466 display_pub_class = Type(ZMQDisplayPublisher)
445
467
446 # Override the traitlet in the parent class, because there's no point using
468 # Override the traitlet in the parent class, because there's no point using
447 # readline for the kernel. Can be removed when the readline code is moved
469 # readline for the kernel. Can be removed when the readline code is moved
448 # to the terminal frontend.
470 # to the terminal frontend.
449 colors_force = CBool(True)
471 colors_force = CBool(True)
450 readline_use = CBool(False)
472 readline_use = CBool(False)
451 # autoindent has no meaning in a zmqshell, and attempting to enable it
473 # autoindent has no meaning in a zmqshell, and attempting to enable it
452 # will print a warning in the absence of readline.
474 # will print a warning in the absence of readline.
453 autoindent = CBool(False)
475 autoindent = CBool(False)
454
476
455 exiter = Instance(ZMQExitAutocall)
477 exiter = Instance(ZMQExitAutocall)
456 def _exiter_default(self):
478 def _exiter_default(self):
457 return ZMQExitAutocall(self)
479 return ZMQExitAutocall(self)
458
480
459 def _exit_now_changed(self, name, old, new):
481 def _exit_now_changed(self, name, old, new):
460 """stop eventloop when exit_now fires"""
482 """stop eventloop when exit_now fires"""
461 if new:
483 if new:
462 loop = ioloop.IOLoop.instance()
484 loop = ioloop.IOLoop.instance()
463 loop.add_timeout(time.time()+0.1, loop.stop)
485 loop.add_timeout(time.time()+0.1, loop.stop)
464
486
465 keepkernel_on_exit = None
487 keepkernel_on_exit = None
466
488
467 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
489 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
468 # interactive input being read; we provide event loop support in ipkernel
490 # interactive input being read; we provide event loop support in ipkernel
469 from .eventloops import enable_gui
491 from .eventloops import enable_gui
470 enable_gui = staticmethod(enable_gui)
492 enable_gui = staticmethod(enable_gui)
471
493
472 def init_environment(self):
494 def init_environment(self):
473 """Configure the user's environment.
495 """Configure the user's environment.
474
496
475 """
497 """
476 env = os.environ
498 env = os.environ
477 # These two ensure 'ls' produces nice coloring on BSD-derived systems
499 # These two ensure 'ls' produces nice coloring on BSD-derived systems
478 env['TERM'] = 'xterm-color'
500 env['TERM'] = 'xterm-color'
479 env['CLICOLOR'] = '1'
501 env['CLICOLOR'] = '1'
480 # Since normal pagers don't work at all (over pexpect we don't have
502 # Since normal pagers don't work at all (over pexpect we don't have
481 # single-key control of the subprocess), try to disable paging in
503 # single-key control of the subprocess), try to disable paging in
482 # subprocesses as much as possible.
504 # subprocesses as much as possible.
483 env['PAGER'] = 'cat'
505 env['PAGER'] = 'cat'
484 env['GIT_PAGER'] = 'cat'
506 env['GIT_PAGER'] = 'cat'
485
507
486 # And install the payload version of page.
508 # And install the payload version of page.
487 install_payload_page()
509 install_payload_page()
488
510
489 def auto_rewrite_input(self, cmd):
511 def auto_rewrite_input(self, cmd):
490 """Called to show the auto-rewritten input for autocall and friends.
512 """Called to show the auto-rewritten input for autocall and friends.
491
513
492 FIXME: this payload is currently not correctly processed by the
514 FIXME: this payload is currently not correctly processed by the
493 frontend.
515 frontend.
494 """
516 """
495 new = self.prompt_manager.render('rewrite') + cmd
517 new = self.prompt_manager.render('rewrite') + cmd
496 payload = dict(
518 payload = dict(
497 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
519 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
498 transformed_input=new,
520 transformed_input=new,
499 )
521 )
500 self.payload_manager.write_payload(payload)
522 self.payload_manager.write_payload(payload)
501
523
502 def ask_exit(self):
524 def ask_exit(self):
503 """Engage the exit actions."""
525 """Engage the exit actions."""
504 self.exit_now = True
526 self.exit_now = True
505 payload = dict(
527 payload = dict(
506 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
528 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
507 exit=True,
529 exit=True,
508 keepkernel=self.keepkernel_on_exit,
530 keepkernel=self.keepkernel_on_exit,
509 )
531 )
510 self.payload_manager.write_payload(payload)
532 self.payload_manager.write_payload(payload)
511
533
512 def _showtraceback(self, etype, evalue, stb):
534 def _showtraceback(self, etype, evalue, stb):
513
535
514 exc_content = {
536 exc_content = {
515 u'traceback' : stb,
537 u'traceback' : stb,
516 u'ename' : unicode(etype.__name__),
538 u'ename' : unicode(etype.__name__),
517 u'evalue' : unicode(evalue)
539 u'evalue' : safe_unicode(evalue)
518 }
540 }
519
541
520 dh = self.displayhook
542 dh = self.displayhook
521 # Send exception info over pub socket for other clients than the caller
543 # Send exception info over pub socket for other clients than the caller
522 # to pick up
544 # to pick up
523 topic = None
545 topic = None
524 if dh.topic:
546 if dh.topic:
525 topic = dh.topic.replace(b'pyout', b'pyerr')
547 topic = dh.topic.replace(b'pyout', b'pyerr')
526
548
527 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header, ident=topic)
549 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header, ident=topic)
528
550
529 # FIXME - Hack: store exception info in shell object. Right now, the
551 # FIXME - Hack: store exception info in shell object. Right now, the
530 # caller is reading this info after the fact, we need to fix this logic
552 # caller is reading this info after the fact, we need to fix this logic
531 # to remove this hack. Even uglier, we need to store the error status
553 # to remove this hack. Even uglier, we need to store the error status
532 # here, because in the main loop, the logic that sets it is being
554 # here, because in the main loop, the logic that sets it is being
533 # skipped because runlines swallows the exceptions.
555 # skipped because runlines swallows the exceptions.
534 exc_content[u'status'] = u'error'
556 exc_content[u'status'] = u'error'
535 self._reply_content = exc_content
557 self._reply_content = exc_content
536 # /FIXME
558 # /FIXME
537
559
538 return exc_content
560 return exc_content
539
561
540 def set_next_input(self, text):
562 def set_next_input(self, text):
541 """Send the specified text to the frontend to be presented at the next
563 """Send the specified text to the frontend to be presented at the next
542 input cell."""
564 input cell."""
543 payload = dict(
565 payload = dict(
544 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
566 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
545 text=text
567 text=text
546 )
568 )
547 self.payload_manager.write_payload(payload)
569 self.payload_manager.write_payload(payload)
548
570
549 #-------------------------------------------------------------------------
571 #-------------------------------------------------------------------------
550 # Things related to magics
572 # Things related to magics
551 #-------------------------------------------------------------------------
573 #-------------------------------------------------------------------------
552
574
553 def init_magics(self):
575 def init_magics(self):
554 super(ZMQInteractiveShell, self).init_magics()
576 super(ZMQInteractiveShell, self).init_magics()
555 self.register_magics(KernelMagics)
577 self.register_magics(KernelMagics)
556
578
557
579
558
580
559 InteractiveShellABC.register(ZMQInteractiveShell)
581 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now