##// END OF EJS Templates
First cut at allowing the kernel to be restarted from the frontend.
epatters -
Show More
@@ -430,12 +430,6 b' class ConsoleWidget(QtGui.QWidget):'
430 430 """
431 431 raise NotImplementedError
432 432
433 def _execute_interrupt(self):
434 """ Attempts to stop execution. Returns whether this method has an
435 implementation.
436 """
437 return False
438
439 433 def _prompt_started_hook(self):
440 434 """ Called immediately after a new prompt is displayed.
441 435 """
@@ -575,10 +569,7 b' class ConsoleWidget(QtGui.QWidget):'
575 569 intercepted = True
576 570
577 571 elif ctrl_down:
578 if key == QtCore.Qt.Key_C:
579 intercepted = self._executing and self._execute_interrupt()
580
581 elif key == QtCore.Qt.Key_K:
572 if key == QtCore.Qt.Key_K:
582 573 if self._in_buffer(position):
583 574 cursor.movePosition(QtGui.QTextCursor.EndOfLine,
584 575 QtGui.QTextCursor.KeepAnchor)
@@ -72,12 +72,22 b' class FrontendHighlighter(PygmentsHighlighter):'
72 72 class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
73 73 """ A Qt frontend for a generic Python kernel.
74 74 """
75
76 # An option and corresponding signal for overriding the default kernel
77 # interrupt behavior.
78 custom_interrupt = False
79 custom_interrupt_requested = QtCore.pyqtSignal()
80
81 # An option and corresponding signal for overriding the default kernel
82 # restart behavior.
83 custom_restart = False
84 custom_restart_requested = QtCore.pyqtSignal()
75 85
76 86 # Emitted when an 'execute_reply' has been received from the kernel and
77 87 # processed by the FrontendWidget.
78 88 executed = QtCore.pyqtSignal(object)
79
80 # Protected class attributes.
89
90 # Protected class variables.
81 91 _highlighter_class = FrontendHighlighter
82 92 _input_splitter_class = InputSplitter
83 93
@@ -123,13 +133,6 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
123 133 """
124 134 self.kernel_manager.xreq_channel.execute(source, hidden)
125 135 self._hidden = hidden
126
127 def _execute_interrupt(self):
128 """ Attempts to stop execution. Returns whether this method has an
129 implementation.
130 """
131 self._interrupt_kernel()
132 return True
133 136
134 137 def _prompt_started_hook(self):
135 138 """ Called immediately after a new prompt is displayed.
@@ -163,6 +166,19 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
163 166 # 'ConsoleWidget' protected interface
164 167 #---------------------------------------------------------------------------
165 168
169 def _event_filter_console_keypress(self, event):
170 """ Reimplemented to allow execution interruption.
171 """
172 key = event.key()
173 if self._executing and self._control_key_down(event.modifiers()):
174 if key == QtCore.Qt.Key_C:
175 self._kernel_interrupt()
176 return True
177 elif key == QtCore.Qt.Key_Period:
178 self._kernel_restart()
179 return True
180 return super(FrontendWidget, self)._event_filter_console_keypress(event)
181
166 182 def _show_continuation_prompt(self):
167 183 """ Reimplemented for auto-indentation.
168 184 """
@@ -324,15 +340,36 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
324 340 text = str(cursor.selection().toPlainText())
325 341 return self._completion_lexer.get_context(text)
326 342
327 def _interrupt_kernel(self):
328 """ Attempts to the interrupt the kernel.
343 def _kernel_interrupt(self):
344 """ Attempts to interrupt the running kernel.
329 345 """
330 if self.kernel_manager.has_kernel:
346 if self.custom_interrupt:
347 self.custom_interrupt_requested.emit()
348 elif self.kernel_manager.has_kernel:
331 349 self.kernel_manager.signal_kernel(signal.SIGINT)
332 350 else:
333 351 self._append_plain_text('Kernel process is either remote or '
334 352 'unspecified. Cannot interrupt.\n')
335 353
354 def _kernel_restart(self):
355 """ Attempts to restart the running kernel.
356 """
357 if self.custom_restart:
358 self.custom_restart_requested.emit()
359 elif self.kernel_manager.has_kernel:
360 try:
361 self.kernel_manager.restart_kernel()
362 except RuntimeError:
363 message = 'Kernel started externally. Cannot restart.\n'
364 self._append_plain_text(message)
365 else:
366 self._stopped_channels()
367 self._append_plain_text('Kernel restarting...\n')
368 self._show_interpreter_prompt()
369 else:
370 self._append_plain_text('Kernel process is either remote or '
371 'unspecified. Cannot restart.\n')
372
336 373 def _process_execute_abort(self, msg):
337 374 """ Process a reply for an aborted execution request.
338 375 """
@@ -1,5 +1,3 b''
1 import os
2
3 1 # System library imports
4 2 from PyQt4 import QtCore, QtGui
5 3
@@ -482,6 +482,7 b' class KernelManager(HasTraits):'
482 482 rep_channel_class = Type(RepSocketChannel)
483 483
484 484 # Protected traits.
485 _launch_args = Any
485 486 _xreq_channel = Any
486 487 _sub_channel = Any
487 488 _rep_channel = Any
@@ -523,7 +524,7 b' class KernelManager(HasTraits):'
523 524 # Kernel process management methods:
524 525 #--------------------------------------------------------------------------
525 526
526 def start_kernel(self, ipython=True, **kw):
527 def start_kernel(self, **kw):
527 528 """Starts a kernel process and configures the manager to use it.
528 529
529 530 If random ports (port=0) are being used, this method must be called
@@ -540,7 +541,8 b' class KernelManager(HasTraits):'
540 541 "Make sure that the '*_address' attributes are "
541 542 "configured properly.")
542 543
543 if ipython:
544 self._launch_args = kw.copy()
545 if kw.pop('ipython', True):
544 546 from ipkernel import launch_kernel as launch
545 547 else:
546 548 from pykernel import launch_kernel as launch
@@ -550,6 +552,19 b' class KernelManager(HasTraits):'
550 552 self.sub_address = (LOCALHOST, pub)
551 553 self.rep_address = (LOCALHOST, req)
552 554
555 def restart_kernel(self):
556 """Restarts a kernel with the same arguments that were used to launch
557 it. If the old kernel was launched with random ports, the same ports
558 will be used for the new kernel.
559 """
560 if self._launch_args is None:
561 raise RuntimeError("Cannot restart the kernel. "
562 "No previous call to 'start_kernel'.")
563 else:
564 if self.has_kernel:
565 self.kill_kernel()
566 self.start_kernel(*self._launch_args)
567
553 568 @property
554 569 def has_kernel(self):
555 570 """Returns whether a kernel process has been specified for the kernel
General Comments 0
You need to be logged in to leave comments. Login now