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_ |
|
|
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 |
|
|
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 |
|
|
328 |
""" Attempts to |
|
|
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 | """ |
@@ -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, |
|
|
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