Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

zmq kernels now started via newapp

  • Loading branch information...
commit 048514e464f21073c3f05098f5d4e34ccd9a4649 1 parent 91fd632
Min RK authored
7 IPython/frontend/qt/console/ipythonqt.py
@@ -217,9 +217,12 @@ def main():
217 217 if args.pure:
218 218 kwargs['ipython']=False
219 219 else:
220   - kwargs['colors']=colors
  220 + extra = []
  221 + if colors:
  222 + extra.append("colors=%s"%colors)
221 223 if args.pylab:
222   - kwargs['pylab']=args.pylab
  224 + extra.append("pylab=%s"%args.pylab)
  225 + kwargs['extra_arguments'] = extra
223 226
224 227 kernel_manager.start_kernel(**kwargs)
225 228 kernel_manager.start_channels()
197 IPython/zmq/entry_point.py
@@ -9,159 +9,14 @@
9 9 from subprocess import Popen, PIPE
10 10 import sys
11 11
12   -# System library imports.
13   -import zmq
14   -
15 12 # Local imports.
16   -from IPython.core.ultratb import FormattedTB
17   -from IPython.external.argparse import ArgumentParser
18   -from IPython.utils import io
19   -from IPython.utils.localinterfaces import LOCALHOST
20   -from displayhook import DisplayHook
21   -from heartbeat import Heartbeat
22   -from iostream import OutStream
23   -from parentpoller import ParentPollerUnix, ParentPollerWindows
24   -from session import Session
25   -
26   -
27   -def bind_port(socket, ip, port):
28   - """ Binds the specified ZMQ socket. If the port is zero, a random port is
29   - chosen. Returns the port that was bound.
30   - """
31   - connection = 'tcp://%s' % ip
32   - if port <= 0:
33   - port = socket.bind_to_random_port(connection)
34   - else:
35   - connection += ':%i' % port
36   - socket.bind(connection)
37   - return port
38   -
39   -
40   -def make_argument_parser():
41   - """ Creates an ArgumentParser for the generic arguments supported by all
42   - kernel entry points.
43   - """
44   - parser = ArgumentParser()
45   - parser.add_argument('--ip', type=str, default=LOCALHOST,
46   - help='set the kernel\'s IP address [default: local]')
47   - parser.add_argument('--xrep', type=int, metavar='PORT', default=0,
48   - help='set the XREP channel port [default: random]')
49   - parser.add_argument('--pub', type=int, metavar='PORT', default=0,
50   - help='set the PUB channel port [default: random]')
51   - parser.add_argument('--req', type=int, metavar='PORT', default=0,
52   - help='set the REQ channel port [default: random]')
53   - parser.add_argument('--hb', type=int, metavar='PORT', default=0,
54   - help='set the heartbeat port [default: random]')
55   - parser.add_argument('--no-stdout', action='store_true',
56   - help='redirect stdout to the null device')
57   - parser.add_argument('--no-stderr', action='store_true',
58   - help='redirect stderr to the null device')
59   -
60   - if sys.platform == 'win32':
61   - parser.add_argument('--interrupt', type=int, metavar='HANDLE',
62   - default=0, help='interrupt this process when '
63   - 'HANDLE is signaled')
64   - parser.add_argument('--parent', type=int, metavar='HANDLE',
65   - default=0, help='kill this process if the process '
66   - 'with HANDLE dies')
67   - else:
68   - parser.add_argument('--parent', action='store_true',
69   - help='kill this process if its parent dies')
70   -
71   - return parser
72   -
73   -
74   -def make_kernel(namespace, kernel_factory,
75   - out_stream_factory=None, display_hook_factory=None):
76   - """ Creates a kernel, redirects stdout/stderr, and installs a display hook
77   - and exception handler.
78   - """
79   - # Re-direct stdout/stderr, if necessary.
80   - if namespace.no_stdout or namespace.no_stderr:
81   - blackhole = file(os.devnull, 'w')
82   - if namespace.no_stdout:
83   - sys.stdout = sys.__stdout__ = blackhole
84   - if namespace.no_stderr:
85   - sys.stderr = sys.__stderr__ = blackhole
86   -
87   - # Install minimal exception handling
88   - sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
89   - ostream=sys.__stdout__)
  13 +from parentpoller import ParentPollerWindows
90 14
91   - # Create a context, a session, and the kernel sockets.
92   - io.raw_print("Starting the kernel at pid:", os.getpid())
93   - context = zmq.Context()
94   - # Uncomment this to try closing the context.
95   - # atexit.register(context.close)
96   - session = Session(username=u'kernel')
97 15
98   - reply_socket = context.socket(zmq.XREP)
99   - xrep_port = bind_port(reply_socket, namespace.ip, namespace.xrep)
100   - io.raw_print("XREP Channel on port", xrep_port)
101 16
102   - pub_socket = context.socket(zmq.PUB)
103   - pub_port = bind_port(pub_socket, namespace.ip, namespace.pub)
104   - io.raw_print("PUB Channel on port", pub_port)
105   -
106   - req_socket = context.socket(zmq.XREQ)
107   - req_port = bind_port(req_socket, namespace.ip, namespace.req)
108   - io.raw_print("REQ Channel on port", req_port)
109   -
110   - hb = Heartbeat(context, (namespace.ip, namespace.hb))
111   - hb.start()
112   - hb_port = hb.port
113   - io.raw_print("Heartbeat REP Channel on port", hb_port)
114   -
115   - # Helper to make it easier to connect to an existing kernel, until we have
116   - # single-port connection negotiation fully implemented.
117   - io.raw_print("To connect another client to this kernel, use:")
118   - io.raw_print("-e --xreq {0} --sub {1} --rep {2} --hb {3}".format(
119   - xrep_port, pub_port, req_port, hb_port))
120   -
121   - # Redirect input streams and set a display hook.
122   - if out_stream_factory:
123   - sys.stdout = out_stream_factory(session, pub_socket, u'stdout')
124   - sys.stderr = out_stream_factory(session, pub_socket, u'stderr')
125   - if display_hook_factory:
126   - sys.displayhook = display_hook_factory(session, pub_socket)
127   -
128   - # Create the kernel.
129   - kernel = kernel_factory(session=session, reply_socket=reply_socket,
130   - pub_socket=pub_socket, req_socket=req_socket)
131   - kernel.record_ports(xrep_port=xrep_port, pub_port=pub_port,
132   - req_port=req_port, hb_port=hb_port)
133   - return kernel
134   -
135   -
136   -def start_kernel(namespace, kernel):
137   - """ Starts a kernel.
138   - """
139   - # Configure this kernel process to poll the parent process, if necessary.
140   - if sys.platform == 'win32':
141   - if namespace.interrupt or namespace.parent:
142   - poller = ParentPollerWindows(namespace.interrupt, namespace.parent)
143   - poller.start()
144   - elif namespace.parent:
145   - poller = ParentPollerUnix()
146   - poller.start()
147   -
148   - # Start the kernel mainloop.
149   - kernel.start()
150   -
151   -
152   -def make_default_main(kernel_factory):
153   - """ Creates the simplest possible kernel entry point.
154   - """
155   - def main():
156   - namespace = make_argument_parser().parse_args()
157   - kernel = make_kernel(namespace, kernel_factory, OutStream, DisplayHook)
158   - start_kernel(namespace, kernel)
159   - return main
160   -
161   -
162   -def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
163   - stdin=None, stdout=None, stderr=None,
164   - executable=None, independent=False, extra_arguments=[]):
  17 +def base_launch_kernel(code, shell_port=0, iopub_port=0, stdin_port=0, hb_port=0,
  18 + ip=None, stdin=None, stdout=None, stderr=None,
  19 + executable=None, independent=False, extra_arguments=[]):
165 20 """ Launches a localhost kernel, binding to the specified ports.
166 21
167 22 Parameters
@@ -169,18 +24,21 @@ def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
169 24 code : str,
170 25 A string of Python code that imports and executes a kernel entry point.
171 26
172   - xrep_port : int, optional
  27 + shell_port : int, optional
173 28 The port to use for XREP channel.
174 29
175   - pub_port : int, optional
  30 + iopub_port : int, optional
176 31 The port to use for the SUB channel.
177 32
178   - req_port : int, optional
  33 + stdin_port : int, optional
179 34 The port to use for the REQ (raw input) channel.
180 35
181 36 hb_port : int, optional
182 37 The port to use for the hearbeat REP channel.
183 38
  39 + ip : str, optional
  40 + The ip address the kernel will bind to.
  41 +
184 42 stdin, stdout, stderr : optional (default None)
185 43 Standards streams, as defined in subprocess.Popen.
186 44
@@ -199,13 +57,13 @@ def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
199 57 Returns
200 58 -------
201 59 A tuple of form:
202   - (kernel_process, xrep_port, pub_port, req_port)
  60 + (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
203 61 where kernel_process is a Popen object and the ports are integers.
204 62 """
205 63 # Find open ports as necessary.
206 64 ports = []
207   - ports_needed = int(xrep_port <= 0) + int(pub_port <= 0) + \
208   - int(req_port <= 0) + int(hb_port <= 0)
  65 + ports_needed = int(shell_port <= 0) + int(iopub_port <= 0) + \
  66 + int(stdin_port <= 0) + int(hb_port <= 0)
209 67 for i in xrange(ports_needed):
210 68 sock = socket.socket()
211 69 sock.bind(('', 0))
@@ -214,28 +72,31 @@ def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
214 72 port = sock.getsockname()[1]
215 73 sock.close()
216 74 ports[i] = port
217   - if xrep_port <= 0:
218   - xrep_port = ports.pop(0)
219   - if pub_port <= 0:
220   - pub_port = ports.pop(0)
221   - if req_port <= 0:
222   - req_port = ports.pop(0)
  75 + if shell_port <= 0:
  76 + shell_port = ports.pop(0)
  77 + if iopub_port <= 0:
  78 + iopub_port = ports.pop(0)
  79 + if stdin_port <= 0:
  80 + stdin_port = ports.pop(0)
223 81 if hb_port <= 0:
224 82 hb_port = ports.pop(0)
225 83
226 84 # Build the kernel launch command.
227 85 if executable is None:
228 86 executable = sys.executable
229   - arguments = [ executable, '-c', code, '--xrep', str(xrep_port),
230   - '--pub', str(pub_port), '--req', str(req_port),
231   - '--hb', str(hb_port) ]
  87 + arguments = [ executable, '-c', code, 'shell=%i'%shell_port,
  88 + 'iopub=%i'%iopub_port, 'stdin=%i'%stdin_port,
  89 + 'hb=%i'%hb_port
  90 + ]
  91 + if ip is not None:
  92 + arguments.append('ip=%s'%ip)
232 93 arguments.extend(extra_arguments)
233 94
234 95 # Spawn a kernel.
235 96 if sys.platform == 'win32':
236 97 # Create a Win32 event for interrupting the kernel.
237 98 interrupt_event = ParentPollerWindows.create_interrupt_event()
238   - arguments += [ '--interrupt', str(int(interrupt_event)) ]
  99 + arguments += [ 'interrupt=%i'%interrupt_event ]
239 100
240 101 # If this process in running on pythonw, stdin, stdout, and stderr are
241 102 # invalid. Popen will fail unless they are suitably redirected. We don't
@@ -273,7 +134,7 @@ def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
273 134 handle = DuplicateHandle(pid, pid, pid, 0,
274 135 True, # Inheritable by new processes.
275 136 DUPLICATE_SAME_ACCESS)
276   - proc = Popen(arguments + ['--parent', str(int(handle))],
  137 + proc = Popen(arguments + ['parent=%i'%int(handle)],
277 138 stdin=_stdin, stdout=_stdout, stderr=_stderr)
278 139
279 140 # Attach the interrupt event to the Popen objet so it can be used later.
@@ -293,7 +154,7 @@ def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
293 154 proc = Popen(arguments, preexec_fn=lambda: os.setsid(),
294 155 stdin=stdin, stdout=stdout, stderr=stderr)
295 156 else:
296   - proc = Popen(arguments + ['--parent'],
  157 + proc = Popen(arguments + ['parent=1'],
297 158 stdin=stdin, stdout=stdout, stderr=stderr)
298 159
299   - return proc, xrep_port, pub_port, req_port, hb_port
  160 + return proc, shell_port, iopub_port, stdin_port, hb_port
379 IPython/zmq/ipkernel.py
@@ -27,37 +27,21 @@
27 27
28 28 # Local imports.
29 29 from IPython.config.configurable import Configurable
  30 +from IPython.config.application import boolean_flag
  31 +from IPython.core.newapplication import ProfileDir
30 32 from IPython.utils import io
31 33 from IPython.utils.jsonutil import json_clean
32 34 from IPython.lib import pylabtools
33   -from IPython.utils.traitlets import Instance, Float
34   -from entry_point import (base_launch_kernel, make_argument_parser, make_kernel,
35   - start_kernel)
  35 +from IPython.utils.traitlets import (
  36 + List, Instance, Float, Dict, Bool, Int, Unicode, CaselessStrEnum
  37 +)
  38 +from entry_point import base_launch_kernel
  39 +from kernelapp import KernelApp, kernel_flags, kernel_aliases
36 40 from iostream import OutStream
37 41 from session import Session, Message
38 42 from zmqshell import ZMQInteractiveShell
39 43
40   -#-----------------------------------------------------------------------------
41   -# Globals
42   -#-----------------------------------------------------------------------------
43   -
44   -# Module-level logger
45   -logger = logging.getLogger(__name__)
46 44
47   -# FIXME: this needs to be done more cleanly later, once we have proper
48   -# configuration support. This is a library, so it shouldn't set a stream
49   -# handler, see:
50   -# http://docs.python.org/library/logging.html#configuring-logging-for-a-library
51   -# But this lets us at least do developer debugging for now by manually turning
52   -# it on/off. And once we have full config support, the client entry points
53   -# will select their logging handlers, as well as passing to this library the
54   -# logging level.
55   -
56   -if 0: # dbg - set to 1 to actually see the messages.
57   - logger.addHandler(logging.StreamHandler())
58   - logger.setLevel(logging.DEBUG)
59   -
60   -# /FIXME
61 45
62 46 #-----------------------------------------------------------------------------
63 47 # Main kernel class
@@ -71,9 +55,10 @@ class Kernel(Configurable):
71 55
72 56 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
73 57 session = Instance(Session)
74   - reply_socket = Instance('zmq.Socket')
75   - pub_socket = Instance('zmq.Socket')
76   - req_socket = Instance('zmq.Socket')
  58 + shell_socket = Instance('zmq.Socket')
  59 + iopub_socket = Instance('zmq.Socket')
  60 + stdin_socket = Instance('zmq.Socket')
  61 + log = Instance(logging.Logger)
77 62
78 63 # Private interface
79 64
@@ -100,7 +85,8 @@ class Kernel(Configurable):
100 85
101 86 # This is a dict of port number that the kernel is listening on. It is set
102 87 # by record_ports and used by connect_request.
103   - _recorded_ports = None
  88 + _recorded_ports = Dict()
  89 +
104 90
105 91
106 92 def __init__(self, **kwargs):
@@ -111,11 +97,11 @@ def __init__(self, **kwargs):
111 97 atexit.register(self._at_shutdown)
112 98
113 99 # Initialize the InteractiveShell subclass
114   - self.shell = ZMQInteractiveShell.instance()
  100 + self.shell = ZMQInteractiveShell.instance(config=self.config)
115 101 self.shell.displayhook.session = self.session
116   - self.shell.displayhook.pub_socket = self.pub_socket
  102 + self.shell.displayhook.pub_socket = self.iopub_socket
117 103 self.shell.display_pub.session = self.session
118   - self.shell.display_pub.pub_socket = self.pub_socket
  104 + self.shell.display_pub.pub_socket = self.iopub_socket
119 105
120 106 # TMP - hack while developing
121 107 self.shell._reply_content = None
@@ -131,7 +117,7 @@ def __init__(self, **kwargs):
131 117 def do_one_iteration(self):
132 118 """Do one iteration of the kernel's evaluation loop.
133 119 """
134   - ident,msg = self.session.recv(self.reply_socket, zmq.NOBLOCK)
  120 + ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
135 121 if msg is None:
136 122 return
137 123
@@ -143,21 +129,20 @@ def do_one_iteration(self):
143 129 # Print some info about this message and leave a '--->' marker, so it's
144 130 # easier to trace visually the message chain when debugging. Each
145 131 # handler prints its message at the end.
146   - # Eventually we'll move these from stdout to a logger.
147   - logger.debug('\n*** MESSAGE TYPE:'+str(msg['msg_type'])+'***')
148   - logger.debug(' Content: '+str(msg['content'])+'\n --->\n ')
  132 + self.log.debug('\n*** MESSAGE TYPE:'+str(msg['msg_type'])+'***')
  133 + self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
149 134
150 135 # Find and call actual handler for message
151 136 handler = self.handlers.get(msg['msg_type'], None)
152 137 if handler is None:
153   - logger.error("UNKNOWN MESSAGE TYPE:" +str(msg))
  138 + self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
154 139 else:
155 140 handler(ident, msg)
156 141
157 142 # Check whether we should exit, in case the incoming message set the
158 143 # exit flag on
159 144 if self.shell.exit_now:
160   - logger.debug('\nExiting IPython kernel...')
  145 + self.log.debug('\nExiting IPython kernel...')
161 146 # We do a normal, clean exit, which allows any actions registered
162 147 # via atexit (such as history saving) to take place.
163 148 sys.exit(0)
@@ -166,22 +151,19 @@ def do_one_iteration(self):
166 151 def start(self):
167 152 """ Start the kernel main loop.
168 153 """
  154 + self.poller = zmq.Poller()
  155 + self.poller.register(self.shell_socket, zmq.POLLIN)
169 156 while True:
170   - time.sleep(self._poll_interval)
  157 + self.poller.poll(self._poll_interval)
171 158 self.do_one_iteration()
172 159
173   - def record_ports(self, xrep_port, pub_port, req_port, hb_port):
  160 + def record_ports(self, ports):
174 161 """Record the ports that this kernel is using.
175 162
176 163 The creator of the Kernel instance must call this methods if they
177 164 want the :meth:`connect_request` method to return the port numbers.
178 165 """
179   - self._recorded_ports = {
180   - 'xrep_port' : xrep_port,
181   - 'pub_port' : pub_port,
182   - 'req_port' : req_port,
183   - 'hb_port' : hb_port
184   - }
  166 + self._recorded_ports = ports
185 167
186 168 #---------------------------------------------------------------------------
187 169 # Kernel request handlers
@@ -190,11 +172,11 @@ def record_ports(self, xrep_port, pub_port, req_port, hb_port):
190 172 def _publish_pyin(self, code, parent):
191 173 """Publish the code request on the pyin stream."""
192 174
193   - pyin_msg = self.session.send(self.pub_socket, u'pyin',{u'code':code}, parent=parent)
  175 + pyin_msg = self.session.send(self.iopub_socket, u'pyin',{u'code':code}, parent=parent)
194 176
195 177 def execute_request(self, ident, parent):
196 178
197   - status_msg = self.session.send(self.pub_socket,
  179 + status_msg = self.session.send(self.iopub_socket,
198 180 u'status',
199 181 {u'execution_state':u'busy'},
200 182 parent=parent
@@ -205,8 +187,8 @@ def execute_request(self, ident, parent):
205 187 code = content[u'code']
206 188 silent = content[u'silent']
207 189 except:
208   - logger.error("Got bad msg: ")
209   - logger.error(str(Message(parent)))
  190 + self.log.error("Got bad msg: ")
  191 + self.log.error(str(Message(parent)))
210 192 return
211 193
212 194 shell = self.shell # we'll need this a lot here
@@ -294,14 +276,14 @@ def execute_request(self, ident, parent):
294 276 time.sleep(self._execute_sleep)
295 277
296 278 # Send the reply.
297   - reply_msg = self.session.send(self.reply_socket, u'execute_reply',
  279 + reply_msg = self.session.send(self.shell_socket, u'execute_reply',
298 280 reply_content, parent, ident=ident)
299   - logger.debug(str(reply_msg))
  281 + self.log.debug(str(reply_msg))
300 282
301 283 if reply_msg['content']['status'] == u'error':
302 284 self._abort_queue()
303 285
304   - status_msg = self.session.send(self.pub_socket,
  286 + status_msg = self.session.send(self.iopub_socket,
305 287 u'status',
306 288 {u'execution_state':u'idle'},
307 289 parent=parent
@@ -312,17 +294,17 @@ def complete_request(self, ident, parent):
312 294 matches = {'matches' : matches,
313 295 'matched_text' : txt,
314 296 'status' : 'ok'}
315   - completion_msg = self.session.send(self.reply_socket, 'complete_reply',
  297 + completion_msg = self.session.send(self.shell_socket, 'complete_reply',
316 298 matches, parent, ident)
317   - logger.debug(str(completion_msg))
  299 + self.log.debug(str(completion_msg))
318 300
319 301 def object_info_request(self, ident, parent):
320 302 object_info = self.shell.object_inspect(parent['content']['oname'])
321 303 # Before we send this object over, we scrub it for JSON usage
322 304 oinfo = json_clean(object_info)
323   - msg = self.session.send(self.reply_socket, 'object_info_reply',
  305 + msg = self.session.send(self.shell_socket, 'object_info_reply',
324 306 oinfo, parent, ident)
325   - logger.debug(msg)
  307 + self.log.debug(msg)
326 308
327 309 def history_request(self, ident, parent):
328 310 # We need to pull these out, as passing **kwargs doesn't work with
@@ -349,18 +331,18 @@ def history_request(self, ident, parent):
349 331 else:
350 332 hist = []
351 333 content = {'history' : list(hist)}
352   - msg = self.session.send(self.reply_socket, 'history_reply',
  334 + msg = self.session.send(self.shell_socket, 'history_reply',
353 335 content, parent, ident)
354   - logger.debug(str(msg))
  336 + self.log.debug(str(msg))
355 337
356 338 def connect_request(self, ident, parent):
357 339 if self._recorded_ports is not None:
358 340 content = self._recorded_ports.copy()
359 341 else:
360 342 content = {}
361   - msg = self.session.send(self.reply_socket, 'connect_reply',
  343 + msg = self.session.send(self.shell_socket, 'connect_reply',
362 344 content, parent, ident)
363   - logger.debug(msg)
  345 + self.log.debug(msg)
364 346
365 347 def shutdown_request(self, ident, parent):
366 348 self.shell.exit_now = True
@@ -373,19 +355,19 @@ def shutdown_request(self, ident, parent):
373 355
374 356 def _abort_queue(self):
375 357 while True:
376   - ident,msg = self.session.recv(self.reply_socket, zmq.NOBLOCK)
  358 + ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
377 359 if msg is None:
378 360 break
379 361 else:
380 362 assert ident is not None, \
381 363 "Unexpected missing message part."
382 364
383   - logger.debug("Aborting:\n"+str(Message(msg)))
  365 + self.log.debug("Aborting:\n"+str(Message(msg)))
384 366 msg_type = msg['msg_type']
385 367 reply_type = msg_type.split('_')[0] + '_reply'
386   - reply_msg = self.session.send(self.reply_socket, reply_type,
  368 + reply_msg = self.session.send(self.shell_socket, reply_type,
387 369 {'status' : 'aborted'}, msg, ident=ident)
388   - logger.debug(reply_msg)
  370 + self.log.debug(reply_msg)
389 371 # We need to wait a bit for requests to come in. This can probably
390 372 # be set shorter for true asynchronous clients.
391 373 time.sleep(0.1)
@@ -397,15 +379,15 @@ def _raw_input(self, prompt, ident, parent):
397 379
398 380 # Send the input request.
399 381 content = dict(prompt=prompt)
400   - msg = self.session.send(self.req_socket, u'input_request', content, parent)
  382 + msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
401 383
402 384 # Await a response.
403   - ident, reply = self.session.recv(self.req_socket, 0)
  385 + ident, reply = self.session.recv(self.stdin_socket, 0)
404 386 try:
405 387 value = reply['content']['value']
406 388 except:
407   - logger.error("Got bad raw_input reply: ")
408   - logger.error(str(Message(parent)))
  389 + self.log.error("Got bad raw_input reply: ")
  390 + self.log.error(str(Message(parent)))
409 391 value = ''
410 392 return value
411 393
@@ -457,9 +439,9 @@ def _at_shutdown(self):
457 439 """
458 440 # io.rprint("Kernel at_shutdown") # dbg
459 441 if self._shutdown_message is not None:
460   - self.session.send(self.reply_socket, self._shutdown_message)
461   - self.session.send(self.pub_socket, self._shutdown_message)
462   - logger.debug(str(self._shutdown_message))
  442 + self.session.send(self.shell_socket, self._shutdown_message)
  443 + self.session.send(self.iopub_socket, self._shutdown_message)
  444 + self.log.debug(str(self._shutdown_message))
463 445 # A very short sleep to give zmq time to flush its message buffers
464 446 # before Python truly shuts down.
465 447 time.sleep(0.01)
@@ -565,120 +547,191 @@ def start(self):
565 547
566 548
567 549 #-----------------------------------------------------------------------------
568   -# Kernel main and launch functions
  550 +# Aliases and Flags for the IPKernelApp
569 551 #-----------------------------------------------------------------------------
570 552
571   -def launch_kernel(ip=None, xrep_port=0, pub_port=0, req_port=0, hb_port=0,
572   - stdin=None, stdout=None, stderr=None,
573   - executable=None, independent=False, pylab=False, colors=None):
574   - """Launches a localhost kernel, binding to the specified ports.
  553 +flags = dict(kernel_flags)
  554 +
  555 +addflag = lambda *args: flags.update(boolean_flag(*args))
  556 +addflag('automagic', 'InteractiveShell.automagic',
  557 + """Turn on the auto calling of magic commands. Type %%magic at the
  558 + IPython prompt for more information.""",
  559 + 'Turn off the auto calling of magic commands.'
  560 +)
  561 +addflag('banner', 'InteractiveShell.display_banner',
  562 + "Display a banner upon starting IPython.",
  563 + "Don't display a banner upon starting IPython."
  564 +)
  565 +addflag('pdb', 'InteractiveShell.pdb',
  566 + "Enable auto calling the pdb debugger after every exception.",
  567 + "Disable auto calling the pdb debugger after every exception."
  568 +)
  569 +addflag('pprint', 'PlainTextFormatter.pprint',
  570 + "Enable auto pretty printing of results.",
  571 + "Disable auto auto pretty printing of results."
  572 +)
  573 +addflag('color-info', 'InteractiveShell.color_info',
  574 + """IPython can display information about objects via a set of func-
  575 + tions, and optionally can use colors for this, syntax highlighting
  576 + source code and various other elements. However, because this
  577 + information is passed through a pager (like 'less') and many pagers get
  578 + confused with color codes, this option is off by default. You can test
  579 + it and turn it on permanently in your ipython_config.py file if it
  580 + works for you. Test it and turn it on permanently if it works with
  581 + your system. The magic function %%color_info allows you to toggle this
  582 + inter- actively for testing.""",
  583 + "Disable using colors for info related things."
  584 +)
  585 +addflag('deep-reload', 'InteractiveShell.deep_reload',
  586 + """Enable deep (recursive) reloading by default. IPython can use the
  587 + deep_reload module which reloads changes in modules recursively (it
  588 + replaces the reload() function, so you don't need to change anything to
  589 + use it). deep_reload() forces a full reload of modules whose code may
  590 + have changed, which the default reload() function does not. When
  591 + deep_reload is off, IPython will use the normal reload(), but
  592 + deep_reload will still be available as dreload(). This fea- ture is off
  593 + by default [which means that you have both normal reload() and
  594 + dreload()].""",
  595 + "Disable deep (recursive) reloading by default."
  596 +)
  597 +addflag('readline', 'InteractiveShell.readline_use',
  598 + "Enable readline for command line usage.",
  599 + "Disable readline for command line usage."
  600 +)
  601 +
  602 +flags['pylab'] = (
  603 + {'IPKernelApp' : {'pylab' : 'auto'}},
  604 + """Pre-load matplotlib and numpy for interactive use with
  605 + the default matplotlib backend."""
  606 +)
  607 +
  608 +aliases = dict(kernel_aliases)
  609 +
  610 +# it's possible we don't want short aliases for *all* of these:
  611 +aliases.update(dict(
  612 + autocall='InteractiveShell.autocall',
  613 + cache_size='InteractiveShell.cache_size',
  614 + colors='InteractiveShell.colors',
  615 + logfile='InteractiveShell.logfile',
  616 + log_append='InteractiveShell.logappend',
  617 + pi1='InteractiveShell.prompt_in1',
  618 + pi2='InteractiveShell.prompt_in2',
  619 + po='InteractiveShell.prompt_out',
  620 + si='InteractiveShell.separate_in',
  621 + so='InteractiveShell.separate_out',
  622 + so2='InteractiveShell.separate_out2',
  623 + xmode='InteractiveShell.xmode',
  624 + c='IPKernelApp.code_to_run',
  625 + ext='IPKernelApp.extra_extension',
  626 + pylab='IPKernelApp.pylab',
  627 +))
575 628
576   - Parameters
577   - ----------
578   - ip : str, optional
579   - The ip address the kernel will bind to.
580   -
581   - xrep_port : int, optional
582   - The port to use for XREP channel.
  629 +#-----------------------------------------------------------------------------
  630 +# The IPKernelApp class
  631 +#-----------------------------------------------------------------------------
583 632
584   - pub_port : int, optional
585   - The port to use for the SUB channel.
  633 +class IPKernelApp(KernelApp):
  634 + name = 'ipkernel'
  635 +
  636 + aliases = Dict(aliases)
  637 + flags = Dict(flags)
  638 + classes = [Kernel, ZMQInteractiveShell, ProfileDir]
  639 + # configurables
  640 + pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
  641 + config=True,
  642 + help="""Pre-load matplotlib and numpy for interactive use,
  643 + selecting a particular matplotlib backend and loop integration.
  644 + """
  645 + )
  646 + extensions = List(Unicode, config=True,
  647 + help="A list of dotted module names of IPython extensions to load."
  648 + )
  649 + extra_extension = Unicode('', config=True,
  650 + help="dotted module name of an IPython extension to load."
  651 + )
  652 + def _extra_extension_changed(self, name, old, new):
  653 + if new:
  654 + # add to self.extensions
  655 + self.extensions.append(new)
  656 +
  657 + exec_files = List(Unicode, config=True,
  658 + help="""List of files to run at IPython startup."""
  659 + )
  660 + file_to_run = Unicode('', config=True,
  661 + help="""A file to be run""")
  662 + def _file_to_run_changed(self, name, old, new):
  663 + self.exec_files.append(new)
  664 +
  665 + exec_lines = List(Unicode, config=True,
  666 + help="""lines of code to run at IPython startup."""
  667 + )
  668 + code_to_run = Unicode('', config=True,
  669 + help="Execute the given command string."
  670 + )
  671 + def _code_to_run_changed(self, name, old, new):
  672 + self.exec_lines.append(new)
  673 +
  674 + def init_kernel(self):
  675 + kernel_factory = Kernel
  676 +
  677 + kernel_map = {
  678 + 'qt' : QtKernel,
  679 + 'qt4': QtKernel,
  680 + 'inline': Kernel,
  681 + 'osx': TkKernel,
  682 + 'wx' : WxKernel,
  683 + 'tk' : TkKernel,
  684 + 'gtk': GTKKernel,
  685 + }
586 686
587   - req_port : int, optional
588   - The port to use for the REQ (raw input) channel.
  687 + if self.pylab:
  688 + key = None if self.pylab == 'auto' else self.pylab
  689 + gui, backend = pylabtools.find_gui_and_backend(key)
  690 + kernel_factory = kernel_map.get(gui)
  691 + if kernel_factory is None:
  692 + raise ValueError('GUI is not supported: %r' % gui)
  693 + pylabtools.activate_matplotlib(backend)
  694 +
  695 + kernel = kernel_factory(config=self.config, session=self.session,
  696 + shell_socket=self.shell_socket,
  697 + iopub_socket=self.iopub_socket,
  698 + stdin_socket=self.stdin_socket,
  699 + log=self.log
  700 + )
  701 + self.kernel = kernel
  702 + kernel.record_ports(self.ports)
589 703
590   - hb_port : int, optional
591   - The port to use for the hearbeat REP channel.
  704 + if self.pylab:
  705 + pylabtools.import_pylab(kernel.shell.user_ns, backend,
  706 + shell=kernel.shell)
592 707
593   - stdin, stdout, stderr : optional (default None)
594   - Standards streams, as defined in subprocess.Popen.
595 708
596   - executable : str, optional (default sys.executable)
597   - The Python executable to use for the kernel process.
598 709
599   - independent : bool, optional (default False)
600   - If set, the kernel process is guaranteed to survive if this process
601   - dies. If not set, an effort is made to ensure that the kernel is killed
602   - when this process dies. Note that in this case it is still good practice
603   - to kill kernels manually before exiting.
  710 +#-----------------------------------------------------------------------------
  711 +# Kernel main and launch functions
  712 +#-----------------------------------------------------------------------------
604 713
605   - pylab : bool or string, optional (default False)
606   - If not False, the kernel will be launched with pylab enabled. If a
607   - string is passed, matplotlib will use the specified backend. Otherwise,
608   - matplotlib's default backend will be used.
  714 +def launch_kernel(*args, **kwargs):
  715 + """Launches a localhost IPython kernel, binding to the specified ports.
609 716
610   - colors : None or string, optional (default None)
611   - If not None, specify the color scheme. One of (NoColor, LightBG, Linux)
  717 + This function simply calls entry_point.base_launch_kernel with the right first
  718 + command to start an ipkernel. See base_launch_kernel for arguments.
612 719
613 720 Returns
614 721 -------
615 722 A tuple of form:
616   - (kernel_process, xrep_port, pub_port, req_port)
  723 + (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
617 724 where kernel_process is a Popen object and the ports are integers.
618 725 """
619   - extra_arguments = []
620   - if pylab:
621   - extra_arguments.append('--pylab')
622   - if isinstance(pylab, basestring):
623   - extra_arguments.append(pylab)
624   - if ip is not None:
625   - extra_arguments.append('--ip')
626   - if isinstance(ip, basestring):
627   - extra_arguments.append(ip)
628   - if colors is not None:
629   - extra_arguments.append('--colors')
630   - extra_arguments.append(colors)
631 726 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
632   - xrep_port, pub_port, req_port, hb_port,
633   - stdin, stdout, stderr,
634   - executable, independent, extra_arguments)
  727 + *args, **kwargs)
635 728
636 729
637 730 def main():
638   - """ The IPython kernel main entry point.
639   - """
640   - parser = make_argument_parser()
641   - parser.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
642   - const='auto', help = \
643   -"Pre-load matplotlib and numpy for interactive use. If GUI is not \
644   -given, the GUI backend is matplotlib's, otherwise use one of: \
645   -['tk', 'gtk', 'qt', 'wx', 'osx', 'inline'].")
646   - parser.add_argument('--colors',
647   - type=str, dest='colors',
648   - help="Set the color scheme (NoColor, Linux, and LightBG).",
649   - metavar='ZMQInteractiveShell.colors')
650   - namespace = parser.parse_args()
651   -
652   - kernel_class = Kernel
653   -
654   - kernel_classes = {
655   - 'qt' : QtKernel,
656   - 'qt4': QtKernel,
657   - 'inline': Kernel,
658   - 'osx': TkKernel,
659   - 'wx' : WxKernel,
660   - 'tk' : TkKernel,
661   - 'gtk': GTKKernel,
662   - }
663   - if namespace.pylab:
664   - if namespace.pylab == 'auto':
665   - gui, backend = pylabtools.find_gui_and_backend()
666   - else:
667   - gui, backend = pylabtools.find_gui_and_backend(namespace.pylab)
668   - kernel_class = kernel_classes.get(gui)
669   - if kernel_class is None:
670   - raise ValueError('GUI is not supported: %r' % gui)
671   - pylabtools.activate_matplotlib(backend)
672   - if namespace.colors:
673   - ZMQInteractiveShell.colors=namespace.colors
674   -
675   - kernel = make_kernel(namespace, kernel_class, OutStream)
676   -
677   - if namespace.pylab:
678   - pylabtools.import_pylab(kernel.shell.user_ns, backend,
679   - shell=kernel.shell)
680   -
681   - start_kernel(namespace, kernel)
  731 + """Run a PyKernel as an application"""
  732 + app = IPKernelApp()
  733 + app.initialize()
  734 + app.start()
682 735
683 736
684 737 if __name__ == '__main__':
213 IPython/zmq/kernelapp.py
... ... @@ -0,0 +1,213 @@
  1 +#!/usr/bin/env python
  2 +"""An Application for launching a kernel
  3 +
  4 +Authors
  5 +-------
  6 +* MinRK
  7 +"""
  8 +#-----------------------------------------------------------------------------
  9 +# Copyright (C) 2011 The IPython Development Team
  10 +#
  11 +# Distributed under the terms of the BSD License. The full license is in
  12 +# the file COPYING.txt, distributed as part of this software.
  13 +#-----------------------------------------------------------------------------
  14 +
  15 +#-----------------------------------------------------------------------------
  16 +# Imports
  17 +#-----------------------------------------------------------------------------
  18 +
  19 +# Standard library imports.
  20 +import os
  21 +import sys
  22 +
  23 +# System library imports.
  24 +import zmq
  25 +
  26 +# IPython imports.
  27 +from IPython.core.ultratb import FormattedTB
  28 +from IPython.core.newapplication import (
  29 + BaseIPythonApplication, base_flags, base_aliases
  30 +)
  31 +from IPython.utils import io
  32 +from IPython.utils.localinterfaces import LOCALHOST
  33 +from IPython.utils.traitlets import Any, Instance, Dict, Unicode, Int, Bool
  34 +from IPython.utils.importstring import import_item
  35 +# local imports
  36 +from IPython.zmq.heartbeat import Heartbeat
  37 +from IPython.zmq.parentpoller import ParentPollerUnix, ParentPollerWindows
  38 +from IPython.zmq.session import Session
  39 +
  40 +
  41 +#-----------------------------------------------------------------------------
  42 +# Flags and Aliases
  43 +#-----------------------------------------------------------------------------
  44 +
  45 +kernel_aliases = dict(base_aliases)
  46 +kernel_aliases.update({
  47 + 'ip' : 'KernelApp.ip',
  48 + 'hb' : 'KernelApp.hb_port',
  49 + 'shell' : 'KernelApp.shell_port',
  50 + 'iopub' : 'KernelApp.iopub_port',
  51 + 'stdin' : 'KernelApp.stdin_port',
  52 + 'parent': 'KernelApp.parent',
  53 +})
  54 +if sys.platform.startswith('win'):
  55 + kernel_aliases['interrupt'] = 'KernelApp.interrupt'
  56 +
  57 +kernel_flags = dict(base_flags)
  58 +kernel_flags.update({
  59 + 'no-stdout' : (
  60 + {'KernelApp' : {'no_stdout' : True}},
  61 + "redirect stdout to the null device"),
  62 + 'no-stderr' : (
  63 + {'KernelApp' : {'no_stderr' : True}},
  64 + "redirect stderr to the null device"),
  65 +})
  66 +
  67 +
  68 +#-----------------------------------------------------------------------------
  69 +# Application class for starting a Kernel
  70 +#-----------------------------------------------------------------------------
  71 +
  72 +class KernelApp(BaseIPythonApplication):
  73 + name='pykernel'
  74 + aliases = Dict(kernel_aliases)
  75 + flags = Dict(kernel_flags)
  76 +
  77 + # the kernel class, as an importstring
  78 + kernel_class = Unicode('IPython.zmq.pykernel.Kernel')
  79 + kernel = Any()
  80 + poller = Any() # don't restrict this even though current pollers are all Threads
  81 + heartbeat = Instance(Heartbeat)
  82 + session = Instance('IPython.zmq.session.Session')
  83 + ports = Dict()
  84 +
  85 + # connection info:
  86 + ip = Unicode(LOCALHOST, config=True,
  87 + help="Set the IP or interface on which the kernel will listen.")
  88 + hb_port = Int(0, config=True, help="set the heartbeat port [default: random]")
  89 + shell_port = Int(0, config=True, help="set the shell (XREP) port [default: random]")
  90 + iopub_port = Int(0, config=True, help="set the iopub (PUB) port [default: random]")
  91 + stdin_port = Int(0, config=True, help="set the stdin (XREQ) port [default: random]")
  92 +
  93 + # streams, etc.
  94 + no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
  95 + no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
  96 + outstream_class = Unicode('IPython.zmq.iostream.OutStream', config=True,
  97 + help="The importstring for the OutStream factory")
  98 + displayhook_class = Unicode('IPython.zmq.displayhook.DisplayHook', config=True,
  99 + help="The importstring for the DisplayHook factory")
  100 +
  101 + # polling
  102 + parent = Int(0, config=True,
  103 + help="""kill this process if its parent dies. On Windows, the argument
  104 + specifies the HANDLE of the parent process, otherwise it is simply boolean.
  105 + """)
  106 + interrupt = Int(0, config=True,
  107 + help="""ONLY USED ON WINDOWS
  108 + Interrupt this process when the parent is signalled.
  109 + """)
  110 +
  111 + def init_crash_handler(self):
  112 + # Install minimal exception handling
  113 + sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
  114 + ostream=sys.__stdout__)
  115 +
  116 + def init_poller(self):
  117 + if sys.platform == 'win32':
  118 + if self.interrupt or self.parent:
  119 + self.poller = ParentPollerWindows(self.interrupt, self.parent)
  120 + elif self.parent:
  121 + self.poller = ParentPollerUnix()
  122 +
  123 + def _bind_socket(self, s, port):
  124 + iface = 'tcp://%s' % self.ip
  125 + if port <= 0:
  126 + port = s.bind_to_random_port(iface)
  127 + else:
  128 + s.bind(iface + ':%i'%port)
  129 + return port
  130 +
  131 + def init_sockets(self):
  132 + # Create a context, a session, and the kernel sockets.
  133 + io.raw_print("Starting the kernel at pid:", os.getpid())
  134 + context = zmq.Context.instance()
  135 + # Uncomment this to try closing the context.
  136 + # atexit.register(context.term)
  137 +
  138 + self.shell_socket = context.socket(zmq.XREP)
  139 + self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
  140 + self.log.debug("shell XREP Channel on port: %i"%self.shell_port)
  141 +
  142 + self.iopub_socket = context.socket(zmq.PUB)
  143 + self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
  144 + self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
  145 +
  146 + self.stdin_socket = context.socket(zmq.XREQ)
  147 + self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
  148 + self.log.debug("stdin XREQ Channel on port: %i"%self.stdin_port)
  149 +
  150 + self.heartbeat = Heartbeat(context, (self.ip, self.hb_port))
  151 + self.hb_port = self.heartbeat.port
  152 + self.log.debug("Heartbeat REP Channel on port: %i"%self.hb_port)
  153 +
  154 + # Helper to make it easier to connect to an existing kernel, until we have
  155 + # single-port connection negotiation fully implemented.
  156 + self.log.info("To connect another client to this kernel, use:")
  157 + self.log.info("--external shell={0} iopub={1} stdin={2} hb={3}".format(
  158 + self.shell_port, self.iopub_port, self.stdin_port, self.hb_port))
  159 +
  160 +
  161 + self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
  162 + stdin=self.stdin_port, hb=self.hb_port)
  163 +
  164 + def init_session(self):
  165 + """create our session object"""
  166 + self.session = Session(username=u'kernel')
  167 +
  168 + def init_io(self):
  169 + """redirects stdout/stderr, and installs a display hook"""
  170 + # Re-direct stdout/stderr, if necessary.
  171 + if self.no_stdout or self.no_stderr:
  172 + blackhole = file(os.devnull, 'w')
  173 + if self.no_stdout:
  174 + sys.stdout = sys.__stdout__ = blackhole
  175 + if self.no_stderr:
  176 + sys.stderr = sys.__stderr__ = blackhole
  177 +
  178 + # Redirect input streams and set a display hook.
  179 +
  180 + if self.outstream_class:
  181 + outstream_factory = import_item(str(self.outstream_class))
  182 + sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
  183 + sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
  184 + if self.displayhook_class:
  185 + displayhook_factory = import_item(str(self.displayhook_class))
  186 + sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
  187 +
  188 + def init_kernel(self):
  189 + """Create the Kernel object itself"""
  190 + kernel_factory = import_item(str(self.kernel_class))
  191 + self.kernel = kernel_factory(config=self.config, session=self.session,
  192 + shell_socket=self.shell_socket,
  193 + iopub_socket=self.iopub_socket,
  194 + stdin_socket=self.stdin_socket,
  195 + )
  196 + self.kernel.record_ports(self.ports)
  197 +
  198 + def initialize(self, argv=None):
  199 + super(KernelApp, self).initialize(argv)
  200 + self.init_session()
  201 + self.init_poller()
  202 + self.init_sockets()
  203 + self.init_io()
  204 + self.init_kernel()
  205 +
  206 + def start(self):
  207 + self.heartbeat.start()
  208 + if self.poller is not None:
  209 + self.poller.start()
  210 + try:
  211 + self.kernel.start()
  212 + except KeyboardInterrupt:
  213 + pass
4 IPython/zmq/kernelmanager.py
@@ -759,8 +759,8 @@ def start_kernel(self, **kw):
759 759 else:
760 760 from pykernel import launch_kernel
761 761 self.kernel, xrep, pub, req, _hb = launch_kernel(
762   - xrep_port=xreq[1], pub_port=sub[1],
763   - req_port=rep[1], hb_port=hb[1], **kw)
  762 + shell_port=xreq[1], iopub_port=sub[1],
  763 + stdin_port=rep[1], hb_port=hb[1], **kw)
764 764 self.xreq_address = (xreq[0], xrep)
765 765 self.sub_address = (sub[0], pub)
766 766 self.rep_address = (rep[0], req)
100 IPython/zmq/pykernel.py
@@ -25,10 +25,11 @@
25 25 import zmq
26 26
27 27 # Local imports.
28   -from IPython.utils.traitlets import HasTraits, Instance
  28 +from IPython.utils.traitlets import HasTraits, Instance, Dict
29 29 from completer import KernelCompleter
30   -from entry_point import base_launch_kernel, make_default_main
  30 +from entry_point import base_launch_kernel
31 31 from session import Session, Message
  32 +from kernelapp import KernelApp
32 33
33 34 #-----------------------------------------------------------------------------
34 35 # Main kernel class
@@ -40,16 +41,16 @@ class Kernel(HasTraits):
40 41
41 42 # This is a dict of port number that the kernel is listening on. It is set
42 43 # by record_ports and used by connect_request.
43   - _recorded_ports = None
  44 + _recorded_ports = Dict()
44 45
45 46 #---------------------------------------------------------------------------
46 47 # Kernel interface
47 48 #---------------------------------------------------------------------------
48 49
49 50 session = Instance(Session)
50   - reply_socket = Instance('zmq.Socket')
51   - pub_socket = Instance('zmq.Socket')
52   - req_socket = Instance('zmq.Socket')
  51 + shell_socket = Instance('zmq.Socket')
  52 + iopub_socket = Instance('zmq.Socket')
  53 + stdin_socket = Instance('zmq.Socket')
53 54
54 55 def __init__(self, **kwargs):
55 56 super(Kernel, self).__init__(**kwargs)
@@ -69,7 +70,7 @@ def start(self):
69 70 """ Start the kernel main loop.
70 71 """
71 72 while True:
72   - ident,msg = self.session.recv(self.reply_socket,0)
  73 + ident,msg = self.session.recv(self.shell_socket,0)
73 74 assert ident is not None, "Missing message part."
74 75 omsg = Message(msg)
75 76 print>>sys.__stdout__
@@ -80,18 +81,13 @@ def start(self):
80 81 else:
81 82 handler(ident, omsg)
82 83
83   - def record_ports(self, xrep_port, pub_port, req_port, hb_port):
  84 + def record_ports(self, ports):
84 85 """Record the ports that this kernel is using.
85 86
86 87 The creator of the Kernel instance must call this methods if they
87 88 want the :meth:`connect_request` method to return the port numbers.
88 89 """
89   - self._recorded_ports = {
90   - 'xrep_port' : xrep_port,
91   - 'pub_port' : pub_port,
92   - 'req_port' : req_port,
93   - 'hb_port' : hb_port
94   - }
  90 + self._recorded_ports = ports
95 91
96 92 #---------------------------------------------------------------------------
97 93 # Kernel request handlers
@@ -104,7 +100,7 @@ def execute_request(self, ident, parent):
104 100 print>>sys.__stderr__, "Got bad msg: "
105 101 print>>sys.__stderr__, Message(parent)
106 102 return
107   - pyin_msg = self.session.send(self.pub_socket, u'pyin',{u'code':code}, parent=parent)
  103 + pyin_msg = self.session.send(self.iopub_socket, u'pyin',{u'code':code}, parent=parent)
108 104
109 105 try:
110 106 comp_code = self.compiler(code, '<zmq-kernel>')
@@ -129,7 +125,7 @@ def execute_request(self, ident, parent):
129 125 u'ename' : unicode(etype.__name__),
130 126 u'evalue' : unicode(evalue)
131 127 }
132   - exc_msg = self.session.send(self.pub_socket, u'pyerr', exc_content, parent)
  128 + exc_msg = self.session.send(self.iopub_socket, u'pyerr', exc_content, parent)
133 129 reply_content = exc_content
134 130 else:
135 131 reply_content = { 'status' : 'ok', 'payload' : {} }
@@ -139,7 +135,7 @@ def execute_request(self, ident, parent):
139 135 sys.stdout.flush()
140 136
141 137 # Send the reply.
142   - reply_msg = self.session.send(self.reply_socket, u'execute_reply', reply_content, parent, ident=ident)
  138 + reply_msg = self.session.send(self.shell_socket, u'execute_reply', reply_content, parent, ident=ident)
143 139 print>>sys.__stdout__, Message(reply_msg)