Skip to content

Commit

Permalink
Re #5939. Add a mechanism to avoid blocking MantidPlot while running.
Browse files Browse the repository at this point in the history
We replace the IPython method that actually executes the entered code
with one that then calls the original one on a separate thread so that
we can continue to process GUI events while the command runs.
  • Loading branch information
RussellTaylor committed Oct 4, 2013
1 parent 4923824 commit a92a0fb
Showing 1 changed file with 42 additions and 1 deletion.
43 changes: 42 additions & 1 deletion Code/Mantid/MantidPlot/ipython_widget/mantid_ipython_widget.py
@@ -1,7 +1,40 @@
import threading
import types

from PyQt4 import QtGui

from IPython.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.qt.inprocess import QtInProcessKernelManager


def our_run_code(self, code_obj):
""" Method which we replace the run_code method of IPython's InteractiveShell class.
It call's the original method (renamed to ipython_run_code) on a separate thread
so that we can avoid locking up the whole of MantidPlot while a command runs
Parameters
----------
code_obj : code object
A compiled code object, to be executed
Returns
-------
False : Always, as it doesn't seem to matter.
"""
t = threading.Thread(target=self.ipython_run_code, args=[code_obj])
t.start()
while t.is_alive():
QtGui.QApplication.processEvents()
# We don't capture the return value of the ipython_run_code method but as far as I can tell
# it doesn't make any difference what's returned
return 0


class MantidIPythonWidget(RichIPythonWidget):
""" Extends IPython's qt widget to include setting up and in-process kernel as well as the
Mantid environment, plus our trick to avoid blocking the event loop while processing commands.
This widget is set in the QDockWidget that houses the script interpreter within ApplicationWindow.
"""

def __init__(self, *args, **kw):
super(MantidIPythonWidget, self).__init__(*args, **kw)
Expand All @@ -16,7 +49,15 @@ def __init__(self, *args, **kw):
from os import path
mantidplotpath = path.split(path.dirname(__file__))[0] # It's the directory above this one
mantidplotrc = path.join(mantidplotpath, 'mantidplotrc.py')
kernel.shell.run_line_magic('run',mantidplotrc)
shell = kernel.shell
shell.run_line_magic('run',mantidplotrc)

# These 3 lines replace the run_code method of IPython's InteractiveShell class (of which the
# shell variable is a derived instance) with our method defined above. The original method
# is renamed so that we can call it from within the our_run_code method.
f = shell.run_code
shell.run_code = types.MethodType(our_run_code, shell)
shell.ipython_run_code = f

kernel_client = kernel_manager.client()
kernel_client.start_channels()
Expand Down

0 comments on commit a92a0fb

Please sign in to comment.