diff --git a/IPython/kernel/zmq/zmqshell.py b/IPython/kernel/zmq/zmqshell.py index 9d80218..9ea1de1 100644 --- a/IPython/kernel/zmq/zmqshell.py +++ b/IPython/kernel/zmq/zmqshell.py @@ -32,6 +32,7 @@ from IPython.core.error import UsageError from IPython.core.magics import MacroToEdit, CodeMagics from IPython.core.magic import magics_class, line_magic, Magics from IPython.core.payloadpage import install_payload_page +from IPython.core.usage import default_gui_banner from IPython.display import display, Javascript from IPython.kernel.inprocess.socket import SocketABC from IPython.kernel import ( @@ -422,6 +423,9 @@ class ZMQInteractiveShell(InteractiveShell): data_pub_class = Type(ZMQDataPublisher) kernel = Any() parent_header = Any() + + def _banner1_default(self): + return default_gui_banner # Override the traitlet in the parent class, because there's no point using # readline for the kernel. Can be removed when the readline code is moved diff --git a/IPython/qt/console/frontend_widget.py b/IPython/qt/console/frontend_widget.py index 651bdb4..3d7a816 100644 --- a/IPython/qt/console/frontend_widget.py +++ b/IPython/qt/console/frontend_widget.py @@ -82,6 +82,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): # The text to show when the kernel is (re)started. banner = Unicode(config=True) + kernel_banner = Unicode() # An option and corresponding signal for overriding the default kernel # interrupt behavior. @@ -639,6 +640,9 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): if clear: self._control.clear() self._append_plain_text(self.banner) + if self.kernel_banner: + self._append_plain_text(self.kernel_banner) + # update output marker for stdout/stderr, so that startup # messages appear after banner: self._append_before_prompt_pos = self._get_cursor().position() diff --git a/IPython/qt/console/ipython_widget.py b/IPython/qt/console/ipython_widget.py index d5eba3f..5913dce 100644 --- a/IPython/qt/console/ipython_widget.py +++ b/IPython/qt/console/ipython_widget.py @@ -17,6 +17,7 @@ from textwrap import dedent from IPython.external.qt import QtCore, QtGui from IPython.core.inputsplitter import IPythonInputSplitter +from IPython.core.release import version from IPython.core.inputtransformer import ipy_prompt from IPython.utils.traitlets import Bool, Unicode from .frontend_widget import FrontendWidget @@ -107,6 +108,7 @@ class IPythonWidget(FrontendWidget): _payload_source_next_input = 'set_next_input' _payload_source_page = 'page' _retrying_history_request = False + _starting = False #--------------------------------------------------------------------------- # 'object' interface @@ -253,31 +255,28 @@ class IPythonWidget(FrontendWidget): self._append_plain_text(u'\n', True) def _handle_kernel_info_reply(self, rep): - """ Handle kernel info replies. - """ + """Handle kernel info replies.""" + content = rep['content'] if not self._guiref_loaded: - if rep['content'].get('language') == 'python': + if content.get('language') == 'python': self._load_guiref_magic() self._guiref_loaded = True + + self.kernel_banner = content.get('banner', '') + if self._starting: + # finish handling started channels + self._starting = False + super(IPythonWidget, self)._started_channels() def _started_channels(self): """Reimplemented to make a history request and load %guiref.""" - super(IPythonWidget, self)._started_channels() - + self._starting = True # The reply will trigger %guiref load provided language=='python' self.kernel_client.kernel_info() self.kernel_client.shell_channel.history(hist_access_type='tail', n=1000) - def _started_kernel(self): - """Load %guiref when the kernel starts (if channels are also started). - - Principally triggered by kernel restart. - """ - if self.kernel_client.shell_channel is not None: - self._load_guiref_magic() - def _load_guiref_magic(self): """Load %guiref magic.""" self.kernel_client.shell_channel.execute('\n'.join([ @@ -568,5 +567,4 @@ class IPythonWidget(FrontendWidget): #------ Trait default initializers ----------------------------------------- def _banner_default(self): - from IPython.core.usage import default_gui_banner - return default_gui_banner + return "IPython QtConsole {version}\n".format(version=version) diff --git a/IPython/terminal/console/interactiveshell.py b/IPython/terminal/console/interactiveshell.py index 50d83d6..e91378a 100644 --- a/IPython/terminal/console/interactiveshell.py +++ b/IPython/terminal/console/interactiveshell.py @@ -22,6 +22,7 @@ except ImportError: from Queue import Empty # Py 2 from IPython.core import page +from IPython.core import release from IPython.utils.warn import warn, error from IPython.utils import io from IPython.utils.py3compat import string_types, input @@ -37,6 +38,7 @@ class ZMQTerminalInteractiveShell(TerminalInteractiveShell): _executing = False _execution_state = Unicode('') _pending_clearoutput = False + kernel_banner = Unicode('') kernel_timeout = Float(60, config=True, help="""Timeout for giving up on a kernel (in seconds). @@ -366,7 +368,7 @@ class ZMQTerminalInteractiveShell(TerminalInteractiveShell): while True: try: self.interact(display_banner=display_banner) - #self.interact_with_readline() + #self.interact_with_readline() # XXX for testing of a readline-decoupled repl loop, call # interact_with_readline above break @@ -375,6 +377,24 @@ class ZMQTerminalInteractiveShell(TerminalInteractiveShell): # handling seems rather unpredictable... self.write("\nKeyboardInterrupt in interact()\n") + def _banner1_default(self): + return "IPython Console {version}\n".format(version=release.version) + + def compute_banner(self): + super(ZMQTerminalInteractiveShell, self).compute_banner() + if self.client and not self.kernel_banner: + msg_id = self.client.kernel_info() + while True: + try: + reply = self.client.get_shell_msg(timeout=1) + except Empty: + break + else: + if reply['parent_header'].get('msg_id') == msg_id: + self.kernel_banner = reply['content'].get('banner', '') + break + self.banner += self.kernel_banner + def wait_for_kernel(self, timeout=None): """method to wait for a kernel to be ready""" tic = time.time()