##// END OF EJS Templates
Revert commit that fixed gh-617 as it broke %run in the Qt console....
Fernando Perez -
Show More
@@ -1,451 +1,457 b''
1 1 """A ZMQ-based subclass of InteractiveShell.
2 2
3 3 This code is meant to ease the refactoring of the base InteractiveShell into
4 4 something with a cleaner architecture for 2-process use, without actually
5 5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 6 we subclass and override what we want to fix. Once this is working well, we
7 7 can go back to the base class and refactor the code for a cleaner inheritance
8 8 implementation that doesn't rely on so much monkeypatching.
9 9
10 10 But this lets us maintain a fully working IPython as we develop the new
11 11 machinery. This should thus be thought of as scaffolding.
12 12 """
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 19 import inspect
20 20 import os
21 21
22 22 # Our own
23 23 from IPython.core.interactiveshell import (
24 24 InteractiveShell, InteractiveShellABC
25 25 )
26 26 from IPython.core import page
27 27 from IPython.core.autocall import ZMQExitAutocall
28 28 from IPython.core.displaypub import DisplayPublisher
29 29 from IPython.core.macro import Macro
30 30 from IPython.core.magic import MacroToEdit
31 31 from IPython.core.payloadpage import install_payload_page
32 32 from IPython.utils import io
33 33 from IPython.utils.path import get_py_filename
34 34 from IPython.utils.traitlets import Instance, Type, Dict, CBool
35 35 from IPython.utils.warn import warn
36 36 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_png
37 37 from IPython.zmq.session import extract_header
38 38 from session import Session
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Globals and side-effects
42 42 #-----------------------------------------------------------------------------
43 43
44 44 # Install the payload version of page.
45 45 install_payload_page()
46 46
47 47 #-----------------------------------------------------------------------------
48 48 # Functions and classes
49 49 #-----------------------------------------------------------------------------
50 50
51 51 class ZMQDisplayPublisher(DisplayPublisher):
52 52 """A display publisher that publishes data using a ZeroMQ PUB socket."""
53 53
54 54 session = Instance(Session)
55 55 pub_socket = Instance('zmq.Socket')
56 56 parent_header = Dict({})
57 57
58 58 def set_parent(self, parent):
59 59 """Set the parent for outbound messages."""
60 60 self.parent_header = extract_header(parent)
61 61
62 62 def publish(self, source, data, metadata=None):
63 63 if metadata is None:
64 64 metadata = {}
65 65 self._validate_data(source, data, metadata)
66 66 content = {}
67 67 content['source'] = source
68 68 _encode_png(data)
69 69 content['data'] = data
70 70 content['metadata'] = metadata
71 71 self.session.send(
72 72 self.pub_socket, u'display_data', content,
73 73 parent=self.parent_header
74 74 )
75 75
76 76
77 77 class ZMQInteractiveShell(InteractiveShell):
78 78 """A subclass of InteractiveShell for ZMQ."""
79 79
80 80 displayhook_class = Type(ZMQShellDisplayHook)
81 81 display_pub_class = Type(ZMQDisplayPublisher)
82 82
83 83 # Override the traitlet in the parent class, because there's no point using
84 84 # readline for the kernel. Can be removed when the readline code is moved
85 85 # to the terminal frontend.
86 readline_use = CBool(False)
86
87 # FIXME. This is disabled for now, even though it may cause problems under
88 # Windows, because it breaks %run in the Qt console. See gh-617 for more
89 # details. Re-enable once we've fully tested that %run works in the Qt
90 # console with syntax highlighting in tracebacks.
91 # readline_use = CBool(False)
92 # /FIXME
87 93
88 94 exiter = Instance(ZMQExitAutocall)
89 95 def _exiter_default(self):
90 96 return ZMQExitAutocall(self)
91 97
92 98 keepkernel_on_exit = None
93 99
94 100 def init_environment(self):
95 101 """Configure the user's environment.
96 102
97 103 """
98 104 env = os.environ
99 105 # These two ensure 'ls' produces nice coloring on BSD-derived systems
100 106 env['TERM'] = 'xterm-color'
101 107 env['CLICOLOR'] = '1'
102 108 # Since normal pagers don't work at all (over pexpect we don't have
103 109 # single-key control of the subprocess), try to disable paging in
104 110 # subprocesses as much as possible.
105 111 env['PAGER'] = 'cat'
106 112 env['GIT_PAGER'] = 'cat'
107 113
108 114 def auto_rewrite_input(self, cmd):
109 115 """Called to show the auto-rewritten input for autocall and friends.
110 116
111 117 FIXME: this payload is currently not correctly processed by the
112 118 frontend.
113 119 """
114 120 new = self.displayhook.prompt1.auto_rewrite() + cmd
115 121 payload = dict(
116 122 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
117 123 transformed_input=new,
118 124 )
119 125 self.payload_manager.write_payload(payload)
120 126
121 127 def ask_exit(self):
122 128 """Engage the exit actions."""
123 129 payload = dict(
124 130 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
125 131 exit=True,
126 132 keepkernel=self.keepkernel_on_exit,
127 133 )
128 134 self.payload_manager.write_payload(payload)
129 135
130 136 def _showtraceback(self, etype, evalue, stb):
131 137
132 138 exc_content = {
133 139 u'traceback' : stb,
134 140 u'ename' : unicode(etype.__name__),
135 141 u'evalue' : unicode(evalue)
136 142 }
137 143
138 144 dh = self.displayhook
139 145 # Send exception info over pub socket for other clients than the caller
140 146 # to pick up
141 147 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', exc_content, dh.parent_header)
142 148
143 149 # FIXME - Hack: store exception info in shell object. Right now, the
144 150 # caller is reading this info after the fact, we need to fix this logic
145 151 # to remove this hack. Even uglier, we need to store the error status
146 152 # here, because in the main loop, the logic that sets it is being
147 153 # skipped because runlines swallows the exceptions.
148 154 exc_content[u'status'] = u'error'
149 155 self._reply_content = exc_content
150 156 # /FIXME
151 157
152 158 return exc_content
153 159
154 160 #------------------------------------------------------------------------
155 161 # Magic overrides
156 162 #------------------------------------------------------------------------
157 163 # Once the base class stops inheriting from magic, this code needs to be
158 164 # moved into a separate machinery as well. For now, at least isolate here
159 165 # the magics which this class needs to implement differently from the base
160 166 # class, or that are unique to it.
161 167
162 168 def magic_doctest_mode(self,parameter_s=''):
163 169 """Toggle doctest mode on and off.
164 170
165 171 This mode is intended to make IPython behave as much as possible like a
166 172 plain Python shell, from the perspective of how its prompts, exceptions
167 173 and output look. This makes it easy to copy and paste parts of a
168 174 session into doctests. It does so by:
169 175
170 176 - Changing the prompts to the classic ``>>>`` ones.
171 177 - Changing the exception reporting mode to 'Plain'.
172 178 - Disabling pretty-printing of output.
173 179
174 180 Note that IPython also supports the pasting of code snippets that have
175 181 leading '>>>' and '...' prompts in them. This means that you can paste
176 182 doctests from files or docstrings (even if they have leading
177 183 whitespace), and the code will execute correctly. You can then use
178 184 '%history -t' to see the translated history; this will give you the
179 185 input after removal of all the leading prompts and whitespace, which
180 186 can be pasted back into an editor.
181 187
182 188 With these features, you can switch into this mode easily whenever you
183 189 need to do testing and changes to doctests, without having to leave
184 190 your existing IPython session.
185 191 """
186 192
187 193 from IPython.utils.ipstruct import Struct
188 194
189 195 # Shorthands
190 196 shell = self.shell
191 197 disp_formatter = self.shell.display_formatter
192 198 ptformatter = disp_formatter.formatters['text/plain']
193 199 # dstore is a data store kept in the instance metadata bag to track any
194 200 # changes we make, so we can undo them later.
195 201 dstore = shell.meta.setdefault('doctest_mode', Struct())
196 202 save_dstore = dstore.setdefault
197 203
198 204 # save a few values we'll need to recover later
199 205 mode = save_dstore('mode', False)
200 206 save_dstore('rc_pprint', ptformatter.pprint)
201 207 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
202 208 save_dstore('xmode', shell.InteractiveTB.mode)
203 209
204 210 if mode == False:
205 211 # turn on
206 212 ptformatter.pprint = False
207 213 disp_formatter.plain_text_only = True
208 214 shell.magic_xmode('Plain')
209 215 else:
210 216 # turn off
211 217 ptformatter.pprint = dstore.rc_pprint
212 218 disp_formatter.plain_text_only = dstore.rc_plain_text_only
213 219 shell.magic_xmode(dstore.xmode)
214 220
215 221 # Store new mode and inform on console
216 222 dstore.mode = bool(1-int(mode))
217 223 mode_label = ['OFF','ON'][dstore.mode]
218 224 print('Doctest mode is:', mode_label)
219 225
220 226 # Send the payload back so that clients can modify their prompt display
221 227 payload = dict(
222 228 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
223 229 mode=dstore.mode)
224 230 self.payload_manager.write_payload(payload)
225 231
226 232 def magic_edit(self,parameter_s='',last_call=['','']):
227 233 """Bring up an editor and execute the resulting code.
228 234
229 235 Usage:
230 236 %edit [options] [args]
231 237
232 238 %edit runs IPython's editor hook. The default version of this hook is
233 239 set to call the __IPYTHON__.rc.editor command. This is read from your
234 240 environment variable $EDITOR. If this isn't found, it will default to
235 241 vi under Linux/Unix and to notepad under Windows. See the end of this
236 242 docstring for how to change the editor hook.
237 243
238 244 You can also set the value of this editor via the command line option
239 245 '-editor' or in your ipythonrc file. This is useful if you wish to use
240 246 specifically for IPython an editor different from your typical default
241 247 (and for Windows users who typically don't set environment variables).
242 248
243 249 This command allows you to conveniently edit multi-line code right in
244 250 your IPython session.
245 251
246 252 If called without arguments, %edit opens up an empty editor with a
247 253 temporary file and will execute the contents of this file when you
248 254 close it (don't forget to save it!).
249 255
250 256
251 257 Options:
252 258
253 259 -n <number>: open the editor at a specified line number. By default,
254 260 the IPython editor hook uses the unix syntax 'editor +N filename', but
255 261 you can configure this by providing your own modified hook if your
256 262 favorite editor supports line-number specifications with a different
257 263 syntax.
258 264
259 265 -p: this will call the editor with the same data as the previous time
260 266 it was used, regardless of how long ago (in your current session) it
261 267 was.
262 268
263 269 -r: use 'raw' input. This option only applies to input taken from the
264 270 user's history. By default, the 'processed' history is used, so that
265 271 magics are loaded in their transformed version to valid Python. If
266 272 this option is given, the raw input as typed as the command line is
267 273 used instead. When you exit the editor, it will be executed by
268 274 IPython's own processor.
269 275
270 276 -x: do not execute the edited code immediately upon exit. This is
271 277 mainly useful if you are editing programs which need to be called with
272 278 command line arguments, which you can then do using %run.
273 279
274 280
275 281 Arguments:
276 282
277 283 If arguments are given, the following possibilites exist:
278 284
279 285 - The arguments are numbers or pairs of colon-separated numbers (like
280 286 1 4:8 9). These are interpreted as lines of previous input to be
281 287 loaded into the editor. The syntax is the same of the %macro command.
282 288
283 289 - If the argument doesn't start with a number, it is evaluated as a
284 290 variable and its contents loaded into the editor. You can thus edit
285 291 any string which contains python code (including the result of
286 292 previous edits).
287 293
288 294 - If the argument is the name of an object (other than a string),
289 295 IPython will try to locate the file where it was defined and open the
290 296 editor at the point where it is defined. You can use `%edit function`
291 297 to load an editor exactly at the point where 'function' is defined,
292 298 edit it and have the file be executed automatically.
293 299
294 300 If the object is a macro (see %macro for details), this opens up your
295 301 specified editor with a temporary file containing the macro's data.
296 302 Upon exit, the macro is reloaded with the contents of the file.
297 303
298 304 Note: opening at an exact line is only supported under Unix, and some
299 305 editors (like kedit and gedit up to Gnome 2.8) do not understand the
300 306 '+NUMBER' parameter necessary for this feature. Good editors like
301 307 (X)Emacs, vi, jed, pico and joe all do.
302 308
303 309 - If the argument is not found as a variable, IPython will look for a
304 310 file with that name (adding .py if necessary) and load it into the
305 311 editor. It will execute its contents with execfile() when you exit,
306 312 loading any code in the file into your interactive namespace.
307 313
308 314 After executing your code, %edit will return as output the code you
309 315 typed in the editor (except when it was an existing file). This way
310 316 you can reload the code in further invocations of %edit as a variable,
311 317 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
312 318 the output.
313 319
314 320 Note that %edit is also available through the alias %ed.
315 321
316 322 This is an example of creating a simple function inside the editor and
317 323 then modifying it. First, start up the editor:
318 324
319 325 In [1]: ed
320 326 Editing... done. Executing edited code...
321 327 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
322 328
323 329 We can then call the function foo():
324 330
325 331 In [2]: foo()
326 332 foo() was defined in an editing session
327 333
328 334 Now we edit foo. IPython automatically loads the editor with the
329 335 (temporary) file where foo() was previously defined:
330 336
331 337 In [3]: ed foo
332 338 Editing... done. Executing edited code...
333 339
334 340 And if we call foo() again we get the modified version:
335 341
336 342 In [4]: foo()
337 343 foo() has now been changed!
338 344
339 345 Here is an example of how to edit a code snippet successive
340 346 times. First we call the editor:
341 347
342 348 In [5]: ed
343 349 Editing... done. Executing edited code...
344 350 hello
345 351 Out[5]: "print 'hello'n"
346 352
347 353 Now we call it again with the previous output (stored in _):
348 354
349 355 In [6]: ed _
350 356 Editing... done. Executing edited code...
351 357 hello world
352 358 Out[6]: "print 'hello world'n"
353 359
354 360 Now we call it with the output #8 (stored in _8, also as Out[8]):
355 361
356 362 In [7]: ed _8
357 363 Editing... done. Executing edited code...
358 364 hello again
359 365 Out[7]: "print 'hello again'n"
360 366
361 367
362 368 Changing the default editor hook:
363 369
364 370 If you wish to write your own editor hook, you can put it in a
365 371 configuration file which you load at startup time. The default hook
366 372 is defined in the IPython.core.hooks module, and you can use that as a
367 373 starting example for further modifications. That file also has
368 374 general instructions on how to set a new hook for use once you've
369 375 defined it."""
370 376
371 377 opts,args = self.parse_options(parameter_s,'prn:')
372 378
373 379 try:
374 380 filename, lineno, _ = self._find_edit_target(args, opts, last_call)
375 381 except MacroToEdit as e:
376 382 # TODO: Implement macro editing over 2 processes.
377 383 print("Macro editing not yet implemented in 2-process model.")
378 384 return
379 385
380 386 # Make sure we send to the client an absolute path, in case the working
381 387 # directory of client and kernel don't match
382 388 filename = os.path.abspath(filename)
383 389
384 390 payload = {
385 391 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
386 392 'filename' : filename,
387 393 'line_number' : lineno
388 394 }
389 395 self.payload_manager.write_payload(payload)
390 396
391 397 def magic_gui(self, *args, **kwargs):
392 398 raise NotImplementedError(
393 399 'GUI support must be enabled in command line options.')
394 400
395 401 def magic_pylab(self, *args, **kwargs):
396 402 raise NotImplementedError(
397 403 'pylab support must be enabled in command line options.')
398 404
399 405 # A few magics that are adapted to the specifics of using pexpect and a
400 406 # remote terminal
401 407
402 408 def magic_clear(self, arg_s):
403 409 """Clear the terminal."""
404 410 if os.name == 'posix':
405 411 self.shell.system("clear")
406 412 else:
407 413 self.shell.system("cls")
408 414
409 415 if os.name == 'nt':
410 416 # This is the usual name in windows
411 417 magic_cls = magic_clear
412 418
413 419 # Terminal pagers won't work over pexpect, but we do have our own pager
414 420
415 421 def magic_less(self, arg_s):
416 422 """Show a file through the pager.
417 423
418 424 Files ending in .py are syntax-highlighted."""
419 425 cont = open(arg_s).read()
420 426 if arg_s.endswith('.py'):
421 427 cont = self.shell.pycolorize(cont)
422 428 page.page(cont)
423 429
424 430 magic_more = magic_less
425 431
426 432 # Man calls a pager, so we also need to redefine it
427 433 if os.name == 'posix':
428 434 def magic_man(self, arg_s):
429 435 """Find the man page for the given command and display in pager."""
430 436 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
431 437 split=False))
432 438
433 439 # FIXME: this is specific to the GUI, so we should let the gui app load
434 440 # magics at startup that are only for the gui. Once the gui app has proper
435 441 # profile and configuration management, we can have it initialize a kernel
436 442 # with a special config file that provides these.
437 443 def magic_guiref(self, arg_s):
438 444 """Show a basic reference about the GUI console."""
439 445 from IPython.core.usage import gui_reference
440 446 page.page(gui_reference, auto_html=True)
441 447
442 448 def set_next_input(self, text):
443 449 """Send the specified text to the frontend to be presented at the next
444 450 input cell."""
445 451 payload = dict(
446 452 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
447 453 text=text
448 454 )
449 455 self.payload_manager.write_payload(payload)
450 456
451 457 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now