From: Serhiy Storchaka Date: Sat, 16 May 2015 13:42:18 +0000 (+0300) Subject: Issue #23637: Showing a warning no longer fails with UnicodeErrror. X-Git-Tag: v2.7.11rc1~302^2~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f40fcb33d2e905b128daa24f7ce6f25fb5cd5d9e;p=thirdparty%2FPython%2Fcpython.git 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 7a9459a47e2b..11dc29408ae3 100644 --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -593,6 +593,63 @@ class WarningsDisplayTests(unittest.TestCase): 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 fbec94b7f07a..b0d53aa0321b 100644 --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -31,7 +31,7 @@ def _show_warning(message, category, filename, lineno, file=None, line=None): 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 @@ showwarning = _show_warning 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, diff --git a/Misc/NEWS b/Misc/NEWS index dbaddd88b921..8a8e8d2e5d64 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Core and Builtins Library ------- +- 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. + - Issue #24134: Reverted issue #24134 changes.