New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
getpass.getpass not working with on windows when ctrl+v is used to enter the string #81607
Comments
|
Detailed issue filed here - microsoft/knack#160 |
|
getpass() reads from the console via msvcrt.getwch(). This is a raw console read, so Ctrl+V is read as the SYN (0x16) control character. Only the following keys are handled specially by getpass:
getpass() behaves pretty much the same in a Linux terminal emulator, except Ctrl+H isn't backspace. Recent versions of the console host in Windows 10 have an option to support pasting via Ctrl+Shift+V, regardless of the input mode. This is pretty common in Unix terminal emulators as well. You can change this setting in the Properties->Options dialog for a particular window or shortcut, or the default setting in the Defaults->Options dialog. In the "HKCU\Console" registry key, the DWORD value name is "InterceptCopyPaste". |
|
If anything, this seems to be a getpass doc issue. |
|
Suprisingly this works fine on ConEMU which I commonly use on windows though internally I still use powershell on conemu. It does not work on CMD and Powershell consoles. |
|
In addition to Ctrl+V, Shift+Insert also doesn't work. This behavior is the same Command Prompt and PowerShell on Windows 10. Workarounds include:
I stumbled upon this issue while investigating pypa/twine#671. Thanks for writing it up! |
|
I have an idea to solve it. But I don't know how to get the clipboard data. The code like this (Windows): def win_getpass(prompt='Password: ', stream=None, echoChar='*'):
"""Prompt for password with echo off, using Windows getwch()."""
if not isinstance(echoChar, str) or len(echoChar) < 1 or len(echoChar) > 1:
raise ValueError("Argument 'echoChar' is incorrect. It should be a character.")
if sys.stdin is not sys.__stdin__:
return fallback_getpass(prompt, stream)
for c in prompt:
msvcrt.putwch(c)
pw = ""
while 1:
c = msvcrt.getwch()
if ord(c) == 22: # User pressed Ctrl-V
k = <Clipboard Info>
pw += k
for _ in range(len(k)):
msvcrt.putwch(echoChar)
if c == '\r' or c == '\n' or c == '\r\n':
break
if c == '\003':
raise KeyboardInterrupt
if c == '\b':
if pw != '':
pw = pw[:-1]
count = len(pw)
for _ in range(count+1):
msvcrt.putwch('\b')
for _ in range(count):
msvcrt.putwch(echoChar)
msvcrt.putwch(' ')
msvcrt.putwch('\b')
else:
pw = pw + c
msvcrt.putwch(echoChar)
msvcrt.putwch('\r')
msvcrt.putwch('\n')
return pw |
In particular, if the console has quick-edit mode enabled, then you can paste text by right-clicking. Also, if text is selected in quick-edit mode, right-clicking copies to the clipboard.
I prefer this setting because it matches the behavior of terminals on other platforms. I suggest setting it in the "Defaults" dialog instead of "Properties". Otherwise, you'll have to configure it individually for each shell link (.LNK file) or session title. (The console session title defaults to the executable path, unless set in STARTUPINFO.)
Terminal allows configuring the actions for keyboard shortcuts. By default it grabs Ctrl+C (copy) and Ctrl+V (paste). I disable these mappings. I leave the default mappings in place for Ctrl+Shift+C (copy), Ctrl+Shift+V (paste), Ctrl+Insert (copy), and Shift+Insert (paste).
The behavior has to be the same when the parent process is a normal console shell such as CMD or PowerShell. Python inherits its console session from the shell, and that's the extent of the shell's involvement. A console session is hosted by an instance of conhost.exe or openconsole.exe. If the host is running in pseudoconsole (headless) mode, then the user interface for the session is hosted by another application (e.g. Windows Terminal). Even in pseudoconsole mode, however, the console host a lot to do in order to manage the session state for the console API. |
In Windows, using the window manager entails extending the process and the current thread with GUI-related structures in the kernel and then connecting the process to a window station (usually "WinSta0", which contains the clipboard) and connecting the thread to a desktop (usually "Default"). This permanently changes how the OS sees the process. I think whether or not the process should be a GUI process is something for the application to decide, not the standard library. Thus getpass should not read text from the clipboard. The docs could note that terminals may need to be configured to support Ctrl+Shift+C (copy) and Ctrl+Shift+V (paste) shortcuts, and that some terminals provide alternate ways to paste text, such as a right-click action or context menu. I don't think the docs should provide detailed explanations and configuration details for particular terminals. |
Which doc do you suggest this be included in? This comment would not be specific for getpass, right? |
|
Windows Terminal is the default in Windows 11, so this won't be an issue forever. The biggest problem with getpass is that it doesn't display anything when typing, so if you Ctrl+V in a console host that doesn't support it, you can't tell. Doing anything about that is its own set of problems, so I'd say at most we could add a note that getpass users may need to warn their users that they won't be able to see whether they've typed anything. That's probably too much though. I think we're fine to just have this issue to attract concerns and point people towards the workarounds. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: