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