diff --git a/Lib/getpass.py b/Lib/getpass.py index 53c38b88975..27403634883 100644 --- a/Lib/getpass.py +++ b/Lib/getpass.py @@ -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() diff --git a/Lib/test/test_getpass.py b/Lib/test/test_getpass.py index 1731bd44a65..3452e46213a 100644 --- a/Lib/test/test_getpass.py +++ b/Lib/test/test_getpass.py @@ -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) diff --git a/Misc/NEWS b/Misc/NEWS index cd85b2abed9..a8da8ab2050 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,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.