diff --git a/IPython/frontend/qt/console/frontend_widget.py b/IPython/frontend/qt/console/frontend_widget.py
index ad21249..d039e27 100644
--- a/IPython/frontend/qt/console/frontend_widget.py
+++ b/IPython/frontend/qt/console/frontend_widget.py
@@ -339,9 +339,19 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
def _process_execute_ok(self, msg):
""" Process a reply for a successful execution equest.
"""
+ payload = msg['content']['payload']
+ for item in payload:
+ if not self._process_execute_payload(item):
+ warning = 'Received unknown payload of type %s\n'
+ self._append_plain_text(warning % repr(item['source']))
+
+ def _process_execute_payload(self, item):
+ """ Process a single payload item from the list of payload items in an
+ execution reply. Returns whether the payload was handled.
+ """
# The basic FrontendWidget doesn't handle payloads, as they are a
# mechanism for going beyond the standard Python interpreter model.
- pass
+ return False
def _show_interpreter_prompt(self):
""" Shows a prompt for the interpreter.
diff --git a/IPython/frontend/qt/console/ipython_widget.py b/IPython/frontend/qt/console/ipython_widget.py
index 2478b90..5689268 100644
--- a/IPython/frontend/qt/console/ipython_widget.py
+++ b/IPython/frontend/qt/console/ipython_widget.py
@@ -24,8 +24,8 @@ class IPythonWidget(FrontendWidget):
"""
# Signal emitted when an editor is needed for a file and the editor has been
- # specified as 'custom'.
- custom_edit_requested = QtCore.pyqtSignal(object)
+ # specified as 'custom'. See 'set_editor' for more information.
+ custom_edit_requested = QtCore.pyqtSignal(object, int)
# The default stylesheet: black text on a white background.
default_stylesheet = """
@@ -51,9 +51,13 @@ class IPythonWidget(FrontendWidget):
in_prompt = 'In [%i]: '
out_prompt = 'Out[%i]: '
- # FrontendWidget protected class attributes.
+ # FrontendWidget protected class variables.
#_input_splitter_class = IPythonInputSplitter
+ # IPythonWidget protected class variables.
+ _payload_source_edit = 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic'
+ _payload_source_page = 'IPython.zmq.page.page'
+
#---------------------------------------------------------------------------
# 'object' interface
#---------------------------------------------------------------------------
@@ -116,6 +120,18 @@ class IPythonWidget(FrontendWidget):
self._append_html(traceback)
+ def _process_execute_payload(self, item):
+ """ Reimplemented to handle %edit and paging payloads.
+ """
+ if item['source'] == self._payload_source_edit:
+ self.edit(item['filename'], item['line_number'])
+ return True
+ elif item['source'] == self._payload_source_page:
+ self._page(item['data'])
+ return True
+ else:
+ return False
+
def _show_interpreter_prompt(self, number=None, input_sep='\n'):
""" Reimplemented for IPython-style prompts.
"""
@@ -170,13 +186,16 @@ class IPythonWidget(FrontendWidget):
# 'IPythonWidget' interface
#---------------------------------------------------------------------------
- def edit(self, filename):
+ def edit(self, filename, line=None):
""" Opens a Python script for editing.
Parameters:
-----------
filename : str
A path to a local system file.
+
+ line : int, optional
+ A line of interest in the file.
Raises:
-------
@@ -189,7 +208,7 @@ class IPythonWidget(FrontendWidget):
message = 'Failed to open %s with the default application'
raise OSError(message % repr(filename))
elif self._editor is None:
- self.custom_edit_requested.emit(filename)
+ self.custom_edit_requested.emit(filename, line)
else:
Popen(self._editor + [filename])
@@ -211,8 +230,8 @@ class IPythonWidget(FrontendWidget):
This parameter also takes two special values:
'default' : Files will be edited with the system default
application for Python files.
- 'custom' : Emit a 'custom_edit_requested(str)' signal instead
- of opening an editor.
+ 'custom' : Emit a 'custom_edit_requested(str, int)' signal
+ instead of opening an editor.
"""
if editor == 'default':
self._editor = 'default'
diff --git a/IPython/frontend/qt/console/rich_ipython_widget.py b/IPython/frontend/qt/console/rich_ipython_widget.py
index 66a5e68..c38946c 100644
--- a/IPython/frontend/qt/console/rich_ipython_widget.py
+++ b/IPython/frontend/qt/console/rich_ipython_widget.py
@@ -14,7 +14,8 @@ class RichIPythonWidget(IPythonWidget):
text version.
"""
- # Protected class variables.
+ # RichIPythonWidget protected class variables.
+ _payload_source_plot = 'IPython.zmq.pylab.backend_payload.add_plot_payload'
_svg_text_format_property = 1
#---------------------------------------------------------------------------
@@ -58,55 +59,29 @@ class RichIPythonWidget(IPythonWidget):
# 'FrontendWidget' protected interface
#---------------------------------------------------------------------------
- def _process_execute_ok(self, msg):
+ def _process_execute_payload(self, item):
""" Reimplemented to handle matplotlib plot payloads.
"""
- payload = msg['content']['payload']
- for item in payload:
- if item['source'] == 'IPython.zmq.pylab.backend_payload.add_plot_payload':
- 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()
+ if item['source'] == self._payload_source_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:
- # Add other plot formats here!
- pass
- elif item['source'] == 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic':
- # TODO: I have implmented the logic for TextMate on the Mac.
- # But, we need to allow payload handlers on the non-rich
- # text IPython widget as well. Furthermore, we should probably
- # move these handlers to separate methods. But, we need to
- # be very careful to process the payload list in order. Thus,
- # we will probably need a _handle_payload method of the
- # base class that dispatches to the separate handler methods
- # for each payload source. If a particular subclass doesn't
- # have a handler for a payload source, it should at least
- # print a nice message.
- filename = item['filename']
- line_number = item['line_number']
- if line_number is None:
- cmd = 'mate %s' % filename
- else:
- cmd = 'mate -l %s %s' % (line_number, filename)
- os.system(cmd)
- elif item['source'] == 'IPython.zmq.page.page':
- # TODO: This is probably a good place to start, but Evan can
- # add better paging capabilities.
- self._append_plain_text(item['data'])
+ 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()
+ return True
else:
- # Add other payload types here!
- pass
+ # Add other plot formats here!
+ return False
else:
- super(RichIPythonWidget, self)._process_execute_ok(msg)
+ return super(RichIPythonWidget, self)._process_execute_ok(msg)
#---------------------------------------------------------------------------
# 'RichIPythonWidget' protected interface