From 6e6dcc901b7ee9ac37db43218fca2b3432b86c8f 2010-08-19 21:28:05 From: Brian Granger Date: 2010-08-19 21:28:05 Subject: [PATCH] First working draft of new payload system. --- diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 711b2f9..e5a4a79 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -1901,6 +1901,9 @@ class InteractiveShell(Configurable, Magic): - 1: an error occurred. """ + # Clear the payload before executing new code. + self.payload_manager.clear_payload() + # Set our own excepthook in case the user code tries to call it # directly, so that the IPython crash handler doesn't get triggered old_excepthook,sys.excepthook = sys.excepthook, self.excepthook diff --git a/IPython/core/payload.py b/IPython/core/payload.py index 4903581..9fd90f9 100644 --- a/IPython/core/payload.py +++ b/IPython/core/payload.py @@ -32,10 +32,10 @@ class PayloadManager(Configurable): def write_payload(self, data): if not isinstance(data, dict): raise TypeError('Each payload write must be a dict, got: %r' % data) - self.payload.append(data) - - def reset_payload(self): - self.payload = [] + self._payload.append(data) def read_payload(self): return self._payload + + def clear_payload(self): + self._payload = [] diff --git a/IPython/frontend/qt/console/rich_ipython_widget.py b/IPython/frontend/qt/console/rich_ipython_widget.py index 58ea93c..53bda65 100644 --- a/IPython/frontend/qt/console/rich_ipython_widget.py +++ b/IPython/frontend/qt/console/rich_ipython_widget.py @@ -60,20 +60,28 @@ class RichIPythonWidget(IPythonWidget): """ Reimplemented to handle matplotlib plot payloads. """ payload = msg['content']['payload'] - plot_payload = payload.get('plot', None) - if plot_payload and plot_payload['format'] == 'svg': - svg = plot_payload['data'] - try: - image = svg_to_image(svg) - except ValueError: - self._append_plain_text('Received invalid plot data.') - else: - format = self._add_image(image) - format.setProperty(self._svg_text_format_property, svg) - cursor = self._get_end_cursor() - cursor.insertBlock() - cursor.insertImage(format) - cursor.insertBlock() + if payload: + for item in payload: + if item['type'] == 'plot': + if item['format'] == 'svg': + svg = item['data'] + try: + image = svg_to_image(svg) + except ValueError: + self._append_plain_text('Received invalid plot data.') + else: + format = self._add_image(image) + format.setProperty(self._svg_text_format_property, svg) + cursor = self._get_end_cursor() + cursor.insertBlock() + cursor.insertImage(format) + cursor.insertBlock() + else: + # Add other plot formats here! + pass + else: + # Add other payload types here! + pass else: super(RichIPythonWidget, self)._process_execute_ok(msg) diff --git a/IPython/zmq/ipkernel.py b/IPython/zmq/ipkernel.py index fc17cf8..7959124 100755 --- a/IPython/zmq/ipkernel.py +++ b/IPython/zmq/ipkernel.py @@ -49,9 +49,6 @@ class Kernel(Configurable): pub_socket = Instance('zmq.Socket') req_socket = Instance('zmq.Socket') - # The global kernel instance. - _kernel = None - # Maps user-friendly backend names to matplotlib backend identifiers. _pylab_map = { 'tk': 'TkAgg', 'gtk': 'GTKAgg', @@ -69,9 +66,6 @@ class Kernel(Configurable): self.shell.displayhook.session = self.session self.shell.displayhook.pub_socket = self.pub_socket - # Protected variables. - self._exec_payload = {} - # Build dict of handlers for message types msg_types = [ 'execute_request', 'complete_request', 'object_info_request', 'prompt_request', @@ -80,11 +74,6 @@ class Kernel(Configurable): for msg_type in msg_types: self.handlers[msg_type] = getattr(self, msg_type) - def add_exec_payload(self, key, value): - """ Adds a key/value pair to the execute payload. - """ - self._exec_payload[key] = value - def activate_pylab(self, backend=None, import_all=True): """ Activates pylab in this kernel's namespace. @@ -126,21 +115,9 @@ class Kernel(Configurable): matplotlib.interactive(True) - @classmethod - def get_kernel(cls): - """ Return the global kernel instance or raise a RuntimeError if it does - not exist. - """ - if cls._kernel is None: - raise RuntimeError("Kernel not started!") - else: - return cls._kernel - def start(self): """ Start the kernel main loop. """ - # Set the global kernel instance. - self.__class__._kernel = self while True: ident = self.reply_socket.recv() @@ -169,9 +146,6 @@ class Kernel(Configurable): pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent) self.pub_socket.send_json(pyin_msg) - # Clear the execute payload from the last request. - self._exec_payload = {} - try: # Replace raw_input. Note that is not sufficient to replace # raw_input in the user namespace. @@ -182,7 +156,6 @@ class Kernel(Configurable): self.shell.displayhook.set_parent(parent) self.shell.runlines(code) - # exec comp_code in self.user_ns, self.user_ns except: etype, evalue, tb = sys.exc_info() tb = traceback.format_exception(etype, evalue, tb) @@ -196,7 +169,11 @@ class Kernel(Configurable): self.pub_socket.send_json(exc_msg) reply_content = exc_content else: - reply_content = { 'status' : 'ok', 'payload' : self._exec_payload } + payload = self.shell.payload_manager.read_payload() + # Be agressive about clearing the payload because we don't want + # it to sit in memory until the next execute_request comes in. + self.shell.payload_manager.clear_payload() + reply_content = { 'status' : 'ok', 'payload' : payload } # Compute the prompt information prompt_number = self.shell.displayhook.prompt_count diff --git a/IPython/zmq/pylab/backend_payload.py b/IPython/zmq/pylab/backend_payload.py index c83b860..8ad92d5 100644 --- a/IPython/zmq/pylab/backend_payload.py +++ b/IPython/zmq/pylab/backend_payload.py @@ -2,7 +2,7 @@ """ # Local imports. -from IPython.zmq.ipkernel import Kernel +from IPython.core.interactiveshell import InteractiveShell def add_plot_payload(format, data, metadata={}): @@ -19,5 +19,5 @@ def add_plot_payload(format, data, metadata={}): metadata : dict, optional [default empty] Allows for specification of additional information about the plot data. """ - payload = dict(format=format, data=data, metadata=metadata) - Kernel.get_kernel().add_exec_payload('plot', payload) + payload = dict(type='plot', format=format, data=data, metadata=metadata) + InteractiveShell.instance().payload_manager.write_payload(payload)