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,10 +111,8 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(): |
|
114 | self.resize(self.sizeHint()) | |
115 | self.resize(self.sizeHint()) |
|
115 | self.show() | |
116 | else: |
|
|||
117 | self.show() |
|
|||
118 | return True |
|
116 | return True | |
119 |
|
117 | |||
120 | #-------------------------------------------------------------------------- |
|
118 | #-------------------------------------------------------------------------- |
@@ -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 |
|
|
340 | content = reply['content'] | |
341 |
|
|
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 |
|
|
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, |
|
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 | |
@@ -557,11 +564,17 b' def launch_kernel(xrep_port=0, pub_port=0, req_port=0, independent=False):' | |||||
557 | pub_port = ports.pop(0) |
|
564 | pub_port = ports.pop(0) | |
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,23 +433,22 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): |
|
451 | #-------------------------------------------------------------------------- | |
450 | super(KernelManager, self).__init__(**kwargs) |
|
|||
451 |
|
||||
452 | #--------------------------------- ----------------------------------------- |
|
|||
453 | # Channel management methods: |
|
452 | # Channel management methods: | |
454 | #-------------------------------------------------------------------------- |
|
453 | #-------------------------------------------------------------------------- | |
455 |
|
454 | |||
@@ -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