base_frontend_mixin.py
150 lines
| 5.7 KiB
| text/x-python
|
PythonLexer
epatters
|
r2770 | """ Defines a convenient mix-in class for implementing Qt frontends. | ||
""" | ||||
class BaseFrontendMixin(object): | ||||
""" A mix-in class for implementing Qt frontends. | ||||
To handle messages of a particular type, frontends need only define an | ||||
appropriate handler method. For example, to handle 'stream' messaged, define | ||||
a '_handle_stream(msg)' method. | ||||
""" | ||||
#--------------------------------------------------------------------------- | ||||
# 'BaseFrontendMixin' concrete interface | ||||
#--------------------------------------------------------------------------- | ||||
MinRK
|
r10302 | _kernel_client = None | ||
MinRK
|
r10311 | _kernel_manager = None | ||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r10311 | @property | ||
def kernel_client(self): | ||||
"""Returns the current kernel client.""" | ||||
MinRK
|
r10288 | return self._kernel_client | ||
epatters
|
r2770 | |||
MinRK
|
r10311 | @kernel_client.setter | ||
def kernel_client(self, kernel_client): | ||||
MinRK
|
r10288 | """Disconnect from the current kernel client (if any) and set a new | ||
kernel client. | ||||
epatters
|
r2770 | """ | ||
MinRK
|
r10288 | # Disconnect the old kernel client, if necessary. | ||
old_client = self._kernel_client | ||||
if old_client is not None: | ||||
old_client.started_channels.disconnect(self._started_channels) | ||||
old_client.stopped_channels.disconnect(self._stopped_channels) | ||||
# Disconnect the old kernel client's channels. | ||||
old_client.iopub_channel.message_received.disconnect(self._dispatch) | ||||
old_client.shell_channel.message_received.disconnect(self._dispatch) | ||||
old_client.stdin_channel.message_received.disconnect(self._dispatch) | ||||
old_client.hb_channel.kernel_died.disconnect( | ||||
epatters
|
r2913 | self._handle_kernel_died) | ||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r10288 | # Handle the case where the old kernel client is still listening. | ||
if old_client.channels_running: | ||||
epatters
|
r2770 | self._stopped_channels() | ||
MinRK
|
r10288 | # Set the new kernel client. | ||
self._kernel_client = kernel_client | ||||
if kernel_client is None: | ||||
epatters
|
r2770 | return | ||
MinRK
|
r10288 | # Connect the new kernel client. | ||
kernel_client.started_channels.connect(self._started_channels) | ||||
kernel_client.stopped_channels.connect(self._stopped_channels) | ||||
epatters
|
r2770 | |||
MinRK
|
r10288 | # Connect the new kernel client's channels. | ||
kernel_client.iopub_channel.message_received.connect(self._dispatch) | ||||
kernel_client.shell_channel.message_received.connect(self._dispatch) | ||||
kernel_client.stdin_channel.message_received.connect(self._dispatch) | ||||
MinRK
|
r10311 | # hb_channel | ||
MinRK
|
r10288 | kernel_client.hb_channel.kernel_died.connect(self._handle_kernel_died) | ||
Brian Granger
|
r2910 | |||
MinRK
|
r10288 | # Handle the case where the kernel client started channels before | ||
epatters
|
r2770 | # we connected. | ||
MinRK
|
r10288 | if kernel_client.channels_running: | ||
epatters
|
r2770 | self._started_channels() | ||
MinRK
|
r10311 | @property | ||
def kernel_manager(self): | ||||
"""The kernel manager, if any""" | ||||
return self._kernel_manager | ||||
@kernel_manager.setter | ||||
def kernel_manager(self, kernel_manager): | ||||
old_man = self._kernel_manager | ||||
if old_man is not None: | ||||
old_man.kernel_restarted.disconnect(self._handle_kernel_restarted) | ||||
self._kernel_manager = kernel_manager | ||||
if kernel_manager is None: | ||||
return | ||||
kernel_manager.kernel_restarted.connect(self._handle_kernel_restarted) | ||||
epatters
|
r2770 | |||
#--------------------------------------------------------------------------- | ||||
# 'BaseFrontendMixin' abstract interface | ||||
#--------------------------------------------------------------------------- | ||||
epatters
|
r2913 | |||
def _handle_kernel_died(self, since_last_heartbeat): | ||||
""" This is called when the ``kernel_died`` signal is emitted. | ||||
This method is called when the kernel heartbeat has not been | ||||
MinRK
|
r10311 | active for a certain amount of time. | ||
This is a strictly passive notification - | ||||
the kernel is likely being restarted by its KernelManager. | ||||
epatters
|
r2913 | |||
Parameters | ||||
---------- | ||||
since_last_heartbeat : float | ||||
The time since the heartbeat was last received. | ||||
""" | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r10311 | def _handle_kernel_restarted(self): | ||
""" This is called when the ``kernel_restarted`` signal is emitted. | ||||
This method is called when the kernel has been restarted by the | ||||
autorestart mechanism. | ||||
Parameters | ||||
---------- | ||||
since_last_heartbeat : float | ||||
The time since the heartbeat was last received. | ||||
""" | ||||
MinRK
|
r7079 | def _started_kernel(self): | ||
"""Called when the KernelManager starts (or restarts) the kernel subprocess. | ||||
Channels may or may not be running at this point. | ||||
""" | ||||
epatters
|
r2770 | def _started_channels(self): | ||
Bernardo B. Marques
|
r4872 | """ Called when the KernelManager channels have started listening or | ||
epatters
|
r2770 | when the frontend is assigned an already listening KernelManager. | ||
""" | ||||
def _stopped_channels(self): | ||||
""" Called when the KernelManager channels have stopped listening or | ||||
when a listening KernelManager is removed from the frontend. | ||||
""" | ||||
#--------------------------------------------------------------------------- | ||||
epatters
|
r2824 | # 'BaseFrontendMixin' protected interface | ||
epatters
|
r2770 | #--------------------------------------------------------------------------- | ||
def _dispatch(self, msg): | ||||
Bernardo B. Marques
|
r4872 | """ Calls the frontend handler associated with the message type of the | ||
epatters
|
r2824 | given message. | ||
epatters
|
r2770 | """ | ||
Brian E. Granger
|
r4230 | msg_type = msg['header']['msg_type'] | ||
epatters
|
r2770 | handler = getattr(self, '_handle_' + msg_type, None) | ||
if handler: | ||||
handler(msg) | ||||
epatters
|
r2824 | |||
def _is_from_this_session(self, msg): | ||||
""" Returns whether a reply from the kernel originated from a request | ||||
from this frontend. | ||||
""" | ||||
MinRK
|
r10288 | session = self._kernel_client.session.session | ||
MinRK
|
r5362 | parent = msg['parent_header'] | ||
if not parent: | ||||
# if the message has no parent, assume it is meant for all frontends | ||||
return True | ||||
else: | ||||
return parent.get('session') == session | ||||