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