Repository: ipython/ipython

Issue:
Making stdin optional when creating new kernels
It would be useful for the `ExecutePreprocessor` (and other things that want to automatically run notebooks on the fly) to be able to easily disable `stdin` -- otherwise, if there is something like a call to `input`, it causes the preprocessor to just hang and eventually time out. I think this would just involve adding a new kwarg to this function: https://github.com/ipython/ipython/blob/master/IPython/kernel/manager.py#L417 and then calling `kc.start_channels(stdin=stdin)`, where `stdin` is whatever value that was passed in (True by default).

Questions:
1. Is there some other way to do this that I missed?
2. If not, does this change sound ok? If so, I'll go ahead and make a PR for it and add an option to disable stdin to the `ExecutePreprocessor` as well.



Discussion:
Hum, I think there is already a way to tell kernels that stdin is not implemented. 

stdin -> raw input. , but I guess that what you are encountering.

Yeah, `raw_input` or `input`, depending on the version of python :)

KernelClient has an `allow_stdin` attribute, and the `execute` method has a similarly named parameter. Setting either to False _should_ suffice, though I don't know if we've checked that recently.

Aha, I missed the argument to `execute` somehow. I'll play around with that and see if it works.


Resolving patch:
diff --git a/IPython/nbconvert/preprocessors/execute.py b/IPython/nbconvert/preprocessors/execute.py
--- a/IPython/nbconvert/preprocessors/execute.py
+++ b/IPython/nbconvert/preprocessors/execute.py
@@ -36,6 +36,7 @@ def preprocess(self, nb, resources):
                         extra_arguments=self.extra_arguments,
                         stderr=open(os.devnull, 'w')) as kc:
             self.kc = kc
+            self.kc.allow_stdin = False
             nb, resources = super(ExecutePreprocessor, self).preprocess(nb, resources)
         return nb, resources
 


Test patch:
diff --git a/IPython/nbconvert/preprocessors/tests/files/Disable Stdin.ipynb b/IPython/nbconvert/preprocessors/tests/files/Disable Stdin.ipynb
new file mode 100644
--- /dev/null
+++ b/IPython/nbconvert/preprocessors/tests/files/Disable Stdin.ipynb	
@@ -0,0 +1,23 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [],
+   "source": [
+    "try:\n",
+    "    input = raw_input\n",
+    "except:\n",
+    "    pass\n",
+    "\n",
+    "name = input(\"name: \")"
+   ]
+  }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
diff --git a/IPython/nbconvert/preprocessors/tests/test_execute.py b/IPython/nbconvert/preprocessors/tests/test_execute.py
--- a/IPython/nbconvert/preprocessors/tests/test_execute.py
+++ b/IPython/nbconvert/preprocessors/tests/test_execute.py
@@ -89,4 +89,18 @@ def test_run_notebooks(self):
                     del cell['execution_count']
                 cell['outputs'] = []
             output_nb, _ = preprocessor(cleaned_input_nb, res)
-            self.assert_notebooks_equal(output_nb, input_nb)
+
+            if os.path.basename(filename) == "Disable Stdin.ipynb":
+                # We need to special-case this particular notebook, because the
+                # traceback contains machine-specific stuff like where IPython
+                # is installed. It is sufficient here to just check that an error
+                # was thrown, and that it was a StdinNotImplementedError
+                self.assertEqual(len(output_nb['cells']), 1)
+                self.assertEqual(len(output_nb['cells'][0]['outputs']), 1)
+                output = output_nb['cells'][0]['outputs'][0]
+                self.assertEqual(output['output_type'], 'error')
+                self.assertEqual(output['ename'], 'StdinNotImplementedError')
+                self.assertEqual(output['evalue'], 'raw_input was called, but this frontend does not support input requests.')
+
+            else:
+                self.assert_notebooks_equal(output_nb, input_nb)