From f80d93bb994ab0e3514ac303d410bffc5b706a96 2014-05-07 05:39:44 From: MinRK <benjaminrk@gmail.com> Date: 2014-05-07 05:39:44 Subject: [PATCH] support password in input_request --- diff --git a/IPython/html/static/notebook/js/outputarea.js b/IPython/html/static/notebook/js/outputarea.js index 497141d..1459ea4 100644 --- a/IPython/html/static/notebook/js/outputarea.js +++ b/IPython/html/static/notebook/js/outputarea.js @@ -748,6 +748,8 @@ var IPython = (function (IPython) { // disable any other raw_inputs, if they are left around $("div.output_subarea.raw_input_container").remove(); + var input_type = content.password ? 'password' : 'text'; + area.append( $("<div/>") .addClass("box-flex1 output_subarea raw_input_container") @@ -759,7 +761,7 @@ var IPython = (function (IPython) { .append( $("<input/>") .addClass("raw_input") - .attr('type', 'text') + .attr('type', input_type) .attr("size", 47) .keydown(function (event, ui) { // make sure we submit on enter, @@ -788,10 +790,15 @@ var IPython = (function (IPython) { var theprompt = container.find("span.raw_input_prompt"); var theinput = container.find("input.raw_input"); var value = theinput.val(); + var echo = value; + // don't echo if it's a password + if (theinput.attr('type') == 'password') { + echo = '········'; + } var content = { output_type : 'stream', name : 'stdout', - text : theprompt.text() + value + '\n' + text : theprompt.text() + echo + '\n' } // remove form container container.parent().remove(); diff --git a/IPython/kernel/zmq/ipkernel.py b/IPython/kernel/zmq/ipkernel.py index b46239e..42686c5 100755 --- a/IPython/kernel/zmq/ipkernel.py +++ b/IPython/kernel/zmq/ipkernel.py @@ -6,6 +6,7 @@ from __future__ import print_function +import getpass import sys import time import traceback @@ -333,7 +334,42 @@ class Kernel(Configurable): parent=parent, ident=self._topic('status'), ) + + def _forward_raw_input(self, ident, parent, allow_stdin): + """Replace raw_input. Note that is not sufficient to replace + raw_input in the user namespace. + """ + + if allow_stdin: + raw_input = lambda prompt='': self._raw_input(prompt, ident, parent) + input = lambda prompt='': eval(raw_input(prompt)) + _getpass = lambda prompt='', stream=None: self._raw_input( + prompt, ident, parent, password=True + ) + else: + _getpass = raw_input = input = lambda prompt='' : self._no_raw_input() + + + if py3compat.PY3: + self._sys_raw_input = builtin_mod.input + builtin_mod.input = raw_input + else: + self._sys_raw_input = builtin_mod.raw_input + self._sys_eval_input = builtin_mod.input + builtin_mod.raw_input = raw_input + builtin_mod.input = input + self._save_getpass = getpass.getpass + getpass.getpass = _getpass + + def _restore_raw_input(self): + # Restore raw_input + if py3compat.PY3: + builtin_mod.input = self._sys_raw_input + else: + builtin_mod.raw_input = self._sys_raw_input + builtin_mod.input = self._sys_eval_input + getpass.getpass = self._save_getpass def execute_request(self, stream, ident, parent): """handle an execute_request""" @@ -354,22 +390,7 @@ class Kernel(Configurable): shell = self.shell # we'll need this a lot here - # Replace raw_input. Note that is not sufficient to replace - # raw_input in the user namespace. - if content.get('allow_stdin', False): - raw_input = lambda prompt='': self._raw_input(prompt, ident, parent) - input = lambda prompt='': eval(raw_input(prompt)) - else: - raw_input = input = lambda prompt='' : self._no_raw_input() - - if py3compat.PY3: - self._sys_raw_input = builtin_mod.input - builtin_mod.input = raw_input - else: - self._sys_raw_input = builtin_mod.raw_input - self._sys_eval_input = builtin_mod.input - builtin_mod.raw_input = raw_input - builtin_mod.input = input + self._forward_raw_input(ident, parent, content.get('allow_stdin', False)) # Set the parent message of the display hook and out streams. shell.set_parent(parent) @@ -398,12 +419,7 @@ class Kernel(Configurable): else: status = u'ok' finally: - # Restore raw_input. - if py3compat.PY3: - builtin_mod.input = self._sys_raw_input - else: - builtin_mod.raw_input = self._sys_raw_input - builtin_mod.input = self._sys_eval_input + self._restore_raw_input() reply_content[u'status'] = status @@ -727,8 +743,8 @@ class Kernel(Configurable): stdin.""" raise StdinNotImplementedError("raw_input was called, but this " "frontend does not support stdin.") - - def _raw_input(self, prompt, ident, parent): + + def _raw_input(self, prompt, ident, parent, password=False): # Flush output before making the request. sys.stderr.flush() sys.stdout.flush() @@ -743,7 +759,7 @@ class Kernel(Configurable): raise # Send the input request. - content = json_clean(dict(prompt=prompt)) + content = json_clean(dict(prompt=prompt, password=password)) self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident)