##// END OF EJS Templates
update zmq shell magics...
MinRK -
Show More
@@ -16,11 +16,9 b' machinery. This should thus be thought of as scaffolding.'
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 import inspect
20 19 import os
21 20 import sys
22 21 import time
23 from subprocess import Popen, PIPE
24 22
25 23 # System library imports
26 24 from zmq.eventloop import ioloop
@@ -29,11 +27,11 b' from zmq.eventloop import ioloop'
29 27 from IPython.core.interactiveshell import (
30 28 InteractiveShell, InteractiveShellABC
31 29 )
32 from IPython.core import page, pylabtools
30 from IPython.core import page
33 31 from IPython.core.autocall import ZMQExitAutocall
34 32 from IPython.core.displaypub import DisplayPublisher
35 from IPython.core.macro import Macro
36 from IPython.core.magics import MacroToEdit
33 from IPython.core.magics import MacroToEdit, CodeMagics
34 from IPython.core.magic import magics_class, line_magic, Magics
37 35 from IPython.core.payloadpage import install_payload_page
38 36 from IPython.lib.kernel import (
39 37 get_connection_file, get_connection_info, connect_qtconsole
@@ -41,7 +39,6 b' from IPython.lib.kernel import ('
41 39 from IPython.testing.skipdoctest import skip_doctest
42 40 from IPython.utils import io
43 41 from IPython.utils.jsonutil import json_clean
44 from IPython.utils.path import get_py_filename
45 42 from IPython.utils.process import arg_split
46 43 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes
47 44 from IPython.utils.warn import warn, error
@@ -99,106 +96,8 b' class ZMQDisplayPublisher(DisplayPublisher):'
99 96 parent=self.parent_header, ident=self.topic,
100 97 )
101 98
102 class ZMQInteractiveShell(InteractiveShell):
103 """A subclass of InteractiveShell for ZMQ."""
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
99 @magics_class
100 class KernelMagics(Magics):
202 101 #------------------------------------------------------------------------
203 102 # Magic overrides
204 103 #------------------------------------------------------------------------
@@ -207,7 +106,8 b' class ZMQInteractiveShell(InteractiveShell):'
207 106 # the magics which this class needs to implement differently from the base
208 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 111 """Toggle doctest mode on and off.
212 112
213 113 This mode is intended to make IPython behave as much as possible like a
@@ -253,12 +153,12 b' class ZMQInteractiveShell(InteractiveShell):'
253 153 # turn on
254 154 ptformatter.pprint = False
255 155 disp_formatter.plain_text_only = True
256 shell.magic_xmode('Plain')
156 shell.magic('xmode Plain')
257 157 else:
258 158 # turn off
259 159 ptformatter.pprint = dstore.rc_pprint
260 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 163 # Store new mode and inform on console
264 164 dstore.mode = bool(1-int(mode))
@@ -267,12 +167,16 b' class ZMQInteractiveShell(InteractiveShell):'
267 167
268 168 # Send the payload back so that clients can modify their prompt display
269 169 payload = dict(
270 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
170 source='IPython.zmq.zmqshell.ZMQInteractiveShell.doctest_mode',
271 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 177 @skip_doctest
275 def magic_edit(self,parameter_s='',last_call=['','']):
178 @line_magic
179 def edit(self, parameter_s='', last_call=['','']):
276 180 """Bring up an editor and execute the resulting code.
277 181
278 182 Usage:
@@ -404,7 +308,7 b' class ZMQInteractiveShell(InteractiveShell):'
404 308 opts,args = self.parse_options(parameter_s,'prn:')
405 309
406 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 312 except MacroToEdit as e:
409 313 # TODO: Implement macro editing over 2 processes.
410 314 print("Macro editing not yet implemented in 2-process model.")
@@ -419,12 +323,13 b' class ZMQInteractiveShell(InteractiveShell):'
419 323 'filename' : filename,
420 324 'line_number' : lineno
421 325 }
422 self.payload_manager.write_payload(payload)
326 self.shell.payload_manager.write_payload(payload)
423 327
424 328 # A few magics that are adapted to the specifics of using pexpect and a
425 329 # remote terminal
426 330
427 def magic_clear(self, arg_s):
331 @line_magic
332 def clear(self, arg_s):
428 333 """Clear the terminal."""
429 334 if os.name == 'posix':
430 335 self.shell.system("clear")
@@ -433,11 +338,12 b' class ZMQInteractiveShell(InteractiveShell):'
433 338
434 339 if os.name == 'nt':
435 340 # This is the usual name in windows
436 magic_cls = magic_clear
341 cls = line_magic('cls')(clear)
437 342
438 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 347 """Show a file through the pager.
442 348
443 349 Files ending in .py are syntax-highlighted."""
@@ -446,11 +352,12 b' class ZMQInteractiveShell(InteractiveShell):'
446 352 cont = self.shell.pycolorize(cont)
447 353 page.page(cont)
448 354
449 magic_more = magic_less
355 more = line_magic('more')(less)
450 356
451 357 # Man calls a pager, so we also need to redefine it
452 358 if os.name == 'posix':
453 def magic_man(self, arg_s):
359 @line_magic
360 def man(self, arg_s):
454 361 """Find the man page for the given command and display in pager."""
455 362 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
456 363 split=False))
@@ -459,12 +366,15 b' class ZMQInteractiveShell(InteractiveShell):'
459 366 # magics at startup that are only for the gui. Once the gui app has proper
460 367 # profile and configuration management, we can have it initialize a kernel
461 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 372 """Show a basic reference about the GUI console."""
464 373 from IPython.core.usage import gui_reference
465 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 378 """Print information for connecting other clients to this kernel
469 379
470 380 It will print the contents of this session's connection file, as well as
@@ -514,7 +424,8 b' class ZMQInteractiveShell(InteractiveShell):'
514 424 )
515 425 )
516 426
517 def magic_qtconsole(self, arg_s):
427 @line_magic
428 def qtconsole(self, arg_s):
518 429 """Open a qtconsole connected to this kernel.
519 430
520 431 Useful for connecting a qtconsole to running notebooks, for better
@@ -526,6 +437,107 b' class ZMQInteractiveShell(InteractiveShell):'
526 437 error("Could not start qtconsole: %r" % e)
527 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 541 def set_next_input(self, text):
530 542 """Send the specified text to the frontend to be presented at the next
531 543 input cell."""
@@ -534,6 +546,15 b' class ZMQInteractiveShell(InteractiveShell):'
534 546 text=text
535 547 )
536 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 560 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now