Source code for schrodinger.ui.qt.schrodinger_ipython

import types
import warnings

from IPython import get_ipython
from qtconsole import inprocess
from qtconsole import rich_jupyter_widget

from schrodinger import get_maestro
from schrodinger.ui.qt.appframework2 import af2

with warnings.catch_warnings():
    warnings.filterwarnings(action="ignore",
                            category=DeprecationWarning,
                            module="ipykernel",
                            message="the imp module")
    from ipykernel.inprocess import ipkernel


[docs]class SchrodingerIPython(af2.App):
[docs] def setPanelOptions(self): super(SchrodingerIPython, self).setPanelOptions() self.title = 'IPython with Maestro integration'
[docs] def setup(self): super(SchrodingerIPython, self).setup() # Add a warning filter so that we don't get deprecation warnings printed # to the terminal every time the user hits Enter warnings.filterwarnings("ignore", category=DeprecationWarning, module=r".*(jupyter)|(traitlets)") # Ignore all DeprecationWarnings that get generated during setup. # Traitlets somehow ignores the warning filters for one warning it # generates, so we use record=True to temporarily override # warning.showwarning and suppress that one as well. with warnings.catch_warnings(record=True): # Create an in-process kernel self.kernel_manager = KernelManagerWithUserModule() self.kernel_manager.start_kernel() kernel = self.kernel_manager.kernel kernel.gui = 'qt' self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() # disable Jedi to fix tab-completion # in maestro IPython shell BLDMGR-4613 get_ipython().Completer.use_jedi = False self.widget = rich_jupyter_widget.RichJupyterWidget() self.widget.kernel_manager = self.kernel_manager self.widget.kernel_client = self.kernel_client self.widget.execute("%matplotlib inline") if get_maestro(): self.widget.execute("from schrodinger import maestro") # A blank execute call is required to clear the input area. # Otherwise the terminal will start with "from schrodinger import # maestro" on the current input line. self.widget.execute("")
[docs] def layOut(self): super(SchrodingerIPython, self).layOut() self.main_layout.addWidget(self.widget)
[docs]class KernelManagerWithUserModule(inprocess.QtInProcessKernelManager): """ This kernel manager starts its kernel with a custom namespace rather than replacing the __main__ namespace, which is the standard InProcessKernelManager behavior. If the __main__ namespace gets replaced, then we'll get exceptions every time Maestro runs a Python command. (When executing Python code from C++, Maestro temporarily modifies sys.path to ensure that the executed code can import any modules that it needs. This code is runs in the __main__ namespace, so replacing that namespace removes the sys import and the temporary variables that Maestro expects. See MAE-35487.) """
[docs] def __init__(self, *args, **kwargs): super(KernelManagerWithUserModule, self).__init__(*args, **kwargs) self._user_module = types.ModuleType( "ipython_kernel_namespace", "The module that the IPython InProcessKernel is executed in")
[docs] def start_kernel(self, **kwargs): """ Start the kernel using a non-__main__ namespace. Note that all arguments to this method are ignored, as that's the behavior of QtInProcessKernelManager. """ self.kernel = ipkernel.InProcessKernel(parent=self, session=self.session, user_module=self._user_module)