##// END OF EJS Templates
Fix race condition in javascript kernel message processing...
Fix race condition in javascript kernel message processing Because the binary messages are now deserialized using the asynchronous FileReader API, we need to have some way to force the messages to still be processed in the order they are received. This patch implements a simple processing queue using promises.

File last commit:

r18374:3b0d8c07
r20441:834cd9c4
Show More
base_frontend_mixin.py
158 lines | 5.9 KiB | text/x-python | PythonLexer
/ IPython / qt / base_frontend_mixin.py
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
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
make sure _kernel_client is defined
r10302 _kernel_client = None
MinRK
front ends can have both Manager and Client
r10311 _kernel_manager = None
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
front ends can have both Manager and Client
r10311 @property
def kernel_client(self):
"""Returns the current kernel client."""
MinRK
update Qt to use KernelClient
r10288 return self._kernel_client
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770
MinRK
front ends can have both Manager and Client
r10311 @kernel_client.setter
def kernel_client(self, kernel_client):
MinRK
update Qt to use KernelClient
r10288 """Disconnect from the current kernel client (if any) and set a new
kernel client.
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 """
MinRK
update Qt to use KernelClient
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
* Improved frontend-side kernel restart support....
r2913 self._handle_kernel_died)
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
update Qt to use KernelClient
r10288 # Handle the case where the old kernel client is still listening.
if old_client.channels_running:
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 self._stopped_channels()
MinRK
update Qt to use KernelClient
r10288 # Set the new kernel client.
self._kernel_client = kernel_client
if kernel_client is None:
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 return
MinRK
update Qt to use KernelClient
r10288 # Connect the new kernel client.
kernel_client.started_channels.connect(self._started_channels)
kernel_client.stopped_channels.connect(self._stopped_channels)
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770
MinRK
update Qt to use KernelClient
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
front ends can have both Manager and Client
r10311 # hb_channel
MinRK
update Qt to use KernelClient
r10288 kernel_client.hb_channel.kernel_died.connect(self._handle_kernel_died)
Brian Granger
Added heartbeat support.
r2910
MinRK
update Qt to use KernelClient
r10288 # Handle the case where the kernel client started channels before
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 # we connected.
MinRK
update Qt to use KernelClient
r10288 if kernel_client.channels_running:
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 self._started_channels()
MinRK
front ends can have both Manager and Client
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
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770
#---------------------------------------------------------------------------
# 'BaseFrontendMixin' abstract interface
#---------------------------------------------------------------------------
epatters
* Improved frontend-side kernel restart support....
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
front ends can have both Manager and Client
r10311 active for a certain amount of time.
This is a strictly passive notification -
the kernel is likely being restarted by its KernelManager.
epatters
* Improved frontend-side kernel restart support....
r2913
Parameters
----------
since_last_heartbeat : float
The time since the heartbeat was last received.
"""
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
front ends can have both Manager and Client
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
add kernel_started signal to QtKernelManager...
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
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 def _started_channels(self):
Bernardo B. Marques
remove all trailling spaces
r4872 """ Called when the KernelManager channels have started listening or
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
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
* The Qt console frontend now ignores cross chatter from other frontends....
r2824 # 'BaseFrontendMixin' protected interface
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 #---------------------------------------------------------------------------
def _dispatch(self, msg):
Bernardo B. Marques
remove all trailling spaces
r4872 """ Calls the frontend handler associated with the message type of the
epatters
* The Qt console frontend now ignores cross chatter from other frontends....
r2824 given message.
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 """
Brian E. Granger
Fixing code to assume msg_type and msg_id are top-level....
r4230 msg_type = msg['header']['msg_type']
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 handler = getattr(self, '_handle_' + msg_type, None)
if handler:
handler(msg)
MinRK
add ConsoleWidget.include_other_output...
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:
MinRK
associate messages with no parent to all qt frontends...
r5362 return True
else:
MinRK
add ConsoleWidget.include_other_output...
r18374 return from_here