4

I am, unfortunately, using Windows 7 and am running GNU Emacs 25.3.1 (x86_64-w64-mingw32) of 2017-09-26. Everything functions as expected from the command line. However, within Emacs, I encounter a problem.

I have started Emacs using -q. I start an interactive Python session with M-x run-python. Regular input works fine. However, when I try to use getpass, no input is accepted and all text is printed to the screen. Pressing Enter only inserts a new line. To demonstrate:

enter image description here

Text transcript of Emacs input:

Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> python.el: native completion setup failed
>>> user = input('Username: ')
Username: bob
>>> import getpass
>>> pw = getpass.getpass('Password: ')
my secret password
wait, why is it printing to screen?
and why does pressing return only insert a new line?
I can't seem to get out of this!
I'm going to press C-c C-c now  C-c C-c  C-c C-cTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\Users\AppData\Local\Continuum\anaconda3\lib\getpass.py", line 110, in win_getpass
    raise KeyboardInterrupt
KeyboardInterrupt
>>>   File "<stdin>", line 1
    my secret password
            ^
SyntaxError: invalid syntax
>>>   File "<stdin>", line 1
    wait, why is it printing to screen?
                           ^
SyntaxError: invalid syntax
>>>   File "<stdin>", line 1
    and why does pressing return only insert a new line?
      ^
SyntaxError: invalid syntax
>>>   File "<stdin>", line 1
    I can't seem to get out of this!
        ^
SyntaxError: invalid syntax
>>> 

I'm not sure what to do next in fixing this.

  1. Does anyone else have this issue?
  2. If so, might it be a problem with python.el and a bug report need to be submitted? And where would that bug be reported?
  3. Any ideas or suggestions?
0

3 Answers 3

4

To make jpkotta's solution work for Windows, you need to use

def my_getpass(prompt):
    if os.isatty(0):
        return getpass.getpass(prompt)
    else:
        return input(prompt)

This is because getpass uses msvcrt.putwch and msvcrt.getwch which only work in a cmd.exe console. IMO, this is a bug in the Python libraries, they should be using the fallback_getpass when os.isatty(0) is false.

2
  • This still prints the password to the screen, but the input is accepted. Accepting input is the primary issue and masking against over-the-shoulder attacks is secondary (and probably best suited for a separate question). Commented May 10, 2018 at 20:04
  • @LoremIpsum If you apply jpkotta's solution as well, then the password should not be printed (assuming the prompt matches comint-password-prompt-regexp, that is).
    – npostavs
    Commented May 10, 2018 at 20:43
4

On Linux, it works just like input() (terminates with RET, input is visible). getpass relies on setting the terminal correctly, and inferior python mode isn't a standard terminal. For example, if you do M-x term RET python RET, you get python running in an actual terminal and it works. If you run python from eshell or shell (also not real terminals) it actually asks for a password in the minibuffer, but only if you have the standard prompt of "Password: ", which gives a hint that those modes are looking for "Password: " and treating it specially. The trick is to add a filter for that, and fortunately it's all implemented already.

(defun jpk/inferior-python-mode-hook ()
  (add-hook 'comint-output-filter-functions
            #'comint-watch-for-password-prompt
            nil 'local))
(add-hook 'inferior-python-mode-hook #'jpk/inferior-python-mode-hook)
1
  • Thank you for your response. Unfortunately, I did not have any success using your hook. It appears as though Emacs has problems with terminals when running on Windows. While shell, eshell, and (make-comint "cmd" "cmd" nil) all function to navigate the file system (term appears not to work on Windows altogether), none of them are able to run the interactive Python shell. Each fails to accept input (similar to the screen shot) when the python command is issued. Commented Jan 3, 2018 at 13:35
0

In case you're wondering how to

apply jpkotta's solution as well

on Windows to prevent the password from being printed: you can either customize comint-password-prompt-regexp or just use

the standard prompt of "Password: "

def my_getpass(prompt):
    if os.isatty(0):
        return getpass.getpass(prompt)
    else:
        return input('Password: ')

As for

If so, might it be a problem with python.el and a bug report need to be submitted? And where would that bug be reported?

As mentioned, seems like a missing feature in python's getpass. Go for it :-) .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.