Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

use ROUTER/DEALER sockets for stdin

stdin requests are now directed to the frontend that made the execution
request that called raw_input.

allow_stdin flag added to execution_request to indicate whether stdin_requests are allowed.

StdInNotImplementedError exception class added to IPython.core.error, and is raised if raw_input is called from execute requests where allow_input is undefined.

closes gh-673
  • Loading branch information...
commit a2ac298eab73f1ac7b8e840173a4998296f3136c 1 parent 0f89bee
@minrk minrk authored
View
8 IPython/core/error.py
@@ -6,6 +6,7 @@
* Brian Granger
* Fernando Perez
+* Min Ragan-Kelley
Notes
-----
@@ -49,3 +50,10 @@ class UsageError(IPythonCoreError):
Something that probably won't warrant a full traceback, but should
nevertheless interrupt a macro / batch file.
"""
+
+class StdinNotImplementedError(IPythonCoreError, NotImplementedError):
+ """raw_input was requested in a context where it is not supported
+
+ For use in IPython kernels, where only some frontends may support
+ stdin requests.
+ """
View
1  IPython/frontend/html/notebook/static/js/kernel.js
@@ -121,6 +121,7 @@ var IPython = (function (IPython) {
silent : false,
user_variables : [],
user_expressions : {}
+ allow_stdin : false,
};
var msg = this.get_msg("execute_request", content);
this.shell_channel.send(JSON.stringify(msg));
View
13 IPython/zmq/ipkernel.py
@@ -29,6 +29,7 @@
from IPython.config.configurable import Configurable
from IPython.config.application import boolean_flag
from IPython.core.application import ProfileDir
+from IPython.core.error import StdinNotImplementedError
from IPython.core.shellapp import (
InteractiveShellApp, shell_flags, shell_aliases
)
@@ -219,7 +220,11 @@ def execute_request(self, ident, parent):
# Replace raw_input. Note that is not sufficient to replace
# raw_input in the user namespace.
- raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
+ if content.get('allow_stdin', False):
+ raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
+ else:
+ raw_input = lambda prompt='' : self._no_raw_input()
+
if py3compat.PY3:
__builtin__.input = raw_input
else:
@@ -406,6 +411,10 @@ def _abort_queue(self):
# be set shorter for true asynchronous clients.
time.sleep(0.1)
+ def _no_raw_input(self):
+ """Raise StdinNotImplentedError if active frontend doesn't support stdin."""
+ raise StdinNotImplementedError("raw_input was called, but this frontend does not support stdin.")
+
def _raw_input(self, prompt, ident, parent):
# Flush output before making the request.
sys.stderr.flush()
@@ -413,7 +422,7 @@ def _raw_input(self, prompt, ident, parent):
# Send the input request.
content = json_clean(dict(prompt=prompt))
- msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
+ msg = self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident)
# Await a response.
while True:
View
4 IPython/zmq/kernelapp.py
@@ -153,9 +153,9 @@ def init_sockets(self):
self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
- self.stdin_socket = context.socket(zmq.XREQ)
+ self.stdin_socket = context.socket(zmq.ROUTER)
self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
- self.log.debug("stdin XREQ Channel on port: %i"%self.stdin_port)
+ self.log.debug("stdin ROUTER Channel on port: %i"%self.stdin_port)
self.heartbeat = Heartbeat(context, (self.ip, self.hb_port))
self.hb_port = self.heartbeat.port
View
22 IPython/zmq/kernelmanager.py
@@ -179,6 +179,8 @@ class ShellSocketChannel(ZMQSocketChannel):
"""
command_queue = None
+ # flag for whether execute requests should be allowed to call raw_input:
+ allow_stdin = True
def __init__(self, context, session, address):
super(ShellSocketChannel, self).__init__(context, session, address)
@@ -210,7 +212,7 @@ def call_handlers(self, msg):
raise NotImplementedError('call_handlers must be defined in a subclass.')
def execute(self, code, silent=False,
- user_variables=None, user_expressions=None):
+ user_variables=None, user_expressions=None, allow_stdin=None):
"""Execute code in the kernel.
Parameters
@@ -231,6 +233,12 @@ def execute(self, code, silent=False,
namespace. They will come back as a dict with these names as keys
and their :func:`repr` as values.
+ allow_stdin : bool, optional
+ Flag for
+ A dict with string keys and to pull from the user's
+ namespace. They will come back as a dict with these names as keys
+ and their :func:`repr` as values.
+
Returns
-------
The msg_id of the message sent.
@@ -239,7 +247,10 @@ def execute(self, code, silent=False,
user_variables = []
if user_expressions is None:
user_expressions = {}
-
+ if allow_stdin is None:
+ allow_stdin = self.allow_stdin
+
+
# Don't waste network traffic if inputs are invalid
if not isinstance(code, basestring):
raise ValueError('code %r must be a string' % code)
@@ -250,7 +261,9 @@ def execute(self, code, silent=False,
# not in Session.
content = dict(code=code, silent=silent,
user_variables=user_variables,
- user_expressions=user_expressions)
+ user_expressions=user_expressions,
+ allow_stdin=allow_stdin,
+ )
msg = self.session.msg('execute_request', content)
self._queue_request(msg)
return msg['header']['msg_id']
@@ -735,6 +748,9 @@ def start_channels(self, shell=True, sub=True, stdin=True, hb=True):
self.sub_channel.start()
if stdin:
self.stdin_channel.start()
+ self.shell_channel.allow_stdin = True
+ else:
+ self.shell_channel.allow_stdin = False
if hb:
self.hb_channel.start()
View
2  IPython/zmq/pykernel.py
@@ -209,7 +209,7 @@ def _raw_input(self, prompt, ident, parent):
# Send the input request.
content = dict(prompt=prompt)
- msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
+ msg = self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident)
# Await a response.
ident,reply = self.session.recv(self.stdin_socket, 0)
Please sign in to comment.
Something went wrong with that request. Please try again.