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)