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