Show More
@@ -62,35 +62,35 b' class IPythonWidget(FrontendWidget):' | |||||
62 |
|
62 | |||
63 |
|
63 | |||
64 | if __name__ == '__main__': |
|
64 | if __name__ == '__main__': | |
65 | from IPython.external.argparse import ArgumentParser |
|
|||
66 | from IPython.frontend.qt.kernelmanager import QtKernelManager |
|
|||
67 |
|
||||
68 | # Don't let Qt swallow KeyboardInterupts. |
|
|||
69 | import signal |
|
65 | import signal | |
70 | signal.signal(signal.SIGINT, signal.SIG_DFL) |
|
66 | from IPython.frontend.qt.kernelmanager import QtKernelManager | |
71 |
|
67 | |||
72 | # Parse command line arguments. |
|
68 | # Create a KernelManager. | |
73 | parser = ArgumentParser() |
|
69 | kernel_manager = QtKernelManager() | |
74 | parser.add_argument('--ip', type=str, default='127.0.0.1', |
|
70 | kernel_manager.start_kernel() | |
75 | help='set the kernel\'s IP address [default localhost]') |
|
|||
76 | parser.add_argument('--xreq', type=int, metavar='PORT', default=5575, |
|
|||
77 | help='set the XREQ Channel port [default %(default)i]') |
|
|||
78 | parser.add_argument('--sub', type=int, metavar='PORT', default=5576, |
|
|||
79 | help='set the SUB Channel port [default %(default)i]') |
|
|||
80 | namespace = parser.parse_args() |
|
|||
81 |
|
||||
82 | # Create KernelManager |
|
|||
83 | ip = namespace.ip |
|
|||
84 | kernel_manager = QtKernelManager(xreq_address = (ip, namespace.xreq), |
|
|||
85 | sub_address = (ip, namespace.sub)) |
|
|||
86 | kernel_manager.start_listening() |
|
71 | kernel_manager.start_listening() | |
87 |
|
72 | |||
88 | # Launch application |
|
73 | # Don't let Qt or ZMQ swallow KeyboardInterupts. | |
|
74 | # FIXME: Gah, ZMQ swallows even custom signal handlers. So for now we leave | |||
|
75 | # behind a kernel process when Ctrl-C is pressed. | |||
|
76 | #def sigint_hook(signum, frame): | |||
|
77 | # QtGui.qApp.quit() | |||
|
78 | #signal.signal(signal.SIGINT, sigint_hook) | |||
|
79 | signal.signal(signal.SIGINT, signal.SIG_DFL) | |||
|
80 | ||||
|
81 | # Create the application, making sure to clean up nicely when we exit. | |||
89 | app = QtGui.QApplication([]) |
|
82 | app = QtGui.QApplication([]) | |
|
83 | def quit_hook(): | |||
|
84 | kernel_manager.stop_listening() | |||
|
85 | kernel_manager.kill_kernel() | |||
|
86 | app.aboutToQuit.connect(quit_hook) | |||
|
87 | ||||
|
88 | # Launch the application. | |||
90 | widget = IPythonWidget() |
|
89 | widget = IPythonWidget() | |
91 | widget.kernel_manager = kernel_manager |
|
90 | widget.kernel_manager = kernel_manager | |
92 | widget.setWindowTitle('Python') |
|
91 | widget.setWindowTitle('Python') | |
93 | widget.resize(640, 480) |
|
92 | widget.resize(640, 480) | |
94 | widget.show() |
|
93 | widget.show() | |
95 | app.exec_() |
|
94 | app.exec_() | |
|
95 | ||||
96 |
|
96 |
@@ -22,6 +22,7 b' from code import CommandCompiler' | |||||
22 | import zmq |
|
22 | import zmq | |
23 |
|
23 | |||
24 | # Local imports. |
|
24 | # Local imports. | |
|
25 | from IPython.external.argparse import ArgumentParser | |||
25 | from session import Session, Message, extract_header |
|
26 | from session import Session, Message, extract_header | |
26 | from completer import KernelCompleter |
|
27 | from completer import KernelCompleter | |
27 |
|
28 | |||
@@ -282,23 +283,33 b' def bind_port(socket, ip, port):' | |||||
282 | socket.bind(connection) |
|
283 | socket.bind(connection) | |
283 | return port |
|
284 | return port | |
284 |
|
285 | |||
285 | def main(ip='127.0.0.1', rep_port=-1, pub_port=-1): |
|
286 | def main(): | |
286 | """ Start a kernel on 'ip' (default localhost) at the specified ports. If |
|
287 | """ Main entry point for launching a kernel. | |
287 | ports are not specified, they are chosen at random. |
|
|||
288 | """ |
|
288 | """ | |
|
289 | # Parse command line arguments. | |||
|
290 | parser = ArgumentParser() | |||
|
291 | parser.add_argument('--ip', type=str, default='127.0.0.1', | |||
|
292 | help='set the kernel\'s IP address [default: local]') | |||
|
293 | parser.add_argument('--xrep', type=int, metavar='PORT', default=-1, | |||
|
294 | help='set the XREP Channel port [default: random]') | |||
|
295 | parser.add_argument('--pub', type=int, metavar='PORT', default=-1, | |||
|
296 | help='set the PUB Channel port [default: random]') | |||
|
297 | namespace = parser.parse_args() | |||
|
298 | ||||
|
299 | # Create context, session, and kernel sockets. | |||
289 | print >>sys.__stdout__, "Starting the kernel..." |
|
300 | print >>sys.__stdout__, "Starting the kernel..." | |
290 |
|
||||
291 | context = zmq.Context() |
|
301 | context = zmq.Context() | |
292 | session = Session(username=u'kernel') |
|
302 | session = Session(username=u'kernel') | |
293 |
|
303 | |||
294 | reply_socket = context.socket(zmq.XREP) |
|
304 | reply_socket = context.socket(zmq.XREP) | |
295 |
rep_port = bind_port(reply_socket, ip, |
|
305 | xrep_port = bind_port(reply_socket, namespace.ip, namespace.xrep) | |
296 | print >>sys.__stdout__, "XREP Channel on port", rep_port |
|
306 | print >>sys.__stdout__, "XREP Channel on port", xrep_port | |
297 |
|
307 | |||
298 | pub_socket = context.socket(zmq.PUB) |
|
308 | pub_socket = context.socket(zmq.PUB) | |
299 |
pub_port = bind_port(pub_socket, ip, pub |
|
309 | pub_port = bind_port(pub_socket, namespace.ip, namespace.pub) | |
300 | print >>sys.__stdout__, "PUB Channel on port", pub_port |
|
310 | print >>sys.__stdout__, "PUB Channel on port", pub_port | |
301 |
|
311 | |||
|
312 | # Redirect input streams and set a display hook. | |||
302 | sys.stdout = OutStream(session, pub_socket, u'stdout') |
|
313 | sys.stdout = OutStream(session, pub_socket, u'stdout') | |
303 | sys.stderr = OutStream(session, pub_socket, u'stderr') |
|
314 | sys.stderr = OutStream(session, pub_socket, u'stderr') | |
304 | sys.displayhook = DisplayHook(session, pub_socket) |
|
315 | sys.displayhook = DisplayHook(session, pub_socket) | |
@@ -313,9 +324,9 b" def main(ip='127.0.0.1', rep_port=-1, pub_port=-1):" | |||||
313 | print >>sys.__stdout__, "Use Ctrl-\\ (NOT Ctrl-C!) to terminate." |
|
324 | print >>sys.__stdout__, "Use Ctrl-\\ (NOT Ctrl-C!) to terminate." | |
314 | kernel.start() |
|
325 | kernel.start() | |
315 |
|
326 | |||
316 | def launch_kernel(): |
|
327 | def launch_kernel(xrep_port=-1, pub_port=-1): | |
317 | """ Launches a kernel on this machine and binds its to channels to open |
|
328 | """ Launches a localhost kernel, binding to the specified ports. For any | |
318 | ports as it determined by the OS. |
|
329 | port that is left unspecified, a port is chosen by the operating system. | |
319 |
|
330 | |||
320 | Returns a tuple of form: |
|
331 | Returns a tuple of form: | |
321 | (kernel_process [Popen], rep_port [int], sub_port [int]) |
|
332 | (kernel_process [Popen], rep_port [int], sub_port [int]) | |
@@ -323,9 +334,10 b' def launch_kernel():' | |||||
323 | import socket |
|
334 | import socket | |
324 | from subprocess import Popen |
|
335 | from subprocess import Popen | |
325 |
|
336 | |||
326 |
# Find |
|
337 | # Find open ports as necessary. | |
327 | ports = [] |
|
338 | ports = [] | |
328 | for i in xrange(2): |
|
339 | ports_needed = int(xrep_port < 0) + int(pub_port < 0) | |
|
340 | for i in xrange(ports_needed): | |||
329 | sock = socket.socket() |
|
341 | sock = socket.socket() | |
330 | sock.bind(('', 0)) |
|
342 | sock.bind(('', 0)) | |
331 | ports.append(sock) |
|
343 | ports.append(sock) | |
@@ -333,17 +345,17 b' def launch_kernel():' | |||||
333 | port = sock.getsockname()[1] |
|
345 | port = sock.getsockname()[1] | |
334 | sock.close() |
|
346 | sock.close() | |
335 | ports[i] = port |
|
347 | ports[i] = port | |
336 | rep_port, sub_port = ports |
|
348 | if xrep_port < 0: | |
337 |
|
349 | xrep_port = ports.pop() | ||
|
350 | if pub_port < 0: | |||
|
351 | pub_port = ports.pop() | |||
|
352 | ||||
338 | # Spawn a kernel. |
|
353 | # Spawn a kernel. | |
339 |
command = 'from IPython.zmq.kernel import main;' |
|
354 | command = 'from IPython.zmq.kernel import main; main()' | |
340 | 'main(rep_port=%i, pub_port=%i)' |
|
355 | proc = Popen([ sys.executable, '-c', command, | |
341 | proc = Popen([sys.executable, '-c', command % (rep_port, sub_port)]) |
|
356 | '--xrep', str(xrep_port), '--pub', str(pub_port) ]) | |
342 |
|
357 | return proc, xrep_port, pub_port | ||
343 | return proc, rep_port, sub_port |
|
358 | ||
344 |
|
||||
345 |
|
359 | |||
346 | if __name__ == '__main__': |
|
360 | if __name__ == '__main__': | |
347 | base_port = 5575 |
|
361 | main() | |
348 | main(rep_port = base_port, |
|
|||
349 | pub_port = base_port + 1) |
|
@@ -6,6 +6,7 b' TODO: Create logger to handle debugging and console messages.' | |||||
6 |
|
6 | |||
7 | # Standard library imports. |
|
7 | # Standard library imports. | |
8 | from Queue import Queue, Empty |
|
8 | from Queue import Queue, Empty | |
|
9 | from subprocess import Popen | |||
9 | from threading import Thread |
|
10 | from threading import Thread | |
10 | import time |
|
11 | import time | |
11 | import traceback |
|
12 | import traceback | |
@@ -18,8 +19,12 b' from zmq.eventloop import ioloop' | |||||
18 | # Local imports. |
|
19 | # Local imports. | |
19 | from IPython.utils.traitlets import HasTraits, Any, Bool, Int, Instance, Str, \ |
|
20 | from IPython.utils.traitlets import HasTraits, Any, Bool, Int, Instance, Str, \ | |
20 | Type |
|
21 | Type | |
|
22 | from kernel import launch_kernel | |||
21 | from session import Session |
|
23 | from session import Session | |
22 |
|
24 | |||
|
25 | # Constants. | |||
|
26 | LOCALHOST = '127.0.0.1' | |||
|
27 | ||||
23 |
|
28 | |||
24 | class MissingHandlerError(Exception): |
|
29 | class MissingHandlerError(Exception): | |
25 | pass |
|
30 | pass | |
@@ -49,19 +54,22 b' class ZmqSocketChannel(Thread):' | |||||
49 | Thread.__init__(self) |
|
54 | Thread.__init__(self) | |
50 |
|
55 | |||
51 | def get_address(self): |
|
56 | def get_address(self): | |
52 | """ Get the channel's address. |
|
57 | """ Get the channel's address. By the default, a channel is on | |
|
58 | localhost with no port specified (a negative port number). | |||
53 | """ |
|
59 | """ | |
54 | return self._address |
|
60 | return self._address | |
55 |
|
61 | |||
56 | def set_adresss(self, address): |
|
62 | def set_adresss(self, address): | |
57 | """ Set the channel's address. Should be a tuple of form: |
|
63 | """ Set the channel's address. Should be a tuple of form: | |
58 | (ip address [str], port [int]) |
|
64 | (ip address [str], port [int]). | |
59 |
or |
|
65 | or None, in which case the address is reset to its default value. | |
60 | """ |
|
66 | """ | |
61 | # FIXME: Validate address. |
|
67 | # FIXME: Validate address. | |
62 | if self.is_alive(): |
|
68 | if self.is_alive(): | |
63 | raise RuntimeError("Cannot set address on a running channel!") |
|
69 | raise RuntimeError("Cannot set address on a running channel!") | |
64 | else: |
|
70 | else: | |
|
71 | if address is None: | |||
|
72 | address = (LOCALHOST, -1) | |||
65 | self._address = address |
|
73 | self._address = address | |
66 |
|
74 | |||
67 | address = property(get_address, set_adresss) |
|
75 | address = property(get_address, set_adresss) | |
@@ -314,6 +322,7 b' class KernelManager(HasTraits):' | |||||
314 | rep_channel_class = Type(RepSocketChannel) |
|
322 | rep_channel_class = Type(RepSocketChannel) | |
315 |
|
323 | |||
316 | # Protected traits. |
|
324 | # Protected traits. | |
|
325 | _kernel = Instance(Popen) | |||
317 | _sub_channel = Any |
|
326 | _sub_channel = Any | |
318 | _xreq_channel = Any |
|
327 | _xreq_channel = Any | |
319 | _rep_channel = Any |
|
328 | _rep_channel = Any | |
@@ -347,17 +356,26 b' class KernelManager(HasTraits):' | |||||
347 | self.rep_channel.stop() |
|
356 | self.rep_channel.stop() | |
348 |
|
357 | |||
349 | def start_kernel(self): |
|
358 | def start_kernel(self): | |
350 |
"""Start a localhost kernel. If ports have been specified |
|
359 | """Start a localhost kernel. If ports have been specified via the | |
351 |
Otherwise, choose |
|
360 | address attributes, use them. Otherwise, choose open ports at random. | |
352 | """ |
|
361 | """ | |
353 | # TODO: start a kernel. |
|
362 | xreq, sub = self.xreq_address, self.sub_address | |
354 | self.start_listening() |
|
363 | if xreq[0] != LOCALHOST or sub[0] != LOCALHOST: | |
|
364 | raise RuntimeError("Can only launch a kernel on localhost." | |||
|
365 | "Make sure that the '*_address' attributes are " | |||
|
366 | "configured properly.") | |||
|
367 | ||||
|
368 | self._kernel, xrep, pub = launch_kernel(xrep_port=xreq[1], | |||
|
369 | pub_port=sub[1]) | |||
|
370 | self.xreq_address = (LOCALHOST, xrep) | |||
|
371 | self.sub_address = (LOCALHOST, pub) | |||
355 |
|
372 | |||
356 | def kill_kernel(self): |
|
373 | def kill_kernel(self): | |
357 | """Kill the running kernel. |
|
374 | """Kill the running kernel, if there is one. | |
358 | """ |
|
375 | """ | |
359 | # TODO: kill the kernel. |
|
376 | if self._kernel: | |
360 |
self. |
|
377 | self._kernel.kill() | |
|
378 | self._kernel = None | |||
361 |
|
379 | |||
362 | @property |
|
380 | @property | |
363 | def is_alive(self): |
|
381 | def is_alive(self): |
General Comments 0
You need to be logged in to leave comments.
Login now