##// END OF EJS Templates
use ROUTER/DEALER sockets for stdin...
MinRK -
Show More
@@ -6,6 +6,7 b' Authors:'
6
6
7 * Brian Granger
7 * Brian Granger
8 * Fernando Perez
8 * Fernando Perez
9 * Min Ragan-Kelley
9
10
10 Notes
11 Notes
11 -----
12 -----
@@ -49,3 +50,10 b' class UsageError(IPythonCoreError):'
49 Something that probably won't warrant a full traceback, but should
50 Something that probably won't warrant a full traceback, but should
50 nevertheless interrupt a macro / batch file.
51 nevertheless interrupt a macro / batch file.
51 """
52 """
53
54 class StdinNotImplementedError(IPythonCoreError, NotImplementedError):
55 """raw_input was requested in a context where it is not supported
56
57 For use in IPython kernels, where only some frontends may support
58 stdin requests.
59 """
@@ -121,6 +121,7 b' var IPython = (function (IPython) {'
121 silent : false,
121 silent : false,
122 user_variables : [],
122 user_variables : [],
123 user_expressions : {}
123 user_expressions : {}
124 allow_stdin : false,
124 };
125 };
125 var msg = this.get_msg("execute_request", content);
126 var msg = this.get_msg("execute_request", content);
126 this.shell_channel.send(JSON.stringify(msg));
127 this.shell_channel.send(JSON.stringify(msg));
@@ -29,6 +29,7 b' import zmq'
29 from IPython.config.configurable import Configurable
29 from IPython.config.configurable import Configurable
30 from IPython.config.application import boolean_flag
30 from IPython.config.application import boolean_flag
31 from IPython.core.application import ProfileDir
31 from IPython.core.application import ProfileDir
32 from IPython.core.error import StdinNotImplementedError
32 from IPython.core.shellapp import (
33 from IPython.core.shellapp import (
33 InteractiveShellApp, shell_flags, shell_aliases
34 InteractiveShellApp, shell_flags, shell_aliases
34 )
35 )
@@ -219,7 +220,11 b' class Kernel(Configurable):'
219
220
220 # Replace raw_input. Note that is not sufficient to replace
221 # Replace raw_input. Note that is not sufficient to replace
221 # raw_input in the user namespace.
222 # raw_input in the user namespace.
222 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
223 if content.get('allow_stdin', False):
224 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
225 else:
226 raw_input = lambda prompt='' : self._no_raw_input()
227
223 if py3compat.PY3:
228 if py3compat.PY3:
224 __builtin__.input = raw_input
229 __builtin__.input = raw_input
225 else:
230 else:
@@ -406,6 +411,10 b' class Kernel(Configurable):'
406 # be set shorter for true asynchronous clients.
411 # be set shorter for true asynchronous clients.
407 time.sleep(0.1)
412 time.sleep(0.1)
408
413
414 def _no_raw_input(self):
415 """Raise StdinNotImplentedError if active frontend doesn't support stdin."""
416 raise StdinNotImplementedError("raw_input was called, but this frontend does not support stdin.")
417
409 def _raw_input(self, prompt, ident, parent):
418 def _raw_input(self, prompt, ident, parent):
410 # Flush output before making the request.
419 # Flush output before making the request.
411 sys.stderr.flush()
420 sys.stderr.flush()
@@ -413,7 +422,7 b' class Kernel(Configurable):'
413
422
414 # Send the input request.
423 # Send the input request.
415 content = json_clean(dict(prompt=prompt))
424 content = json_clean(dict(prompt=prompt))
416 msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
425 msg = self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident)
417
426
418 # Await a response.
427 # Await a response.
419 while True:
428 while True:
@@ -153,9 +153,9 b' class KernelApp(BaseIPythonApplication):'
153 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
153 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
154 self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
154 self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
155
155
156 self.stdin_socket = context.socket(zmq.XREQ)
156 self.stdin_socket = context.socket(zmq.ROUTER)
157 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
157 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
158 self.log.debug("stdin XREQ Channel on port: %i"%self.stdin_port)
158 self.log.debug("stdin ROUTER Channel on port: %i"%self.stdin_port)
159
159
160 self.heartbeat = Heartbeat(context, (self.ip, self.hb_port))
160 self.heartbeat = Heartbeat(context, (self.ip, self.hb_port))
161 self.hb_port = self.heartbeat.port
161 self.hb_port = self.heartbeat.port
@@ -179,6 +179,8 b' class ShellSocketChannel(ZMQSocketChannel):'
179 """
179 """
180
180
181 command_queue = None
181 command_queue = None
182 # flag for whether execute requests should be allowed to call raw_input:
183 allow_stdin = True
182
184
183 def __init__(self, context, session, address):
185 def __init__(self, context, session, address):
184 super(ShellSocketChannel, self).__init__(context, session, address)
186 super(ShellSocketChannel, self).__init__(context, session, address)
@@ -210,7 +212,7 b' class ShellSocketChannel(ZMQSocketChannel):'
210 raise NotImplementedError('call_handlers must be defined in a subclass.')
212 raise NotImplementedError('call_handlers must be defined in a subclass.')
211
213
212 def execute(self, code, silent=False,
214 def execute(self, code, silent=False,
213 user_variables=None, user_expressions=None):
215 user_variables=None, user_expressions=None, allow_stdin=None):
214 """Execute code in the kernel.
216 """Execute code in the kernel.
215
217
216 Parameters
218 Parameters
@@ -231,6 +233,12 b' class ShellSocketChannel(ZMQSocketChannel):'
231 namespace. They will come back as a dict with these names as keys
233 namespace. They will come back as a dict with these names as keys
232 and their :func:`repr` as values.
234 and their :func:`repr` as values.
233
235
236 allow_stdin : bool, optional
237 Flag for
238 A dict with string keys and to pull from the user's
239 namespace. They will come back as a dict with these names as keys
240 and their :func:`repr` as values.
241
234 Returns
242 Returns
235 -------
243 -------
236 The msg_id of the message sent.
244 The msg_id of the message sent.
@@ -239,7 +247,10 b' class ShellSocketChannel(ZMQSocketChannel):'
239 user_variables = []
247 user_variables = []
240 if user_expressions is None:
248 if user_expressions is None:
241 user_expressions = {}
249 user_expressions = {}
242
250 if allow_stdin is None:
251 allow_stdin = self.allow_stdin
252
253
243 # Don't waste network traffic if inputs are invalid
254 # Don't waste network traffic if inputs are invalid
244 if not isinstance(code, basestring):
255 if not isinstance(code, basestring):
245 raise ValueError('code %r must be a string' % code)
256 raise ValueError('code %r must be a string' % code)
@@ -250,7 +261,9 b' class ShellSocketChannel(ZMQSocketChannel):'
250 # not in Session.
261 # not in Session.
251 content = dict(code=code, silent=silent,
262 content = dict(code=code, silent=silent,
252 user_variables=user_variables,
263 user_variables=user_variables,
253 user_expressions=user_expressions)
264 user_expressions=user_expressions,
265 allow_stdin=allow_stdin,
266 )
254 msg = self.session.msg('execute_request', content)
267 msg = self.session.msg('execute_request', content)
255 self._queue_request(msg)
268 self._queue_request(msg)
256 return msg['header']['msg_id']
269 return msg['header']['msg_id']
@@ -735,6 +748,9 b' class KernelManager(HasTraits):'
735 self.sub_channel.start()
748 self.sub_channel.start()
736 if stdin:
749 if stdin:
737 self.stdin_channel.start()
750 self.stdin_channel.start()
751 self.shell_channel.allow_stdin = True
752 else:
753 self.shell_channel.allow_stdin = False
738 if hb:
754 if hb:
739 self.hb_channel.start()
755 self.hb_channel.start()
740
756
@@ -209,7 +209,7 b' class Kernel(HasTraits):'
209
209
210 # Send the input request.
210 # Send the input request.
211 content = dict(prompt=prompt)
211 content = dict(prompt=prompt)
212 msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
212 msg = self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident)
213
213
214 # Await a response.
214 # Await a response.
215 ident,reply = self.session.recv(self.stdin_socket, 0)
215 ident,reply = self.session.recv(self.stdin_socket, 0)
General Comments 0
You need to be logged in to leave comments. Login now