kernelmanager.py
220 lines
| 8.0 KiB
| text/x-python
|
PythonLexer
epatters
|
r2643 | """ Defines a KernelManager that provides signals and slots. | ||
epatters
|
r2609 | """ | ||
# System library imports. | ||||
from PyQt4 import QtCore | ||||
Brian Granger
|
r2695 | import zmq | ||
epatters
|
r2609 | |||
# IPython imports. | ||||
Brian Granger
|
r2786 | from IPython.utils.traitlets import Type | ||
epatters
|
r2611 | from IPython.zmq.kernelmanager import KernelManager, SubSocketChannel, \ | ||
Brian Granger
|
r2910 | XReqSocketChannel, RepSocketChannel, HBSocketChannel | ||
epatters
|
r2643 | from util import MetaQObjectHasTraits | ||
epatters
|
r2609 | |||
Brian Granger
|
r2711 | # When doing multiple inheritance from QtCore.QObject and other classes | ||
# the calling of the parent __init__'s is a subtle issue: | ||||
# * QtCore.QObject does not call super so you can't use super and put | ||||
# QObject first in the inheritance list. | ||||
# * QtCore.QObject.__init__ takes 1 argument, the parent. So if you are going | ||||
# to use super, any class that comes before QObject must pass it something | ||||
# reasonable. | ||||
Brian Granger
|
r2726 | # In summary, I don't think using super in these situations will work. | ||
# Instead we will need to call the __init__ methods of both parents | ||||
# by hand. Not pretty, but it works. | ||||
Brian Granger
|
r2695 | |||
epatters
|
r2609 | class QtSubSocketChannel(SubSocketChannel, QtCore.QObject): | ||
# Emitted when any message is received. | ||||
epatters
|
r2611 | message_received = QtCore.pyqtSignal(object) | ||
epatters
|
r2609 | |||
epatters
|
r2770 | # Emitted when a message of type 'stream' is received. | ||
stream_received = QtCore.pyqtSignal(object) | ||||
epatters
|
r2609 | |||
epatters
|
r2770 | # Emitted when a message of type 'pyin' is received. | ||
pyin_received = QtCore.pyqtSignal(object) | ||||
# Emitted when a message of type 'pyout' is received. | ||||
pyout_received = QtCore.pyqtSignal(object) | ||||
# Emitted when a message of type 'pyerr' is received. | ||||
pyerr_received = QtCore.pyqtSignal(object) | ||||
# Emitted when a crash report message is received from the kernel's | ||||
# last-resort sys.excepthook. | ||||
crash_received = QtCore.pyqtSignal(object) | ||||
epatters
|
r2611 | |||
#--------------------------------------------------------------------------- | ||||
# 'object' interface | ||||
#--------------------------------------------------------------------------- | ||||
def __init__(self, *args, **kw): | ||||
""" Reimplemented to ensure that QtCore.QObject is initialized first. | ||||
""" | ||||
QtCore.QObject.__init__(self) | ||||
SubSocketChannel.__init__(self, *args, **kw) | ||||
epatters
|
r2609 | |||
#--------------------------------------------------------------------------- | ||||
# 'SubSocketChannel' interface | ||||
#--------------------------------------------------------------------------- | ||||
def call_handlers(self, msg): | ||||
""" Reimplemented to emit signals instead of making callbacks. | ||||
""" | ||||
# Emit the generic signal. | ||||
self.message_received.emit(msg) | ||||
# Emit signals for specialized message types. | ||||
msg_type = msg['msg_type'] | ||||
epatters
|
r2770 | signal = getattr(self, msg_type + '_received', None) | ||
if signal: | ||||
signal.emit(msg) | ||||
elif msg_type in ('stdout', 'stderr'): | ||||
self.stream_received.emit(msg) | ||||
epatters
|
r2609 | |||
epatters
|
r2614 | def flush(self): | ||
""" Reimplemented to ensure that signals are dispatched immediately. | ||||
""" | ||||
super(QtSubSocketChannel, self).flush() | ||||
QtCore.QCoreApplication.instance().processEvents() | ||||
epatters
|
r2609 | |||
class QtXReqSocketChannel(XReqSocketChannel, QtCore.QObject): | ||||
# Emitted when any message is received. | ||||
epatters
|
r2611 | message_received = QtCore.pyqtSignal(object) | ||
epatters
|
r2609 | |||
# Emitted when a reply has been received for the corresponding request type. | ||||
epatters
|
r2611 | execute_reply = QtCore.pyqtSignal(object) | ||
complete_reply = QtCore.pyqtSignal(object) | ||||
object_info_reply = QtCore.pyqtSignal(object) | ||||
#--------------------------------------------------------------------------- | ||||
# 'object' interface | ||||
#--------------------------------------------------------------------------- | ||||
def __init__(self, *args, **kw): | ||||
""" Reimplemented to ensure that QtCore.QObject is initialized first. | ||||
""" | ||||
QtCore.QObject.__init__(self) | ||||
XReqSocketChannel.__init__(self, *args, **kw) | ||||
Brian Granger
|
r2711 | |||
epatters
|
r2609 | #--------------------------------------------------------------------------- | ||
# 'XReqSocketChannel' interface | ||||
#--------------------------------------------------------------------------- | ||||
def call_handlers(self, msg): | ||||
""" Reimplemented to emit signals instead of making callbacks. | ||||
""" | ||||
# Emit the generic signal. | ||||
self.message_received.emit(msg) | ||||
# Emit signals for specialized message types. | ||||
msg_type = msg['msg_type'] | ||||
signal = getattr(self, msg_type, None) | ||||
if signal: | ||||
signal.emit(msg) | ||||
class QtRepSocketChannel(RepSocketChannel, QtCore.QObject): | ||||
epatters
|
r2707 | # Emitted when any message is received. | ||
message_received = QtCore.pyqtSignal(object) | ||||
epatters
|
r2730 | # Emitted when an input request is received. | ||
input_requested = QtCore.pyqtSignal(object) | ||||
epatters
|
r2707 | |||
epatters
|
r2611 | #--------------------------------------------------------------------------- | ||
# 'object' interface | ||||
#--------------------------------------------------------------------------- | ||||
def __init__(self, *args, **kw): | ||||
""" Reimplemented to ensure that QtCore.QObject is initialized first. | ||||
""" | ||||
QtCore.QObject.__init__(self) | ||||
RepSocketChannel.__init__(self, *args, **kw) | ||||
epatters
|
r2707 | #--------------------------------------------------------------------------- | ||
# 'RepSocketChannel' interface | ||||
#--------------------------------------------------------------------------- | ||||
def call_handlers(self, msg): | ||||
""" Reimplemented to emit signals instead of making callbacks. | ||||
""" | ||||
# Emit the generic signal. | ||||
self.message_received.emit(msg) | ||||
# Emit signals for specialized message types. | ||||
msg_type = msg['msg_type'] | ||||
epatters
|
r2730 | if msg_type == 'input_request': | ||
self.input_requested.emit(msg) | ||||
epatters
|
r2611 | |||
epatters
|
r2770 | |||
Brian Granger
|
r2910 | class QtHBSocketChannel(HBSocketChannel, QtCore.QObject): | ||
# Emitted when the kernel has died. | ||||
kernel_died = QtCore.pyqtSignal(object) | ||||
#--------------------------------------------------------------------------- | ||||
# 'object' interface | ||||
#--------------------------------------------------------------------------- | ||||
def __init__(self, *args, **kw): | ||||
""" Reimplemented to ensure that QtCore.QObject is initialized first. | ||||
""" | ||||
QtCore.QObject.__init__(self) | ||||
HBSocketChannel.__init__(self, *args, **kw) | ||||
#--------------------------------------------------------------------------- | ||||
# 'RepSocketChannel' interface | ||||
#--------------------------------------------------------------------------- | ||||
def call_handlers(self, since_last_heartbeat): | ||||
""" Reimplemented to emit signals instead of making callbacks. | ||||
""" | ||||
# Emit the generic signal. | ||||
self.kernel_died.emit(since_last_heartbeat) | ||||
epatters
|
r2643 | class QtKernelManager(KernelManager, QtCore.QObject): | ||
""" A KernelManager that provides signals and slots. | ||||
epatters
|
r2611 | """ | ||
epatters
|
r2643 | __metaclass__ = MetaQObjectHasTraits | ||
# Emitted when the kernel manager has started listening. | ||||
epatters
|
r2701 | started_channels = QtCore.pyqtSignal() | ||
epatters
|
r2643 | |||
# Emitted when the kernel manager has stopped listening. | ||||
epatters
|
r2701 | stopped_channels = QtCore.pyqtSignal() | ||
epatters
|
r2643 | |||
# Use Qt-specific channel classes that emit signals. | ||||
Brian Granger
|
r2786 | sub_channel_class = Type(QtSubSocketChannel) | ||
xreq_channel_class = Type(QtXReqSocketChannel) | ||||
rep_channel_class = Type(QtRepSocketChannel) | ||||
Brian Granger
|
r2910 | hb_channel_class = Type(QtHBSocketChannel) | ||
epatters
|
r2643 | |||
#--------------------------------------------------------------------------- | ||||
epatters
|
r2701 | # 'object' interface | ||
#--------------------------------------------------------------------------- | ||||
def __init__(self, *args, **kw): | ||||
""" Reimplemented to ensure that QtCore.QObject is initialized first. | ||||
""" | ||||
QtCore.QObject.__init__(self) | ||||
KernelManager.__init__(self, *args, **kw) | ||||
#--------------------------------------------------------------------------- | ||||
epatters
|
r2643 | # 'KernelManager' interface | ||
#--------------------------------------------------------------------------- | ||||
Brian Granger
|
r2699 | def start_channels(self): | ||
epatters
|
r2643 | """ Reimplemented to emit signal. | ||
""" | ||||
Brian Granger
|
r2699 | super(QtKernelManager, self).start_channels() | ||
epatters
|
r2701 | self.started_channels.emit() | ||
epatters
|
r2643 | |||
Brian Granger
|
r2699 | def stop_channels(self): | ||
epatters
|
r2643 | """ Reimplemented to emit signal. | ||
""" | ||||
Brian Granger
|
r2699 | super(QtKernelManager, self).stop_channels() | ||
epatters
|
r2701 | self.stopped_channels.emit() | ||