Issue #23637: Showing a warning no longer fails with UnicodeErrror.
Formatting unicode warning in the file with the path containing non-ascii
characters no longer fails with UnicodeErrror.
diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py
index 7a9459a..11dc294 100644
--- a/Lib/test/test_warnings.py
+++ b/Lib/test/test_warnings.py
@@ -593,6 +593,63 @@
self.assertEqual(expect, self.module.formatwarning(message,
category, file_name, line_num, file_line))
+ @test_support.requires_unicode
+ def test_formatwarning_unicode_msg(self):
+ message = u"msg"
+ category = Warning
+ file_name = os.path.splitext(warning_tests.__file__)[0] + '.py'
+ line_num = 3
+ file_line = linecache.getline(file_name, line_num).strip()
+ format = "%s:%s: %s: %s\n %s\n"
+ expect = format % (file_name, line_num, category.__name__, message,
+ file_line)
+ self.assertEqual(expect, self.module.formatwarning(message,
+ category, file_name, line_num))
+ # Test the 'line' argument.
+ file_line += " for the win!"
+ expect = format % (file_name, line_num, category.__name__, message,
+ file_line)
+ self.assertEqual(expect, self.module.formatwarning(message,
+ category, file_name, line_num, file_line))
+
+ @test_support.requires_unicode
+ @unittest.skipUnless(test_support.FS_NONASCII, 'need test_support.FS_NONASCII')
+ def test_formatwarning_unicode_msg_nonascii_filename(self):
+ message = u"msg"
+ category = Warning
+ unicode_file_name = test_support.FS_NONASCII + u'.py'
+ file_name = unicode_file_name.encode(sys.getfilesystemencoding())
+ line_num = 3
+ file_line = 'spam'
+ format = "%s:%s: %s: %s\n %s\n"
+ expect = format % (file_name, line_num, category.__name__, str(message),
+ file_line)
+ self.assertEqual(expect, self.module.formatwarning(message,
+ category, file_name, line_num, file_line))
+ message = u"\xb5sg"
+ expect = format % (unicode_file_name, line_num, category.__name__, message,
+ file_line)
+ self.assertEqual(expect, self.module.formatwarning(message,
+ category, file_name, line_num, file_line))
+
+ @test_support.requires_unicode
+ def test_formatwarning_unicode_msg_nonascii_fileline(self):
+ message = u"msg"
+ category = Warning
+ file_name = 'file.py'
+ line_num = 3
+ file_line = 'sp\xe4m'
+ format = "%s:%s: %s: %s\n %s\n"
+ expect = format % (file_name, line_num, category.__name__, str(message),
+ file_line)
+ self.assertEqual(expect, self.module.formatwarning(message,
+ category, file_name, line_num, file_line))
+ message = u"\xb5sg"
+ expect = format % (file_name, line_num, category.__name__, message,
+ unicode(file_line, 'latin1'))
+ self.assertEqual(expect, self.module.formatwarning(message,
+ category, file_name, line_num, file_line))
+
def test_showwarning(self):
file_name = os.path.splitext(warning_tests.__file__)[0] + '.py'
line_num = 3
diff --git a/Lib/warnings.py b/Lib/warnings.py
index fbec94b..b0d53aa 100644
--- a/Lib/warnings.py
+++ b/Lib/warnings.py
@@ -31,7 +31,7 @@
return
try:
file.write(formatwarning(message, category, filename, lineno, line))
- except IOError:
+ except (IOError, UnicodeError):
pass # the file (probably stderr) is invalid - this warning gets lost.
# Keep a working version around in case the deprecation of the old API is
# triggered.
@@ -39,11 +39,29 @@
def formatwarning(message, category, filename, lineno, line=None):
"""Function to format a warning the standard way."""
- s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
+ try:
+ unicodetype = unicode
+ except NameError:
+ unicodetype = ()
+ try:
+ message = str(message)
+ except UnicodeEncodeError:
+ pass
+ s = "%s: %s: %s\n" % (lineno, category.__name__, message)
line = linecache.getline(filename, lineno) if line is None else line
if line:
line = line.strip()
+ if isinstance(s, unicodetype) and isinstance(line, str):
+ line = unicode(line, 'latin1')
s += " %s\n" % line
+ if isinstance(s, unicodetype) and isinstance(filename, str):
+ enc = sys.getfilesystemencoding()
+ if enc:
+ try:
+ filename = unicode(filename, enc)
+ except UnicodeDecodeError:
+ pass
+ s = "%s:%s" % (filename, s)
return s
def filterwarnings(action, message="", category=Warning, module="", lineno=0,