From c82de979d28b357b152e161ba221612aa3ebbb9c 2013-04-24 04:47:44
From: MinRK <benjaminrk@gmail.com>
Date: 2013-04-24 04:47:44
Subject: [PATCH] update Qt to use KernelClient

---

diff --git a/IPython/frontend/qt/base_frontend_mixin.py b/IPython/frontend/qt/base_frontend_mixin.py
index 7897723..2a848cf 100644
--- a/IPython/frontend/qt/base_frontend_mixin.py
+++ b/IPython/frontend/qt/base_frontend_mixin.py
@@ -13,55 +13,53 @@ class BaseFrontendMixin(object):
     # 'BaseFrontendMixin' concrete interface
     #---------------------------------------------------------------------------
 
-    def _get_kernel_manager(self):
-        """ Returns the current kernel manager.
+    def _get_kernel_client(self):
+        """Returns the current kernel client.
         """
-        return self._kernel_manager
+        return self._kernel_client
 
-    def _set_kernel_manager(self, kernel_manager):
-        """ Disconnect from the current kernel manager (if any) and set a new
-            kernel manager.
+    def _set_kernel_client(self, kernel_client):
+        """Disconnect from the current kernel client (if any) and set a new
+            kernel client.
         """
-        # Disconnect the old kernel manager, if necessary.
-        old_manager = self._kernel_manager
-        if old_manager is not None:
-            old_manager.started_kernel.disconnect(self._started_kernel)
-            old_manager.started_channels.disconnect(self._started_channels)
-            old_manager.stopped_channels.disconnect(self._stopped_channels)
-
-            # Disconnect the old kernel manager's channels.
-            old_manager.iopub_channel.message_received.disconnect(self._dispatch)
-            old_manager.shell_channel.message_received.disconnect(self._dispatch)
-            old_manager.stdin_channel.message_received.disconnect(self._dispatch)
-            old_manager.hb_channel.kernel_died.disconnect(
+        # 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(
                 self._handle_kernel_died)
 
-            # Handle the case where the old kernel manager is still listening.
-            if old_manager.channels_running:
+            # Handle the case where the old kernel client is still listening.
+            if old_client.channels_running:
                 self._stopped_channels()
 
-        # Set the new kernel manager.
-        self._kernel_manager = kernel_manager
-        if kernel_manager is None:
+        # Set the new kernel client.
+        self._kernel_client = kernel_client
+        if kernel_client is None:
             return
 
-        # Connect the new kernel manager.
-        kernel_manager.started_kernel.connect(self._started_kernel)
-        kernel_manager.started_channels.connect(self._started_channels)
-        kernel_manager.stopped_channels.connect(self._stopped_channels)
+        # Connect the new kernel client.
+        kernel_client.started_channels.connect(self._started_channels)
+        kernel_client.stopped_channels.connect(self._stopped_channels)
 
-        # Connect the new kernel manager's channels.
-        kernel_manager.iopub_channel.message_received.connect(self._dispatch)
-        kernel_manager.shell_channel.message_received.connect(self._dispatch)
-        kernel_manager.stdin_channel.message_received.connect(self._dispatch)
-        kernel_manager.hb_channel.kernel_died.connect(self._handle_kernel_died)
+        # 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)
+        kernel_client.hb_channel.kernel_died.connect(self._handle_kernel_died)
 
-        # Handle the case where the kernel manager started channels before
+        # Handle the case where the kernel client started channels before
         # we connected.
-        if kernel_manager.channels_running:
+        if kernel_client.channels_running:
             self._started_channels()
 
-    kernel_manager = property(_get_kernel_manager, _set_kernel_manager)
+    kernel_client = property(_get_kernel_client, _set_kernel_client)
 
     #---------------------------------------------------------------------------
     # 'BaseFrontendMixin' abstract interface
@@ -112,7 +110,7 @@ class BaseFrontendMixin(object):
         """ Returns whether a reply from the kernel originated from a request
             from this frontend.
         """
-        session = self._kernel_manager.session.session
+        session = self._kernel_client.session.session
         parent = msg['parent_header']
         if not parent:
             # if the message has no parent, assume it is meant for all frontends
diff --git a/IPython/frontend/qt/kernelmanager.py b/IPython/frontend/qt/client.py
similarity index 58%
rename from IPython/frontend/qt/kernelmanager.py
rename to IPython/frontend/qt/client.py
index bded7fc..0aa927a 100644
--- a/IPython/frontend/qt/kernelmanager.py
+++ b/IPython/frontend/qt/client.py
@@ -1,13 +1,18 @@
-""" Defines a KernelManager that provides signals and slots.
+""" Defines a KernelClient that provides signals and slots.
 """
 
-# Local imports.
+# Local imports
 from IPython.utils.traitlets import Type
-from IPython.kernel.kernelmanager import ShellChannel, IOPubChannel, \
-    StdInChannel, HBChannel, KernelManager
-from base_kernelmanager import QtShellChannelMixin, QtIOPubChannelMixin, \
-    QtStdInChannelMixin, QtHBChannelMixin, QtKernelManagerMixin
+from IPython.kernel.channels import (
+    ShellChannel, IOPubChannel, StdInChannel, HBChannel
+)
+from IPython.kernel import KernelClient
 
+from .kernel_mixins import (
+    QtShellChannelMixin, QtIOPubChannelMixin,
+    QtStdInChannelMixin, QtHBChannelMixin,
+    QtKernelClientMixin
+)
 
 class QtShellChannel(QtShellChannelMixin, ShellChannel):
     pass
@@ -22,8 +27,8 @@ class QtHBChannel(QtHBChannelMixin, HBChannel):
     pass
 
 
-class QtKernelManager(QtKernelManagerMixin, KernelManager):
-    """ A KernelManager that provides signals and slots.
+class QtKernelClient(QtKernelClientMixin, KernelClient):
+    """ A KernelClient that provides signals and slots.
     """
 
     iopub_channel_class = Type(QtIOPubChannel)
diff --git a/IPython/frontend/qt/console/frontend_widget.py b/IPython/frontend/qt/console/frontend_widget.py
index 2fe1cfa..a3e4c21 100644
--- a/IPython/frontend/qt/console/frontend_widget.py
+++ b/IPython/frontend/qt/console/frontend_widget.py
@@ -148,6 +148,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
         self._highlighter = FrontendHighlighter(self)
         self._input_splitter = self._input_splitter_class()
         self._kernel_manager = None
+        self._kernel_client = None
         self._request_info = {}
         self._request_info['execute'] = {};
         self._callback_dict = {}
@@ -215,7 +216,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
 
         See parent class :meth:`execute` docstring for full details.
         """
-        msg_id = self.kernel_manager.shell_channel.execute(source, hidden)
+        msg_id = self.kernel_client.shell_channel.execute(source, hidden)
         self._request_info['execute'][msg_id] = self._ExecutionRequest(msg_id, 'user')
         self._hidden = hidden
         if not hidden:
@@ -357,7 +358,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
         # generate uuid, which would be used as an indication of whether or
         # not the unique request originated from here (can use msg id ?)
         local_uuid = str(uuid.uuid1())
-        msg_id = self.kernel_manager.shell_channel.execute('',
+        msg_id = self.kernel_client.shell_channel.execute('',
             silent=True, user_expressions={ local_uuid:expr })
         self._callback_dict[local_uuid] = callback
         self._request_info['execute'][msg_id] = self._ExecutionRequest(msg_id, 'silent_exec_callback')
@@ -400,7 +401,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
         if info and info.kind == 'user' and not self._hidden:
             # Make sure that all output from the SUB channel has been processed
             # before writing a new prompt.
-            self.kernel_manager.iopub_channel.flush()
+            self.kernel_client.iopub_channel.flush()
 
             # Reset the ANSI style information to prevent bad text in stdout
             # from messing up our colors. We're not a true terminal so we're
@@ -435,10 +436,10 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
 
         # Make sure that all output from the SUB channel has been processed
         # before entering readline mode.
-        self.kernel_manager.iopub_channel.flush()
+        self.kernel_client.iopub_channel.flush()
 
         def callback(line):
-            self.kernel_manager.stdin_channel.input(line)
+            self.kernel_client.stdin_channel.input(line)
         if self._reading:
             self.log.debug("Got second input request, assuming first was interrupted.")
             self._reading = False
@@ -568,7 +569,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
         if self.custom_interrupt:
             self._reading = False
             self.custom_interrupt_requested.emit()
-        elif self.kernel_manager.has_kernel:
+        elif self.kernel_manager:
             self._reading = False
             self.kernel_manager.interrupt_kernel()
         else:
@@ -615,9 +616,9 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
         if self.custom_restart:
             self.custom_restart_requested.emit()
 
-        elif self.kernel_manager.has_kernel:
+        elif self.kernel_manager:
             # Pause the heart beat channel to prevent further warnings.
-            self.kernel_manager.hb_channel.pause()
+            self.kernel_client.hb_channel.pause()
 
             # Prompt the user to restart the kernel. Un-pause the heartbeat if
             # they decline. (If they accept, the heartbeat will be un-paused
@@ -642,7 +643,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
                 else:
                     self.reset()
             else:
-                self.kernel_manager.hb_channel.unpause()
+                self.kernel_client.hb_channel.unpause()
 
         else:
             self._append_plain_text('Kernel process is either remote or '
@@ -670,7 +671,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
 
         # Send the metadata request to the kernel
         name = '.'.join(context)
-        msg_id = self.kernel_manager.shell_channel.object_info(name)
+        msg_id = self.kernel_client.shell_channel.object_info(name)
         pos = self._get_cursor().position()
         self._request_info['call_tip'] = self._CallTipRequest(msg_id, pos)
         return True
@@ -681,7 +682,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
         context = self._get_context()
         if context:
             # Send the completion request to the kernel
-            msg_id = self.kernel_manager.shell_channel.complete(
+            msg_id = self.kernel_client.shell_channel.complete(
                 '.'.join(context),                       # text
                 self._get_input_buffer_cursor_line(),    # line
                 self._get_input_buffer_cursor_column(),  # cursor_pos
diff --git a/IPython/frontend/qt/console/history_console_widget.py b/IPython/frontend/qt/console/history_console_widget.py
index 9201c7a..672df05 100644
--- a/IPython/frontend/qt/console/history_console_widget.py
+++ b/IPython/frontend/qt/console/history_console_widget.py
@@ -224,7 +224,7 @@ class HistoryConsoleWidget(ConsoleWidget):
         return self._history[-n:]
 
     def _request_update_session_history_length(self):
-        msg_id = self.kernel_manager.shell_channel.execute('',
+        msg_id = self.kernel_client.shell_channel.execute('',
             silent=True,
             user_expressions={
                 'hlen':'len(get_ipython().history_manager.input_hist_raw)',
diff --git a/IPython/frontend/qt/console/ipython_widget.py b/IPython/frontend/qt/console/ipython_widget.py
index dfacd93..a68ec0f 100644
--- a/IPython/frontend/qt/console/ipython_widget.py
+++ b/IPython/frontend/qt/console/ipython_widget.py
@@ -194,7 +194,7 @@ class IPythonWidget(FrontendWidget):
                 self._retrying_history_request = True
                 # wait out the kernel's queue flush, which is currently timed at 0.1s
                 time.sleep(0.25)
-                self.kernel_manager.shell_channel.history(hist_access_type='tail',n=1000)
+                self.kernel_client.shell_channel.history(hist_access_type='tail',n=1000)
             else:
                 self._retrying_history_request = False
             return
@@ -261,7 +261,7 @@ class IPythonWidget(FrontendWidget):
         """Reimplemented to make a history request and load %guiref."""
         super(IPythonWidget, self)._started_channels()
         self._load_guiref_magic()
-        self.kernel_manager.shell_channel.history(hist_access_type='tail',
+        self.kernel_client.shell_channel.history(hist_access_type='tail',
                                                   n=1000)
     
     def _started_kernel(self):
@@ -269,12 +269,12 @@ class IPythonWidget(FrontendWidget):
         
         Principally triggered by kernel restart.
         """
-        if self.kernel_manager.shell_channel is not None:
+        if self.kernel_client.shell_channel is not None:
             self._load_guiref_magic()
     
     def _load_guiref_magic(self):
         """Load %guiref magic."""
-        self.kernel_manager.shell_channel.execute('\n'.join([
+        self.kernel_client.shell_channel.execute('\n'.join([
             "try:",
             "    _usage",
             "except:",
@@ -330,7 +330,7 @@ class IPythonWidget(FrontendWidget):
         text = ''
 
         # Send the completion request to the kernel
-        msg_id = self.kernel_manager.shell_channel.complete(
+        msg_id = self.kernel_client.shell_channel.complete(
             text,                                    # text
             self._get_input_buffer_cursor_line(),    # line
             self._get_input_buffer_cursor_column(),  # cursor_pos
@@ -376,7 +376,7 @@ class IPythonWidget(FrontendWidget):
         """
         # If a number was not specified, make a prompt number request.
         if number is None:
-            msg_id = self.kernel_manager.shell_channel.execute('', silent=True)
+            msg_id = self.kernel_client.shell_channel.execute('', silent=True)
             info = self._ExecutionRequest(msg_id, 'prompt')
             self._request_info['execute'][msg_id] = info
             return
diff --git a/IPython/frontend/qt/console/mainwindow.py b/IPython/frontend/qt/console/mainwindow.py
index 4778b1b..bf3b6c6 100644
--- a/IPython/frontend/qt/console/mainwindow.py
+++ b/IPython/frontend/qt/console/mainwindow.py
@@ -176,14 +176,14 @@ class MainWindow(QtGui.QMainWindow):
                     self.update_tab_bar_visibility()
                     return
 
-        kernel_manager = closing_widget.kernel_manager
+        kernel_client = closing_widget.kernel_client
 
         if keepkernel is None and not closing_widget._confirm_exit:
             # don't prompt, just terminate the kernel if we own it
             # or leave it alone if we don't
             keepkernel = closing_widget._existing
         if keepkernel is None: #show prompt
-            if kernel_manager and kernel_manager.channels_running:
+            if kernel_client and kernel_client.channels_running:
                 title = self.window().windowTitle()
                 cancel = QtGui.QMessageBox.Cancel
                 okay = QtGui.QMessageBox.Ok
@@ -209,17 +209,17 @@ class MainWindow(QtGui.QMainWindow):
                     reply = box.exec_()
                     if reply == 1: # close All
                         for slave in slave_tabs:
-                            background(slave.kernel_manager.stop_channels)
+                            background(slave.kernel_client.stop_channels)
                             self.tab_widget.removeTab(self.tab_widget.indexOf(slave))
                         closing_widget.execute("exit")
                         self.tab_widget.removeTab(current_tab)
-                        background(kernel_manager.stop_channels)
+                        background(kernel_client.stop_channels)
                     elif reply == 0: # close Console
                         if not closing_widget._existing:
                             # Have kernel: don't quit, just close the tab
                             closing_widget.execute("exit True")
                         self.tab_widget.removeTab(current_tab)
-                        background(kernel_manager.stop_channels)
+                        background(kernel_client.stop_channels)
                 else:
                     reply = QtGui.QMessageBox.question(self, title,
                         "Are you sure you want to close this Console?"+
@@ -231,15 +231,15 @@ class MainWindow(QtGui.QMainWindow):
                         self.tab_widget.removeTab(current_tab)
         elif keepkernel: #close console but leave kernel running (no prompt)
             self.tab_widget.removeTab(current_tab)
-            background(kernel_manager.stop_channels)
+            background(kernel_client.stop_channels)
         else: #close console and kernel (no prompt)
             self.tab_widget.removeTab(current_tab)
-            if kernel_manager and kernel_manager.channels_running:
+            if kernel_client and kernel_client.channels_running:
                 for slave in slave_tabs:
-                    background(slave.kernel_manager.stop_channels)
+                    background(slave.kernel_client.stop_channels)
                     self.tab_widget.removeTab(self.tab_widget.indexOf(slave))
                 kernel_manager.shutdown_kernel()
-                background(kernel_manager.stop_channels)
+                background(kernel_client.stop_channels)
         
         self.update_tab_bar_visibility()
 
@@ -284,7 +284,7 @@ class MainWindow(QtGui.QMainWindow):
         #convert from/to int/richIpythonWidget if needed
         if isinstance(tab, int):
             tab = self.tab_widget.widget(tab)
-        km=tab.kernel_manager
+        km=tab.kernel_client
 
         #build list of all widgets
         widget_list = [self.tab_widget.widget(i) for i in range(self.tab_widget.count())]
@@ -292,7 +292,7 @@ class MainWindow(QtGui.QMainWindow):
         # widget that are candidate to be the owner of the kernel does have all the same port of the curent widget
         # And should have a _may_close attribute
         filtered_widget_list = [ widget for widget in widget_list if
-                                widget.kernel_manager.connection_file == km.connection_file and
+                                widget.kernel_client.connection_file == km.connection_file and
                                 hasattr(widget,'_may_close') ]
         # the master widget is the one that may close the kernel
         master_widget= [ widget for widget in filtered_widget_list if widget._may_close]
@@ -315,14 +315,14 @@ class MainWindow(QtGui.QMainWindow):
         #convert from/to int/richIpythonWidget if needed
         if isinstance(tab, int):
             tab = self.tab_widget.widget(tab)
-        km=tab.kernel_manager
+        km=tab.kernel_client
 
         #build list of all widgets
         widget_list = [self.tab_widget.widget(i) for i in range(self.tab_widget.count())]
 
         # widget that are candidate not to be the owner of the kernel does have all the same port of the curent widget
         filtered_widget_list = ( widget for widget in widget_list if
-                                widget.kernel_manager.connection_file == km.connection_file)
+                                widget.kernel_client.connection_file == km.connection_file)
         # Get a list of all widget owning the same kernel and removed it from
         # the previous cadidate. (better using sets ?)
         master_widget_list = self.find_master_tab(tab, as_list=True)
diff --git a/IPython/frontend/qt/console/qtconsoleapp.py b/IPython/frontend/qt/console/qtconsoleapp.py
index a7b219b..f945039 100644
--- a/IPython/frontend/qt/console/qtconsoleapp.py
+++ b/IPython/frontend/qt/console/qtconsoleapp.py
@@ -64,7 +64,7 @@ from IPython.frontend.qt.console.ipython_widget import IPythonWidget
 from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
 from IPython.frontend.qt.console import styles
 from IPython.frontend.qt.console.mainwindow import MainWindow
-from IPython.frontend.qt.kernelmanager import QtKernelManager
+from IPython.frontend.qt.client import QtKernelClient
 from IPython.kernel import tunnel_to_kernel, find_connection_file
 from IPython.utils.path import filefind
 from IPython.utils.py3compat import str_to_bytes
@@ -166,7 +166,7 @@ class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):
     aliases = Dict(aliases)
     frontend_flags = Any(qt_flags)
     frontend_aliases = Any(qt_aliases)
-    kernel_manager_class = QtKernelManager
+    kernel_client_class = QtKernelClient
 
     stylesheet = Unicode('', config=True,
         help="path to a custom CSS stylesheet")
@@ -201,7 +201,7 @@ class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):
         kwargs = dict()
         kwargs['extra_arguments'] = self.kernel_argv
         kernel_manager.start_kernel(**kwargs)
-        kernel_manager.start_channels()
+        kernel_client.start_channels()
         widget = self.widget_factory(config=self.config,
                                    local_kernel=True)
         self.init_colors(widget)
@@ -219,19 +219,19 @@ class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):
         current_widget : IPythonWidget
             The IPythonWidget whose kernel this frontend is to share
         """
-        kernel_manager = self.kernel_manager_class(
-                                connection_file=current_widget.kernel_manager.connection_file,
+        kernel_client = self.kernel_client_class(
+                                connection_file=current_widget.kernel_client.connection_file,
                                 config = self.config,
         )
-        kernel_manager.load_connection_file()
-        kernel_manager.start_channels()
+        kernel_client.load_connection_file()
+        kernel_client.start_channels()
         widget = self.widget_factory(config=self.config,
                                 local_kernel=False)
         self.init_colors(widget)
         widget._existing = True
         widget._may_close = False
         widget._confirm_exit = False
-        widget.kernel_manager = kernel_manager
+        widget.kernel_client = kernel_client
         return widget
 
     def init_qt_elements(self):
@@ -256,6 +256,7 @@ class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):
         self.widget._confirm_exit = self.confirm_exit
 
         self.widget.kernel_manager = self.kernel_manager
+        self.widget.kernel_client = self.kernel_client
         self.window = MainWindow(self.app,
                                 confirm_exit=self.confirm_exit,
                                 new_frontend_factory=self.new_frontend_master,
diff --git a/IPython/frontend/qt/base_kernelmanager.py b/IPython/frontend/qt/kernel_mixins.py
similarity index 78%
rename from IPython/frontend/qt/base_kernelmanager.py
rename to IPython/frontend/qt/kernel_mixins.py
index 0ca589f..a65fc35 100644
--- a/IPython/frontend/qt/base_kernelmanager.py
+++ b/IPython/frontend/qt/kernel_mixins.py
@@ -54,20 +54,12 @@ class QtShellChannelMixin(ChannelQObject):
     # Emitted when any message is received.
     message_received = QtCore.Signal(object)
 
-    # Emitted when a reply has been received for the corresponding request
-    # type.
+    # Emitted when a reply has been received for the corresponding request type.
     execute_reply = QtCore.Signal(object)
     complete_reply = QtCore.Signal(object)
     object_info_reply = QtCore.Signal(object)
     history_reply = QtCore.Signal(object)
 
-    # Emitted when the first reply comes back.
-    first_reply = QtCore.Signal()
-
-    # Used by the first_reply signal logic to determine if a reply is the
-    # first.
-    _handlers_called = False
-
     #---------------------------------------------------------------------------
     # 'ShellChannel' interface
     #---------------------------------------------------------------------------
@@ -84,19 +76,6 @@ class QtShellChannelMixin(ChannelQObject):
         if signal:
             signal.emit(msg)
 
-        if not self._handlers_called:
-            self.first_reply.emit()
-            self._handlers_called = True
-
-    #---------------------------------------------------------------------------
-    # 'QtShellChannelMixin' interface
-    #---------------------------------------------------------------------------
-
-    def reset_first_reply(self):
-        """ Reset the first_reply signal to fire again on the next reply.
-        """
-        self._handlers_called = False
-
 
 class QtIOPubChannelMixin(ChannelQObject):
 
@@ -189,19 +168,16 @@ class QtHBChannelMixin(ChannelQObject):
         self.kernel_died.emit(since_last_heartbeat)
 
 
-class QtKernelManagerMixin(HasTraits, SuperQObject):
-    """ A KernelManager that provides signals and slots.
+class QtKernelClientMixin(HasTraits, SuperQObject):
+    """ A KernelClient that provides signals and slots.
     """
 
     __metaclass__ = MetaQObjectHasTraits
 
-    # Emitted when the kernel manager has started listening.
-    started_kernel = QtCore.Signal()
-
-    # Emitted when the kernel manager has started listening.
+    # Emitted when the kernel client has started listening.
     started_channels = QtCore.Signal()
 
-    # Emitted when the kernel manager has stopped listening.
+    # Emitted when the kernel client has stopped listening.
     stopped_channels = QtCore.Signal()
 
     # Use Qt-specific channel classes that emit signals.
@@ -211,50 +187,19 @@ class QtKernelManagerMixin(HasTraits, SuperQObject):
     hb_channel_class = Type(QtHBChannelMixin)
 
     #---------------------------------------------------------------------------
-    # 'KernelManager' interface
+    # 'KernelClient' interface
     #---------------------------------------------------------------------------
 
-    #------ Kernel process management ------------------------------------------
-
-    def start_kernel(self, *args, **kw):
-        """ Reimplemented for proper heartbeat management.
-        """
-        if self._shell_channel is not None:
-            self._shell_channel.reset_first_reply()
-        super(QtKernelManagerMixin, self).start_kernel(*args, **kw)
-        self.started_kernel.emit()
-
     #------ Channel management -------------------------------------------------
 
     def start_channels(self, *args, **kw):
         """ Reimplemented to emit signal.
         """
-        super(QtKernelManagerMixin, self).start_channels(*args, **kw)
+        super(QtKernelClientMixin, self).start_channels(*args, **kw)
         self.started_channels.emit()
 
     def stop_channels(self):
         """ Reimplemented to emit signal.
         """
-        super(QtKernelManagerMixin, self).stop_channels()
+        super(QtKernelClientMixin, self).stop_channels()
         self.stopped_channels.emit()
-
-    @property
-    def shell_channel(self):
-        """ Reimplemented for proper heartbeat management.
-        """
-        if self._shell_channel is None:
-            self._shell_channel = super(QtKernelManagerMixin,self).shell_channel
-            self._shell_channel.first_reply.connect(self._first_reply)
-        return self._shell_channel
-
-    #---------------------------------------------------------------------------
-    # Protected interface
-    #---------------------------------------------------------------------------
-
-    def _first_reply(self):
-        """ Unpauses the heartbeat channel when the first reply is received on
-            the execute channel. Note that this will *not* start the heartbeat
-            channel if it is not already running!
-        """
-        if self._hb_channel is not None:
-            self._hb_channel.unpause()