##// END OF EJS Templates
Merge branch 'minrk-keepkernel' into trunk...
Fernando Perez -
r3169:dc30beec merge
parent child Browse files
Show More
@@ -0,0 +1,40 b''
1 """Simple utility for building a list of local IPs using the socket module.
2 This module defines two constants:
3
4 LOCALHOST : The loopback interface, or the first interface that points to this
5 machine. It will *almost* always be '127.0.0.1'
6
7 LOCAL_IPS : A list of IP addresses, loopback first, that point to this machine.
8 """
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010 The IPython Development Team
11 #
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
19
20 import socket
21
22 #-----------------------------------------------------------------------------
23 # Code
24 #-----------------------------------------------------------------------------
25
26 LOCAL_IPS = []
27 try:
28 LOCAL_IPS = socket.gethostbyname_ex('localhost')[2]
29 except socket.gaierror:
30 pass
31
32 try:
33 LOCAL_IPS.extend(socket.gethostbyname_ex(socket.gethostname())[2])
34 except socket.gaierror:
35 pass
36
37 # include all-interface aliases: 0.0.0.0 and ''
38 LOCAL_IPS.extend(['0.0.0.0', ''])
39
40 LOCALHOST = LOCAL_IPS[0]
@@ -101,6 +101,7 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
101 101 _CompletionRequest = namedtuple('_CompletionRequest', ['id', 'pos'])
102 102 _ExecutionRequest = namedtuple('_ExecutionRequest', ['id', 'kind'])
103 103 _input_splitter_class = InputSplitter
104 _local_kernel = False
104 105
105 106 #---------------------------------------------------------------------------
106 107 # 'object' interface
@@ -141,6 +142,9 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
141 142 # Connect signal handlers.
142 143 document = self._control.document()
143 144 document.contentsChange.connect(self._document_contents_change)
145
146 # set flag for whether we are connected via localhost
147 self._local_kernel = kw.get('local_kernel', FrontendWidget._local_kernel)
144 148
145 149 #---------------------------------------------------------------------------
146 150 # 'ConsoleWidget' public interface
@@ -366,14 +370,32 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
366 370 """ Handle shutdown signal, only if from other console.
367 371 """
368 372 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()
373 if self._local_kernel:
374 if not msg['content']['restart']:
375 sys.exit(0)
376 else:
377 # we just got notified of a restart!
378 time.sleep(0.25) # wait 1/4 sec to reset
379 # lest the request for a new prompt
380 # goes to the old kernel
381 self.reset()
382 else: # remote kernel, prompt on Kernel shutdown/reset
383 title = self.window().windowTitle()
384 if not msg['content']['restart']:
385 reply = QtGui.QMessageBox.question(self, title,
386 "Kernel has been shutdown permanently. Close the Console?",
387 QtGui.QMessageBox.Yes,QtGui.QMessageBox.No)
388 if reply == QtGui.QMessageBox.Yes:
389 sys.exit(0)
390 else:
391 reply = QtGui.QMessageBox.question(self, title,
392 "Kernel has been reset. Clear the Console?",
393 QtGui.QMessageBox.Yes,QtGui.QMessageBox.No)
394 if reply == QtGui.QMessageBox.Yes:
395 time.sleep(0.25) # wait 1/4 sec to reset
396 # lest the request for a new prompt
397 # goes to the old kernel
398 self.reset()
377 399
378 400 def _started_channels(self):
379 401 """ Called when the KernelManager channels have started listening or
@@ -16,10 +16,10 b' from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget'
16 16 from IPython.frontend.qt.kernelmanager import QtKernelManager
17 17
18 18 #-----------------------------------------------------------------------------
19 # Constants
19 # Network Constants
20 20 #-----------------------------------------------------------------------------
21 21
22 LOCALHOST = '127.0.0.1'
22 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Classes
@@ -31,18 +31,24 b' class MainWindow(QtGui.QMainWindow):'
31 31 # 'object' interface
32 32 #---------------------------------------------------------------------------
33 33
34 def __init__(self, app, frontend, existing=False):
34 def __init__(self, app, frontend, existing=False, may_close=True):
35 35 """ Create a MainWindow for the specified FrontendWidget.
36 36
37 37 The app is passed as an argument to allow for different
38 38 closing behavior depending on whether we are the Kernel's parent.
39 39
40 If existing is True, then this Window does not own the Kernel.
40 If existing is True, then this Console does not own the Kernel.
41
42 If may_close is True, then this Console is permitted to close the kernel
41 43 """
42 44 super(MainWindow, self).__init__()
43 45 self._app = app
44 46 self._frontend = frontend
45 47 self._existing = existing
48 if existing:
49 self._may_close = may_close
50 else:
51 self._may_close = True
46 52 self._frontend.exit_requested.connect(self.close)
47 53 self.setCentralWidget(frontend)
48 54
@@ -56,21 +62,47 b' class MainWindow(QtGui.QMainWindow):'
56 62 kernel_manager = self._frontend.kernel_manager
57 63 if kernel_manager and kernel_manager.channels_running:
58 64 title = self.window().windowTitle()
59 reply = QtGui.QMessageBox.question(self, title,
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
64 kernel_manager.shutdown_kernel()
65 #kernel_manager.stop_channels()
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()
65 cancel = QtGui.QMessageBox.Cancel
66 okay = QtGui.QMessageBox.Ok
67 if self._may_close:
68 msg = "You are closing this Console window."
69 info = "Would you like to quit the Kernel and all attached Consoles as well?"
70 justthis = QtGui.QPushButton("&No, just this Console", self)
71 justthis.setShortcut('N')
72 closeall = QtGui.QPushButton("&Yes, quit everything", self)
73 closeall.setShortcut('Y')
74 box = QtGui.QMessageBox(QtGui.QMessageBox.Question, title, msg)
75 box.setInformativeText(info)
76 box.addButton(cancel)
77 box.addButton(justthis, QtGui.QMessageBox.NoRole)
78 box.addButton(closeall, QtGui.QMessageBox.YesRole)
79 box.setDefaultButton(closeall)
80 box.setEscapeButton(cancel)
81 reply = box.exec_()
82 if reply == 1: # close All
83 kernel_manager.shutdown_kernel()
84 #kernel_manager.stop_channels()
85 event.accept()
86 elif reply == 0: # close Console
87 if not self._existing:
88 # I have the kernel: don't quit, just close the window
89 self._app.setQuitOnLastWindowClosed(False)
90 self.deleteLater()
91 event.accept()
92 else:
93 event.ignore()
72 94 else:
73 event.ignore()
95 reply = QtGui.QMessageBox.question(self, title,
96 "Are you sure you want to close this Console?"+
97 "\nThe Kernel and other Consoles will remain active.",
98 okay|cancel,
99 defaultButton=okay
100 )
101 if reply == okay:
102 event.accept()
103 else:
104 event.ignore()
105
74 106
75 107 #-----------------------------------------------------------------------------
76 108 # Main entry point
@@ -85,7 +117,11 b' def main():'
85 117 kgroup.add_argument('-e', '--existing', action='store_true',
86 118 help='connect to an existing kernel')
87 119 kgroup.add_argument('--ip', type=str, default=LOCALHOST,
88 help='set the kernel\'s IP address [default localhost]')
120 help=\
121 "set the kernel\'s IP address [default localhost].\
122 If the IP address is something other than localhost, then \
123 Consoles on other machines will be able to connect\
124 to the Kernel, so be careful!")
89 125 kgroup.add_argument('--xreq', type=int, metavar='PORT', default=0,
90 126 help='set the XREQ channel port [default random]')
91 127 kgroup.add_argument('--sub', type=int, metavar='PORT', default=0,
@@ -124,29 +160,34 b' def main():'
124 160 sub_address=(args.ip, args.sub),
125 161 rep_address=(args.ip, args.rep),
126 162 hb_address=(args.ip, args.hb))
127 if args.ip == LOCALHOST and not args.existing:
163 if not args.existing:
164 # if not args.ip in LOCAL_IPS+ALL_ALIAS:
165 # raise ValueError("Must bind a local ip, such as: %s"%LOCAL_IPS)
166
167 kwargs = dict(ip=args.ip)
128 168 if args.pure:
129 kernel_manager.start_kernel(ipython=False)
169 kwargs['ipython']=False
130 170 elif args.pylab:
131 kernel_manager.start_kernel(pylab=args.pylab)
132 else:
133 kernel_manager.start_kernel()
171 kwargs['pylab']=args.pylab
172
173 kernel_manager.start_kernel(**kwargs)
134 174 kernel_manager.start_channels()
135 175
176 local_kernel = (not args.existing) or args.ip in LOCAL_IPS
136 177 # Create the widget.
137 178 app = QtGui.QApplication([])
138 179 if args.pure:
139 180 kind = 'rich' if args.rich else 'plain'
140 widget = FrontendWidget(kind=kind, paging=args.paging)
181 widget = FrontendWidget(kind=kind, paging=args.paging, local_kernel=local_kernel)
141 182 elif args.rich or args.pylab:
142 widget = RichIPythonWidget(paging=args.paging)
183 widget = RichIPythonWidget(paging=args.paging, local_kernel=local_kernel)
143 184 else:
144 widget = IPythonWidget(paging=args.paging)
185 widget = IPythonWidget(paging=args.paging, local_kernel=local_kernel)
145 186 widget.gui_completion = args.gui_completion
146 187 widget.kernel_manager = kernel_manager
147 188
148 189 # Create the main window.
149 window = MainWindow(app, widget, args.existing)
190 window = MainWindow(app, widget, args.existing, may_close=local_kernel)
150 191 window.setWindowTitle('Python' if args.pure else 'IPython')
151 192 window.show()
152 193
@@ -16,6 +16,7 b' import zmq'
16 16 from IPython.core.ultratb import FormattedTB
17 17 from IPython.external.argparse import ArgumentParser
18 18 from IPython.utils import io
19 from IPython.utils.localinterfaces import LOCALHOST
19 20 from displayhook import DisplayHook
20 21 from heartbeat import Heartbeat
21 22 from iostream import OutStream
@@ -40,7 +41,7 b' def make_argument_parser():'
40 41 kernel entry points.
41 42 """
42 43 parser = ArgumentParser()
43 parser.add_argument('--ip', type=str, default='127.0.0.1',
44 parser.add_argument('--ip', type=str, default=LOCALHOST,
44 45 help='set the kernel\'s IP address [default: local]')
45 46 parser.add_argument('--xrep', type=int, metavar='PORT', default=0,
46 47 help='set the XREP channel port [default: random]')
@@ -17,6 +17,7 b' import uuid'
17 17 import zmq
18 18 import session
19 19 import completer
20 from IPython.utils.localinterfaces import LOCALHOST
20 21
21 22 #-----------------------------------------------------------------------------
22 23 # Classes and functions
@@ -168,7 +169,7 b' class InteractiveClient(object):'
168 169 def main():
169 170 # Defaults
170 171 #ip = '192.168.2.109'
171 ip = '127.0.0.1'
172 ip = LOCALHOST
172 173 #ip = '99.146.222.252'
173 174 port_base = 5575
174 175 connection = ('tcp://%s' % ip) + ':%i'
@@ -17,6 +17,8 b' from threading import Thread'
17 17
18 18 import zmq
19 19
20 from IPython.utils.localinterfaces import LOCALHOST
21
20 22 #-----------------------------------------------------------------------------
21 23 # Code
22 24 #-----------------------------------------------------------------------------
@@ -25,7 +27,7 b' import zmq'
25 27 class Heartbeat(Thread):
26 28 "A simple ping-pong style heartbeat that runs in a thread."
27 29
28 def __init__(self, context, addr=('127.0.0.1', 0)):
30 def __init__(self, context, addr=(LOCALHOST, 0)):
29 31 Thread.__init__(self)
30 32 self.context = context
31 33 self.addr = addr
@@ -534,12 +534,15 b' class GTKKernel(Kernel):'
534 534 # Kernel main and launch functions
535 535 #-----------------------------------------------------------------------------
536 536
537 def launch_kernel(xrep_port=0, pub_port=0, req_port=0, hb_port=0,
537 def launch_kernel(ip=None, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
538 538 independent=False, pylab=False):
539 539 """Launches a localhost kernel, binding to the specified ports.
540 540
541 541 Parameters
542 542 ----------
543 ip : str, optional
544 The ip address the kernel will bind to.
545
543 546 xrep_port : int, optional
544 547 The port to use for XREP channel.
545 548
@@ -574,6 +577,10 b' def launch_kernel(xrep_port=0, pub_port=0, req_port=0, hb_port=0,'
574 577 extra_arguments.append('--pylab')
575 578 if isinstance(pylab, basestring):
576 579 extra_arguments.append(pylab)
580 if ip is not None:
581 extra_arguments.append('--ip')
582 if isinstance(ip, basestring):
583 extra_arguments.append(ip)
577 584 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
578 585 xrep_port, pub_port, req_port, hb_port,
579 586 independent, extra_arguments)
@@ -31,6 +31,7 b' from zmq.eventloop import ioloop'
31 31
32 32 # Local imports.
33 33 from IPython.utils import io
34 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
34 35 from IPython.utils.traitlets import HasTraits, Any, Instance, Type, TCPAddress
35 36 from session import Session
36 37
@@ -38,8 +39,6 b' from session import Session'
38 39 # Constants and exceptions
39 40 #-----------------------------------------------------------------------------
40 41
41 LOCALHOST = '127.0.0.1'
42
43 42 class InvalidPortNumber(Exception):
44 43 pass
45 44
@@ -724,24 +723,26 b' class KernelManager(HasTraits):'
724 723 """
725 724 xreq, sub, rep, hb = self.xreq_address, self.sub_address, \
726 725 self.rep_address, self.hb_address
727 if xreq[0] != LOCALHOST or sub[0] != LOCALHOST or \
728 rep[0] != LOCALHOST or hb[0] != LOCALHOST:
729 raise RuntimeError("Can only launch a kernel on localhost."
726 if xreq[0] not in LOCAL_IPS or sub[0] not in LOCAL_IPS or \
727 rep[0] not in LOCAL_IPS or hb[0] not in LOCAL_IPS:
728 raise RuntimeError("Can only launch a kernel on a local interface. "
730 729 "Make sure that the '*_address' attributes are "
731 "configured properly.")
732
730 "configured properly. "
731 "Currently valid addresses are: %s"%LOCAL_IPS
732 )
733
733 734 self._launch_args = kw.copy()
734 735 if kw.pop('ipython', True):
735 736 from ipkernel import launch_kernel
736 737 else:
737 738 from pykernel import launch_kernel
738 self.kernel, xrep, pub, req, hb = launch_kernel(
739 self.kernel, xrep, pub, req, _hb = launch_kernel(
739 740 xrep_port=xreq[1], pub_port=sub[1],
740 741 req_port=rep[1], hb_port=hb[1], **kw)
741 self.xreq_address = (LOCALHOST, xrep)
742 self.sub_address = (LOCALHOST, pub)
743 self.rep_address = (LOCALHOST, req)
744 self.hb_address = (LOCALHOST, hb)
742 self.xreq_address = (xreq[0], xrep)
743 self.sub_address = (sub[0], pub)
744 self.rep_address = (rep[0], req)
745 self.hb_address = (hb[0], _hb)
745 746
746 747 def shutdown_kernel(self, restart=False):
747 748 """ Attempts to the stop the kernel process cleanly. If the kernel
@@ -256,12 +256,15 b' class Kernel(HasTraits):'
256 256 # Kernel main and launch functions
257 257 #-----------------------------------------------------------------------------
258 258
259 def launch_kernel(xrep_port=0, pub_port=0, req_port=0, hb_port=0,
259 def launch_kernel(ip=None, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
260 260 independent=False):
261 261 """ Launches a localhost kernel, binding to the specified ports.
262 262
263 263 Parameters
264 264 ----------
265 ip : str, optional
266 The ip address the kernel will bind to.
267
265 268 xrep_port : int, optional
266 269 The port to use for XREP channel.
267 270
@@ -286,9 +289,15 b' def launch_kernel(xrep_port=0, pub_port=0, req_port=0, hb_port=0,'
286 289 (kernel_process, xrep_port, pub_port, req_port)
287 290 where kernel_process is a Popen object and the ports are integers.
288 291 """
292 extra_arguments = []
293 if ip is not None:
294 extra_arguments.append('--ip')
295 if isinstance(ip, basestring):
296 extra_arguments.append(ip)
297
289 298 return base_launch_kernel('from IPython.zmq.pykernel import main; main()',
290 299 xrep_port, pub_port, req_port, hb_port,
291 independent)
300 independent, extra_arguments=extra_arguments)
292 301
293 302 main = make_default_main(Kernel)
294 303
General Comments 0
You need to be logged in to leave comments. Login now