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