##// END OF EJS Templates
* The SVG payload matplotlib backend now works....
epatters -
Show More
@@ -0,0 +1,54 b''
1 """ A demo of Qt console-style IPython frontend.
2 """
3
4 # Systemm library imports
5 from PyQt4 import QtCore, QtGui
6
7 # Local imports
8 from IPython.external.argparse import ArgumentParser
9 from IPython.frontend.qt.kernelmanager import QtKernelManager
10 from ipython_widget import IPythonWidget
11 from rich_ipython_widget import RichIPythonWidget
12
13
14 def main():
15 """ Entry point for demo.
16 """
17 # Parse command line arguments.
18 parser = ArgumentParser()
19 parser.add_argument('--pylab', action='store_true',
20 help='start kernel with pylab enabled')
21 parser.add_argument('--rich', action='store_true',
22 help='use rich text frontend')
23 namespace = parser.parse_args()
24
25 # Don't let Qt or ZMQ swallow KeyboardInterupts.
26 import signal
27 signal.signal(signal.SIGINT, signal.SIG_DFL)
28
29 # Create a KernelManager and start a kernel.
30 kernel_manager = QtKernelManager()
31 if namespace.pylab:
32 if namespace.rich:
33 kernel_manager.start_kernel(pylab='payload-svg')
34 else:
35 kernel_manager.start_kernel(pylab='qt4')
36 else:
37 kernel_manager.start_kernel()
38 kernel_manager.start_channels()
39
40 # Launch the application.
41 app = QtGui.QApplication([])
42 if namespace.rich:
43 widget = RichIPythonWidget()
44 else:
45 widget = IPythonWidget()
46 widget.kernel_manager = kernel_manager
47 widget.setWindowTitle('Python')
48 widget.resize(640, 480)
49 widget.show()
50 app.exec_()
51
52
53 if __name__ == '__main__':
54 main()
@@ -0,0 +1,43 b''
1 # System library imports
2 from PyQt4 import QtCore, QtGui
3
4 # Local imports
5 from IPython.frontend.qt.util import image_from_svg
6 from ipython_widget import IPythonWidget
7
8
9 class RichIPythonWidget(IPythonWidget):
10 """ An IPythonWidget that supports rich text, including lists, images, and
11 tables. Note that raw performance will be reduced compared to the plain
12 text version.
13 """
14
15 #---------------------------------------------------------------------------
16 # 'QObject' interface
17 #---------------------------------------------------------------------------
18
19 def __init__(self, parent=None):
20 """ Create a RichIPythonWidget.
21 """
22 super(RichIPythonWidget, self).__init__(kind='rich', parent=parent)
23
24 #---------------------------------------------------------------------------
25 # 'FrontendWidget' interface
26 #---------------------------------------------------------------------------
27
28 def _handle_execute_payload(self, payload):
29 """ Reimplemented to handle pylab plot payloads.
30 """
31 super(RichIPythonWidget, self)._handle_execute_payload(payload)
32
33 plot_payload = payload.get('plot', None)
34 if plot_payload and plot_payload['format'] == 'svg':
35 try:
36 image = image_from_svg(plot_payload['data'])
37 except ValueError:
38 self._append_plain_text('Received invalid plot data.')
39 else:
40 cursor = self._get_end_cursor()
41 cursor.insertBlock()
42 cursor.insertImage(image)
43 cursor.insertBlock()
@@ -111,9 +111,7 b' class CallTipWidget(QtGui.QLabel):'
111 point = text_edit.mapToGlobal(point)
111 point = text_edit.mapToGlobal(point)
112 self.move(point)
112 self.move(point)
113 self.setText(tip)
113 self.setText(tip)
114 if self.isVisible():
115 self.resize(self.sizeHint())
114 self.resize(self.sizeHint())
116 else:
117 self.show()
115 self.show()
118 return True
116 return True
119
117
@@ -337,12 +337,16 b' class FrontendWidget(HistoryConsoleWidget):'
337 # before writing a new prompt.
337 # before writing a new prompt.
338 self.kernel_manager.sub_channel.flush()
338 self.kernel_manager.sub_channel.flush()
339
339
340 status = reply['content']['status']
340 content = reply['content']
341 if status == 'error':
341 status = content['status']
342 if status == 'ok':
343 self._handle_execute_payload(content['payload'])
344 elif status == 'error':
342 self._handle_execute_error(reply)
345 self._handle_execute_error(reply)
343 elif status == 'aborted':
346 elif status == 'aborted':
344 text = "ERROR: ABORTED\n"
347 text = "ERROR: ABORTED\n"
345 self._append_plain_text(text)
348 self._append_plain_text(text)
349
346 self._hidden = True
350 self._hidden = True
347 self._show_interpreter_prompt()
351 self._show_interpreter_prompt()
348 self.executed.emit(reply)
352 self.executed.emit(reply)
@@ -352,6 +356,9 b' class FrontendWidget(HistoryConsoleWidget):'
352 traceback = ''.join(content['traceback'])
356 traceback = ''.join(content['traceback'])
353 self._append_plain_text(traceback)
357 self._append_plain_text(traceback)
354
358
359 def _handle_execute_payload(self, payload):
360 pass
361
355 def _handle_complete_reply(self, rep):
362 def _handle_complete_reply(self, rep):
356 cursor = self._get_cursor()
363 cursor = self._get_cursor()
357 if rep['parent_header']['msg_id'] == self._complete_id and \
364 if rep['parent_header']['msg_id'] == self._complete_id and \
@@ -182,25 +182,3 b' class IPythonWidget(FrontendWidget):'
182 """
182 """
183 block = self._control.document().lastBlock()
183 block = self._control.document().lastBlock()
184 self._previous_prompt_blocks.append((block, block.length()))
184 self._previous_prompt_blocks.append((block, block.length()))
185
186
187 if __name__ == '__main__':
188 from IPython.frontend.qt.kernelmanager import QtKernelManager
189
190 # Don't let Qt or ZMQ swallow KeyboardInterupts.
191 import signal
192 signal.signal(signal.SIGINT, signal.SIG_DFL)
193
194 # Create a KernelManager.
195 kernel_manager = QtKernelManager()
196 kernel_manager.start_kernel()
197 kernel_manager.start_channels()
198
199 # Launch the application.
200 app = QtGui.QApplication([])
201 widget = IPythonWidget()
202 widget.kernel_manager = kernel_manager
203 widget.setWindowTitle('Python')
204 widget.resize(640, 480)
205 widget.show()
206 app.exec_()
@@ -153,10 +153,6 b' class QtKernelManager(KernelManager, QtCore.QObject):'
153 xreq_channel_class = QtXReqSocketChannel
153 xreq_channel_class = QtXReqSocketChannel
154 rep_channel_class = QtRepSocketChannel
154 rep_channel_class = QtRepSocketChannel
155
155
156 def __init__(self, *args, **kw):
157 QtCore.QObject.__init__(self)
158 KernelManager.__init__(self, *args, **kw)
159
160 #---------------------------------------------------------------------------
156 #---------------------------------------------------------------------------
161 # 'object' interface
157 # 'object' interface
162 #---------------------------------------------------------------------------
158 #---------------------------------------------------------------------------
@@ -181,15 +181,16 b' class Kernel(object):'
181 # FIXME: This is adapted from IPython.lib.pylabtools.pylab_activate.
181 # FIXME: This is adapted from IPython.lib.pylabtools.pylab_activate.
182 # Common funtionality should be refactored.
182 # Common funtionality should be refactored.
183
183
184 import matplotlib
185
186 # We must set the desired backend before importing pylab.
184 # We must set the desired backend before importing pylab.
185 import matplotlib
187 if backend:
186 if backend:
188 matplotlib.use(self._pylab_map[backend])
187 backend_id = self._pylab_map[backend]
189
188 if backend_id.startswith('module://'):
190 # This must be imported last in the matplotlib series, after
189 # Work around bug in matplotlib: matplotlib.use converts the
191 # backend/interactivity choices have been made.
190 # backend_id to lowercase even if a module name is specified!
192 import matplotlib.pylab as pylab
191 matplotlib.rcParams['backend'] = backend_id
192 else:
193 matplotlib.use(backend_id)
193
194
194 # Import numpy as np/pyplot as plt are conventions we're trying to
195 # Import numpy as np/pyplot as plt are conventions we're trying to
195 # somewhat standardize on. Making them available to users by default
196 # somewhat standardize on. Making them available to users by default
@@ -511,7 +512,8 b" given, the GUI backend is matplotlib's, otherwise use one of: \\"
511 kernel.start()
512 kernel.start()
512
513
513
514
514 def launch_kernel(xrep_port=0, pub_port=0, req_port=0, independent=False):
515 def launch_kernel(xrep_port=0, pub_port=0, req_port=0,
516 pylab=False, independent=False):
515 """ Launches a localhost kernel, binding to the specified ports.
517 """ Launches a localhost kernel, binding to the specified ports.
516
518
517 Parameters
519 Parameters
@@ -525,6 +527,11 b' def launch_kernel(xrep_port=0, pub_port=0, req_port=0, independent=False):'
525 req_port : int, optional
527 req_port : int, optional
526 The port to use for the REQ (raw input) channel.
528 The port to use for the REQ (raw input) channel.
527
529
530 pylab : bool or string, optional (default False)
531 If not False, the kernel will be launched with pylab enabled. If a
532 string is passed, matplotlib will use the specified backend. Otherwise,
533 matplotlib's default backend will be used.
534
528 independent : bool, optional (default False)
535 independent : bool, optional (default False)
529 If set, the kernel process is guaranteed to survive if this process
536 If set, the kernel process is guaranteed to survive if this process
530 dies. If not set, an effort is made to ensure that the kernel is killed
537 dies. If not set, an effort is made to ensure that the kernel is killed
@@ -558,10 +565,16 b' def launch_kernel(xrep_port=0, pub_port=0, req_port=0, independent=False):'
558 if req_port <= 0:
565 if req_port <= 0:
559 req_port = ports.pop(0)
566 req_port = ports.pop(0)
560
567
561 # Spawn a kernel.
568 # Build the kernel launch command.
562 command = 'from IPython.zmq.kernel import main; main()'
569 command = 'from IPython.zmq.kernel import main; main()'
563 arguments = [ sys.executable, '-c', command, '--xrep', str(xrep_port),
570 arguments = [ sys.executable, '-c', command, '--xrep', str(xrep_port),
564 '--pub', str(pub_port), '--req', str(req_port) ]
571 '--pub', str(pub_port), '--req', str(req_port) ]
572 if pylab:
573 arguments.append('--pylab')
574 if isinstance(pylab, basestring):
575 arguments.append(pylab)
576
577 # Spawn a kernel.
565 if independent:
578 if independent:
566 if sys.platform == 'win32':
579 if sys.platform == 'win32':
567 proc = Popen(['start', '/b'] + arguments, shell=True)
580 proc = Popen(['start', '/b'] + arguments, shell=True)
@@ -433,22 +433,21 b' class KernelManager(HasTraits):'
433 # The kernel process with which the KernelManager is communicating.
433 # The kernel process with which the KernelManager is communicating.
434 kernel = Instance(Popen)
434 kernel = Instance(Popen)
435
435
436 # The addresses for the communication channels.
437 xreq_address = TCPAddress((LOCALHOST, 0))
438 sub_address = TCPAddress((LOCALHOST, 0))
439 rep_address = TCPAddress((LOCALHOST, 0))
440
436 # The classes to use for the various channels.
441 # The classes to use for the various channels.
437 xreq_channel_class = Type(XReqSocketChannel)
442 xreq_channel_class = Type(XReqSocketChannel)
438 sub_channel_class = Type(SubSocketChannel)
443 sub_channel_class = Type(SubSocketChannel)
439 rep_channel_class = Type(RepSocketChannel)
444 rep_channel_class = Type(RepSocketChannel)
440
445
441 # Protected traits.
446 # Protected traits.
442 xreq_address = TCPAddress((LOCALHOST, 0))
443 sub_address = TCPAddress((LOCALHOST, 0))
444 rep_address = TCPAddress((LOCALHOST, 0))
445 _xreq_channel = Any
447 _xreq_channel = Any
446 _sub_channel = Any
448 _sub_channel = Any
447 _rep_channel = Any
449 _rep_channel = Any
448
450
449 def __init__(self, **kwargs):
450 super(KernelManager, self).__init__(**kwargs)
451
452 #--------------------------------- -----------------------------------------
451 #--------------------------------------------------------------------------
453 # Channel management methods:
452 # Channel management methods:
454 #--------------------------------------------------------------------------
453 #--------------------------------------------------------------------------
@@ -486,11 +485,16 b' class KernelManager(HasTraits):'
486 # Kernel process management methods:
485 # Kernel process management methods:
487 #--------------------------------------------------------------------------
486 #--------------------------------------------------------------------------
488
487
489 def start_kernel(self):
488 def start_kernel(self, pylab=False):
490 """Starts a kernel process and configures the manager to use it.
489 """Starts a kernel process and configures the manager to use it.
491
490
492 If random ports (port=0) are being used, this method must be called
491 If random ports (port=0) are being used, this method must be called
493 before the channels are created.
492 before the channels are created.
493
494 Parameters:
495 -----------
496 pylab : bool or string, optional (default False)
497 See IPython.zmq.kernel.launch_kernel for documentation.
494 """
498 """
495 xreq, sub, rep = self.xreq_address, self.sub_address, self.rep_address
499 xreq, sub, rep = self.xreq_address, self.sub_address, self.rep_address
496 if xreq[0] != LOCALHOST or sub[0] != LOCALHOST or rep[0] != LOCALHOST:
500 if xreq[0] != LOCALHOST or sub[0] != LOCALHOST or rep[0] != LOCALHOST:
@@ -499,7 +503,7 b' class KernelManager(HasTraits):'
499 "configured properly.")
503 "configured properly.")
500
504
501 self.kernel, xrep, pub, req = launch_kernel(
505 self.kernel, xrep, pub, req = launch_kernel(
502 xrep_port=xreq[1], pub_port=sub[1], req_port=rep[1])
506 xrep_port=xreq[1], pub_port=sub[1], req_port=rep[1], pylab=pylab)
503 self.xreq_address = (LOCALHOST, xrep)
507 self.xreq_address = (LOCALHOST, xrep)
504 self.sub_address = (LOCALHOST, pub)
508 self.sub_address = (LOCALHOST, pub)
505 self.rep_address = (LOCALHOST, req)
509 self.rep_address = (LOCALHOST, req)
@@ -12,7 +12,7 b' from backend_payload import add_plot_payload'
12 def show():
12 def show():
13 """ Deliver a SVG payload.
13 """ Deliver a SVG payload.
14 """
14 """
15 figure_manager = Gcf.get_actve()
15 figure_manager = Gcf.get_active()
16 if figure_manager is not None:
16 if figure_manager is not None:
17 data = svg_from_canvas(figure_manager.canvas)
17 data = svg_from_canvas(figure_manager.canvas)
18 add_plot_payload('svg', data)
18 add_plot_payload('svg', data)
General Comments 0
You need to be logged in to leave comments. Login now