base_frontend_mixin.py
158 lines
| 5.9 KiB
| text/x-python
|
PythonLexer
/ jupyter_qtconsole / base_frontend_mixin.py
|
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 | ||||
#--------------------------------------------------------------------------- | ||||
|
r10302 | _kernel_client = None | ||
|
r10311 | _kernel_manager = None | ||
|
r4872 | |||
|
r10311 | @property | ||
def kernel_client(self): | ||||
"""Returns the current kernel client.""" | ||||
|
r10288 | return self._kernel_client | ||
|
r2770 | |||
|
r10311 | @kernel_client.setter | ||
def kernel_client(self, kernel_client): | ||||
|
r10288 | """Disconnect from the current kernel client (if any) and set a new | ||
kernel client. | ||||
|
r2770 | """ | ||
|
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( | ||||
|
r2913 | self._handle_kernel_died) | ||
|
r4872 | |||
|
r10288 | # Handle the case where the old kernel client is still listening. | ||
if old_client.channels_running: | ||||
|
r2770 | self._stopped_channels() | ||
|
r10288 | # Set the new kernel client. | ||
self._kernel_client = kernel_client | ||||
if kernel_client is None: | ||||
|
r2770 | return | ||
|
r10288 | # Connect the new kernel client. | ||
kernel_client.started_channels.connect(self._started_channels) | ||||
kernel_client.stopped_channels.connect(self._stopped_channels) | ||||
|
r2770 | |||
|
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) | ||||
|
r10311 | # hb_channel | ||
|
r10288 | kernel_client.hb_channel.kernel_died.connect(self._handle_kernel_died) | ||
|
r2910 | |||
|
r10288 | # Handle the case where the kernel client started channels before | ||
|
r2770 | # we connected. | ||
|
r10288 | if kernel_client.channels_running: | ||
|
r2770 | self._started_channels() | ||
|
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) | ||||
|
r2770 | |||
#--------------------------------------------------------------------------- | ||||
# 'BaseFrontendMixin' abstract interface | ||||
#--------------------------------------------------------------------------- | ||||
|
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 | ||||
|
r10311 | active for a certain amount of time. | ||
This is a strictly passive notification - | ||||
the kernel is likely being restarted by its KernelManager. | ||||
|
r2913 | |||
Parameters | ||||
---------- | ||||
since_last_heartbeat : float | ||||
The time since the heartbeat was last received. | ||||
""" | ||||
|
r4872 | |||
|
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. | ||||
""" | ||||
|
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. | ||||
""" | ||||
|
r2770 | def _started_channels(self): | ||
|
r4872 | """ Called when the KernelManager channels have started listening or | ||
|
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. | ||||
""" | ||||
#--------------------------------------------------------------------------- | ||||
|
r2824 | # 'BaseFrontendMixin' protected interface | ||
|
r2770 | #--------------------------------------------------------------------------- | ||
def _dispatch(self, msg): | ||||
|
r4872 | """ Calls the frontend handler associated with the message type of the | ||
|
r2824 | given message. | ||
|
r2770 | """ | ||
|
r4230 | msg_type = msg['header']['msg_type'] | ||
|
r2770 | handler = getattr(self, '_handle_' + msg_type, None) | ||
if handler: | ||||
handler(msg) | ||||
|
r18374 | |||
def from_here(self, msg): | ||||
"""Return whether a message is from this session""" | ||||
session_id = self._kernel_client.session.session | ||||
return msg['parent_header'].get("session", session_id) == session_id | ||||
def include_output(self, msg): | ||||
"""Return whether we should include a given output message""" | ||||
if self._hidden: | ||||
return False | ||||
from_here = self.from_here(msg) | ||||
if msg['msg_type'] == 'execute_input': | ||||
# only echo inputs not from here | ||||
return self.include_other_output and not from_here | ||||
if self.include_other_output: | ||||
|
r5362 | return True | ||
else: | ||||
|
r18374 | return from_here | ||