##// END OF EJS Templates
qtconsole autorestarts
MinRK -
Show More
@@ -445,18 +445,30 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
445 self._reading = False
445 self._reading = False
446 self._readline(msg['content']['prompt'], callback=callback)
446 self._readline(msg['content']['prompt'], callback=callback)
447
447
448 def _kernel_restarted_message(self, died=True):
449 msg = "Kernel died, restarting" if died else "Kernel restarting"
450 self._append_html("<br>%s<hr><br>" % msg,
451 before_prompt=False
452 )
453
448 def _handle_kernel_died(self, since_last_heartbeat):
454 def _handle_kernel_died(self, since_last_heartbeat):
449 """ Handle the kernel's death by asking if the user wants to restart.
455 """Handle the kernel's death (if we do not own the kernel).
450 """
456 """
451 self.log.debug("kernel died: %s", since_last_heartbeat)
457 self.log.warn("kernel died: %s", since_last_heartbeat)
452 if self.custom_restart:
458 if self.custom_restart:
453 self.custom_restart_kernel_died.emit(since_last_heartbeat)
459 self.custom_restart_kernel_died.emit(since_last_heartbeat)
454 else:
460 else:
455 message = 'The kernel heartbeat has been inactive for %.2f ' \
461 self._kernel_restarted_message(died=True)
456 'seconds. Do you want to restart the kernel? You may ' \
462 self.reset()
457 'first want to check the network connection.' % \
463
458 since_last_heartbeat
464 def _handle_kernel_restarted(self, died=True):
459 self.restart_kernel(message, now=True)
465 """Notice that the autorestarter restarted the kernel.
466
467 There's nothing to do but show a message.
468 """
469 self.log.warn("kernel restarted")
470 self._kernel_restarted_message(died=died)
471 self.reset()
460
472
461 def _handle_object_info_reply(self, rep):
473 def _handle_object_info_reply(self, rep):
462 """ Handle replies for call tips.
474 """ Handle replies for call tips.
@@ -506,37 +518,28 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
506 def _handle_shutdown_reply(self, msg):
518 def _handle_shutdown_reply(self, msg):
507 """ Handle shutdown signal, only if from other console.
519 """ Handle shutdown signal, only if from other console.
508 """
520 """
509 self.log.debug("shutdown: %s", msg.get('content', ''))
521 self.log.warn("shutdown: %s", msg.get('content', ''))
522 restart = msg.get('content', {}).get('restart', False)
510 if not self._hidden and not self._is_from_this_session(msg):
523 if not self._hidden and not self._is_from_this_session(msg):
511 if self._local_kernel:
524 # got shutdown reply, request came from session other than ours
512 if not msg['content']['restart']:
525 if restart:
526 # someone restarted the kernel, handle it
527 self._handle_kernel_restarted(died=False)
528 else:
529 # kernel was shutdown permanently
530 # this triggers exit_requested if the kernel was local,
531 # and a dialog if the kernel was remote,
532 # so we don't suddenly clear the qtconsole without asking.
533 if self._local_kernel:
513 self.exit_requested.emit(self)
534 self.exit_requested.emit(self)
514 else:
535 else:
515 # we just got notified of a restart!
536 title = self.window().windowTitle()
516 time.sleep(0.25) # wait 1/4 sec to reset
517 # lest the request for a new prompt
518 # goes to the old kernel
519 self.reset()
520 else: # remote kernel, prompt on Kernel shutdown/reset
521 title = self.window().windowTitle()
522 if not msg['content']['restart']:
523 reply = QtGui.QMessageBox.question(self, title,
537 reply = QtGui.QMessageBox.question(self, title,
524 "Kernel has been shutdown permanently. "
538 "Kernel has been shutdown permanently. "
525 "Close the Console?",
539 "Close the Console?",
526 QtGui.QMessageBox.Yes,QtGui.QMessageBox.No)
540 QtGui.QMessageBox.Yes,QtGui.QMessageBox.No)
527 if reply == QtGui.QMessageBox.Yes:
541 if reply == QtGui.QMessageBox.Yes:
528 self.exit_requested.emit(self)
542 self.exit_requested.emit(self)
529 else:
530 # XXX: remove message box in favor of using the
531 # clear_on_kernel_restart setting?
532 reply = QtGui.QMessageBox.question(self, title,
533 "Kernel has been reset. Clear the Console?",
534 QtGui.QMessageBox.Yes,QtGui.QMessageBox.No)
535 if reply == QtGui.QMessageBox.Yes:
536 time.sleep(0.25) # wait 1/4 sec to reset
537 # lest the request for a new prompt
538 # goes to the old kernel
539 self.reset()
540
543
541 def _started_channels(self):
544 def _started_channels(self):
542 """ Called when the KernelManager channels have started listening or
545 """ Called when the KernelManager channels have started listening or
@@ -573,12 +576,11 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
573 self._reading = False
576 self._reading = False
574 self.kernel_manager.interrupt_kernel()
577 self.kernel_manager.interrupt_kernel()
575 else:
578 else:
576 self._append_plain_text('Kernel process is either remote or '
579 self._append_plain_text('Cannot interrupt a kernel I did not start.\n')
577 'unspecified. Cannot interrupt.\n')
578
580
579 def reset(self, clear=False):
581 def reset(self, clear=False):
580 """ Resets the widget to its initial state if ``clear`` parameter or
582 """ Resets the widget to its initial state if ``clear`` parameter
581 ``clear_on_kernel_restart`` configuration setting is True, otherwise
583 is True, otherwise
582 prints a visual indication of the fact that the kernel restarted, but
584 prints a visual indication of the fact that the kernel restarted, but
583 does not clear the traces from previous usage of the kernel before it
585 does not clear the traces from previous usage of the kernel before it
584 was restarted. With ``clear=True``, it is similar to ``%clear``, but
586 was restarted. With ``clear=True``, it is similar to ``%clear``, but
@@ -590,15 +592,9 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
590 self._reading = False
592 self._reading = False
591 self._highlighter.highlighting_on = False
593 self._highlighter.highlighting_on = False
592
594
593 if self.clear_on_kernel_restart or clear:
595 if clear:
594 self._control.clear()
596 self._control.clear()
595 self._append_plain_text(self.banner)
597 self._append_plain_text(self.banner)
596 else:
597 self._append_plain_text("# restarting kernel...")
598 self._append_html("<hr><br>")
599 # XXX: Reprinting the full banner may be too much, but once #1680 is
600 # addressed, that will mitigate it.
601 #self._append_plain_text(self.banner)
602 # update output marker for stdout/stderr, so that startup
598 # update output marker for stdout/stderr, so that startup
603 # messages appear after banner:
599 # messages appear after banner:
604 self._append_before_prompt_pos = self._get_cursor().position()
600 self._append_before_prompt_pos = self._get_cursor().position()
@@ -615,8 +611,9 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
615
611
616 if self.custom_restart:
612 if self.custom_restart:
617 self.custom_restart_requested.emit()
613 self.custom_restart_requested.emit()
614 return
618
615
619 elif self.kernel_manager:
616 if self.kernel_manager:
620 # Pause the heart beat channel to prevent further warnings.
617 # Pause the heart beat channel to prevent further warnings.
621 self.kernel_client.hb_channel.pause()
618 self.kernel_client.hb_channel.pause()
622
619
@@ -635,21 +632,23 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
635 if do_restart:
632 if do_restart:
636 try:
633 try:
637 self.kernel_manager.restart_kernel(now=now)
634 self.kernel_manager.restart_kernel(now=now)
638 except RuntimeError:
635 except RuntimeError as e:
639 self._append_plain_text('Kernel started externally. '
636 self._append_plain_text(
640 'Cannot restart.\n',
637 'Error restarting kernel: %s\n' % e,
641 before_prompt=True
638 before_prompt=True
642 )
639 )
643 else:
640 else:
644 self.reset()
641 self._append_html("<br>Restarting kernel...\n<hr><br>",
642 before_prompt=True,
643 )
645 else:
644 else:
646 self.kernel_client.hb_channel.unpause()
645 self.kernel_client.hb_channel.unpause()
647
646
648 else:
647 else:
649 self._append_plain_text('Kernel process is either remote or '
648 self._append_plain_text(
650 'unspecified. Cannot restart.\n',
649 'Cannot restart a Kernel I did not start\n',
651 before_prompt=True
650 before_prompt=True
652 )
651 )
653
652
654 #---------------------------------------------------------------------------
653 #---------------------------------------------------------------------------
655 # 'FrontendWidget' protected interface
654 # 'FrontendWidget' protected interface
@@ -62,6 +62,7 b' from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget'
62 from IPython.frontend.qt.console import styles
62 from IPython.frontend.qt.console import styles
63 from IPython.frontend.qt.console.mainwindow import MainWindow
63 from IPython.frontend.qt.console.mainwindow import MainWindow
64 from IPython.frontend.qt.client import QtKernelClient
64 from IPython.frontend.qt.client import QtKernelClient
65 from IPython.frontend.qt.manager import QtKernelManager
65 from IPython.kernel import tunnel_to_kernel, find_connection_file
66 from IPython.kernel import tunnel_to_kernel, find_connection_file
66 from IPython.utils.traitlets import (
67 from IPython.utils.traitlets import (
67 Dict, List, Unicode, CBool, Any
68 Dict, List, Unicode, CBool, Any
@@ -160,6 +161,7 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):'
160 frontend_flags = Any(qt_flags)
161 frontend_flags = Any(qt_flags)
161 frontend_aliases = Any(qt_aliases)
162 frontend_aliases = Any(qt_aliases)
162 kernel_client_class = QtKernelClient
163 kernel_client_class = QtKernelClient
164 kernel_manager_class = QtKernelManager
163
165
164 stylesheet = Unicode('', config=True,
166 stylesheet = Unicode('', config=True,
165 help="path to a custom CSS stylesheet")
167 help="path to a custom CSS stylesheet")
@@ -189,19 +191,15 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):'
189 kernel_manager = self.kernel_manager_class(
191 kernel_manager = self.kernel_manager_class(
190 connection_file=self._new_connection_file(),
192 connection_file=self._new_connection_file(),
191 config=self.config,
193 config=self.config,
194 autorestart=True,
192 )
195 )
193 # start the kernel
196 # start the kernel
194 kwargs = dict()
197 kwargs = dict()
195 kwargs['extra_arguments'] = self.kernel_argv
198 kwargs['extra_arguments'] = self.kernel_argv
196 kernel_manager.start_kernel(**kwargs)
199 kernel_manager.start_kernel(**kwargs)
197
200 kernel_manager.client_factory = self.kernel_client_class
198 # connect to the kernel
201 kernel_client = kernel_manager.client()
199 kernel_client = self.kernel_client_class(
202 kernel_client.start_channels(shell=True, iopub=True)
200 connection_file=kernel_manager.connection_file,
201 config=self.config,
202 )
203 kernel_client.load_connection_file()
204 kernel_client.start_channels()
205 widget = self.widget_factory(config=self.config,
203 widget = self.widget_factory(config=self.config,
206 local_kernel=True)
204 local_kernel=True)
207 self.init_colors(widget)
205 self.init_colors(widget)
@@ -220,7 +218,6 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):'
220 current_widget : IPythonWidget
218 current_widget : IPythonWidget
221 The IPythonWidget whose kernel this frontend is to share
219 The IPythonWidget whose kernel this frontend is to share
222 """
220 """
223
224 kernel_client = self.kernel_client_class(
221 kernel_client = self.kernel_client_class(
225 connection_file=current_widget.kernel_client.connection_file,
222 connection_file=current_widget.kernel_client.connection_file,
226 config = self.config,
223 config = self.config,
@@ -234,11 +231,15 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):'
234 widget._may_close = False
231 widget._may_close = False
235 widget._confirm_exit = False
232 widget._confirm_exit = False
236 widget.kernel_client = kernel_client
233 widget.kernel_client = kernel_client
234 widget.kernel_manager = current_widget.kernel_manager
237 return widget
235 return widget
238
236
237 def init_qt_app(self):
238 # separate from qt_elements, because it must run first
239 self.app = QtGui.QApplication([])
240
239 def init_qt_elements(self):
241 def init_qt_elements(self):
240 # Create the widget.
242 # Create the widget.
241 self.app = QtGui.QApplication([])
242
243
243 base_path = os.path.abspath(os.path.dirname(__file__))
244 base_path = os.path.abspath(os.path.dirname(__file__))
244 icon_path = os.path.join(base_path, 'resources', 'icon', 'IPythonConsole.svg')
245 icon_path = os.path.join(base_path, 'resources', 'icon', 'IPythonConsole.svg')
@@ -345,6 +346,7 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):'
345
346
346 @catch_config_error
347 @catch_config_error
347 def initialize(self, argv=None):
348 def initialize(self, argv=None):
349 self.init_qt_app()
348 super(IPythonQtConsoleApp, self).initialize(argv)
350 super(IPythonQtConsoleApp, self).initialize(argv)
349 IPythonConsoleApp.initialize(self,argv)
351 IPythonConsoleApp.initialize(self,argv)
350 self.init_qt_elements()
352 self.init_qt_elements()
General Comments 0
You need to be logged in to leave comments. Login now