From c82de979d28b357b152e161ba221612aa3ebbb9c 2013-04-24 04:47:44 From: MinRK 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()