##// END OF EJS Templates
Merge branch 'keepkernel' of https://github.com/minrk/ipython into minrk-keepkernel...
Fernando Perez -
r3106:f16f5ccc merge
parent child Browse files
Show More
@@ -3,6 +3,7 b' from __future__ import print_function'
3 3 # Standard library imports
4 4 from collections import namedtuple
5 5 import sys
6 import time
6 7
7 8 # System library imports
8 9 from pygments.lexers import PythonLexer
@@ -361,6 +362,19 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
361 362 self._append_plain_text(text)
362 363 self._control.moveCursor(QtGui.QTextCursor.End)
363 364
365 def _handle_shutdown_reply(self, msg):
366 """ Handle shutdown signal, only if from other console.
367 """
368 if not self._hidden and not self._is_from_this_session(msg):
369 if not msg['content']['restart']:
370 sys.exit(0)
371 else:
372 # we just got notified of a restart!
373 time.sleep(0.25) # wait 1/4 sec to reset
374 # lest the request for a new prompt
375 # goes to the old kernel
376 self.reset()
377
364 378 def _started_channels(self):
365 379 """ Called when the KernelManager channels have started listening or
366 380 when the frontend is assigned an already listening KernelManager.
@@ -31,11 +31,18 b' class MainWindow(QtGui.QMainWindow):'
31 31 # 'object' interface
32 32 #---------------------------------------------------------------------------
33 33
34 def __init__(self, frontend):
34 def __init__(self, app, frontend, existing=False):
35 35 """ Create a MainWindow for the specified FrontendWidget.
36
37 The app is passed as an argument to allow for different
38 closing behavior depending on whether we are the Kernel's parent.
39
40 If existing is True, then this Window does not own the Kernel.
36 41 """
37 42 super(MainWindow, self).__init__()
43 self._app = app
38 44 self._frontend = frontend
45 self._existing = existing
39 46 self._frontend.exit_requested.connect(self.close)
40 47 self.setCentralWidget(frontend)
41 48
@@ -50,11 +57,18 b' class MainWindow(QtGui.QMainWindow):'
50 57 if kernel_manager and kernel_manager.channels_running:
51 58 title = self.window().windowTitle()
52 59 reply = QtGui.QMessageBox.question(self, title,
53 'Close console?', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
54 if reply == QtGui.QMessageBox.Yes:
60 "Close just this console, or shutdown the kernel and close "+
61 "all windows attached to it?",
62 'Cancel', 'Close Console', 'Close All')
63 if reply == 2: # close All
55 64 kernel_manager.shutdown_kernel()
56 65 #kernel_manager.stop_channels()
57 66 event.accept()
67 elif reply == 1: # close Console
68 if not self._existing:
69 # I have the kernel: don't quit, just close the window
70 self._app.setQuitOnLastWindowClosed(False)
71 event.accept()
58 72 else:
59 73 event.ignore()
60 74
@@ -132,7 +146,7 b' def main():'
132 146 widget.kernel_manager = kernel_manager
133 147
134 148 # Create the main window.
135 window = MainWindow(widget)
149 window = MainWindow(app, widget, args.existing)
136 150 window.setWindowTitle('Python' if args.pure else 'IPython')
137 151 window.show()
138 152
@@ -105,6 +105,9 b' class QtSubSocketChannel(SocketChannelQObject, SubSocketChannel):'
105 105 # last-resort sys.excepthook.
106 106 crash_received = QtCore.pyqtSignal(object)
107 107
108 # Emitted when a shutdown is noticed.
109 shutdown_reply_received = QtCore.pyqtSignal(object)
110
108 111 #---------------------------------------------------------------------------
109 112 # 'SubSocketChannel' interface
110 113 #---------------------------------------------------------------------------
@@ -330,7 +330,7 b' class Kernel(Configurable):'
330 330
331 331 def shutdown_request(self, ident, parent):
332 332 self.shell.exit_now = True
333 self._shutdown_message = self.session.msg(u'shutdown_reply', {}, parent)
333 self._shutdown_message = self.session.msg(u'shutdown_reply', parent['content'], parent)
334 334 sys.exit(0)
335 335
336 336 #---------------------------------------------------------------------------
@@ -428,6 +428,7 b' class Kernel(Configurable):'
428 428 # io.rprint("Kernel at_shutdown") # dbg
429 429 if self._shutdown_message is not None:
430 430 self.reply_socket.send_json(self._shutdown_message)
431 self.pub_socket.send_json(self._shutdown_message)
431 432 io.raw_print(self._shutdown_message)
432 433 # A very short sleep to give zmq time to flush its message buffers
433 434 # before Python truly shuts down.
@@ -305,7 +305,7 b' class XReqSocketChannel(ZmqSocketChannel):'
305 305 self._queue_request(msg)
306 306 return msg['header']['msg_id']
307 307
308 def shutdown(self):
308 def shutdown(self, restart=False):
309 309 """Request an immediate kernel shutdown.
310 310
311 311 Upon receipt of the (empty) reply, client code can safely assume that
@@ -318,7 +318,7 b' class XReqSocketChannel(ZmqSocketChannel):'
318 318 """
319 319 # Send quit message to kernel. Once we implement kernel-side setattr,
320 320 # this should probably be done that way, but for now this will do.
321 msg = self.session.msg('shutdown_request', {})
321 msg = self.session.msg('shutdown_request', {'restart':restart})
322 322 self._queue_request(msg)
323 323 return msg['header']['msg_id']
324 324
@@ -743,7 +743,7 b' class KernelManager(HasTraits):'
743 743 self.rep_address = (LOCALHOST, req)
744 744 self.hb_address = (LOCALHOST, hb)
745 745
746 def shutdown_kernel(self):
746 def shutdown_kernel(self, restart=False):
747 747 """ Attempts to the stop the kernel process cleanly. If the kernel
748 748 cannot be stopped, it is killed, if possible.
749 749 """
@@ -759,7 +759,7 b' class KernelManager(HasTraits):'
759 759 # Don't send any additional kernel kill messages immediately, to give
760 760 # the kernel a chance to properly execute shutdown actions. Wait for at
761 761 # most 1s, checking every 0.1s.
762 self.xreq_channel.shutdown()
762 self.xreq_channel.shutdown(restart=restart)
763 763 for i in range(10):
764 764 if self.is_alive:
765 765 time.sleep(0.1)
@@ -793,7 +793,7 b' class KernelManager(HasTraits):'
793 793 if now:
794 794 self.kill_kernel()
795 795 else:
796 self.shutdown_kernel()
796 self.shutdown_kernel(restart=True)
797 797 self.start_kernel(**self._launch_args)
798 798
799 799 # FIXME: Messages get dropped in Windows due to probable ZMQ bug
@@ -60,7 +60,7 b' class Kernel(HasTraits):'
60 60
61 61 # Build dict of handlers for message types
62 62 msg_types = [ 'execute_request', 'complete_request',
63 'object_info_request' ]
63 'object_info_request', 'shutdown_request' ]
64 64 self.handlers = {}
65 65 for msg_type in msg_types:
66 66 self.handlers[msg_type] = getattr(self, msg_type)
@@ -163,6 +163,16 b' class Kernel(HasTraits):'
163 163 object_info, parent, ident)
164 164 print >> sys.__stdout__, msg
165 165
166 def shutdown_request(self, ident, parent):
167 content = dict(parent['content'])
168 msg = self.session.send(self.reply_socket, 'shutdown_reply',
169 content, parent, ident)
170 msg = self.session.send(self.pub_socket, 'shutdown_reply',
171 content, parent, ident)
172 print >> sys.__stdout__, msg
173 time.sleep(0.1)
174 sys.exit(0)
175
166 176 #---------------------------------------------------------------------------
167 177 # Protected interface
168 178 #---------------------------------------------------------------------------
@@ -663,11 +663,13 b' be sent, so the content dict is empty.'
663 663 Message type: ``shutdown_request``::
664 664
665 665 content = {
666 'restart' : bool # whether the shutdown is final, or precedes a restart
666 667 }
667 668
668 669 Message type: ``shutdown_reply``::
669 670
670 671 content = {
672 'restart' : bool # whether the shutdown is final, or precedes a restart
671 673 }
672 674
673 675 .. Note::
General Comments 0
You need to be logged in to leave comments. Login now