#21169: fix getpass to use replace error handler on UnicodeEncodeError.

If the input stream encoding couldn't encode one or more of the
non-ascii characters in the prompt, it would fail, throwing a
UnicodeEncodeError.  Now if that happens we re-encoding using the
'replace' error handler.

Patch by Kushal Das.
This commit is contained in:
R David Murray 2014-04-13 22:07:39 -04:00
parent e544f9a27e
commit d5aa487cce
3 changed files with 19 additions and 2 deletions

View File

@ -135,7 +135,12 @@ def _raw_input(prompt="", stream=None, input=None):
input = sys.stdin
prompt = str(prompt)
if prompt:
stream.write(prompt)
try:
stream.write(prompt)
except UnicodeEncodeError:
prompt = prompt.encode(stream.encoding, 'replace')
prompt = prompt.decode(stream.encoding)
stream.write(prompt)
stream.flush()
# NOTE: The Python C API calls flockfile() (and unlock) during readline.
line = input.readline()

View File

@ -1,7 +1,7 @@
import getpass
import os
import unittest
from io import BytesIO, StringIO
from io import BytesIO, StringIO, TextIOWrapper
from unittest import mock
from test import support
@ -69,6 +69,14 @@ class GetpassRawinputTest(unittest.TestCase):
getpass._raw_input(stream=StringIO())
mock_input.readline.assert_called_once_with()
@mock.patch('sys.stdin')
def test_uses_stdin_as_different_locale(self, mock_input):
stream = TextIOWrapper(BytesIO(), encoding="ascii")
mock_input.readline.return_value = "HasÅo: "
getpass._raw_input(prompt="HasÅo: ",stream=stream)
mock_input.readline.assert_called_once_with()
def test_raises_on_empty_input(self):
input = StringIO('')
self.assertRaises(EOFError, getpass._raw_input, input=input)

View File

@ -27,6 +27,10 @@ Core and Builtins
Library
-------
- Issue #21169: getpass now handles non-ascii characters that the
input stream encoding cannot encode by re-encoding using the
replace error handler.
- Issue #21171: Fixed undocumented filter API of the rot13 codec.
Patch by Berker Peksag.