diff -r 44c1c0cbdc06 Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py Fri Mar 13 09:04:34 2015 +0200 +++ b/Lib/test/test_warnings.py Fri Mar 13 22:17:17 2015 +0200 @@ -593,6 +593,63 @@ class WarningsDisplayTests(unittest.Test 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 -r 44c1c0cbdc06 Lib/warnings.py --- a/Lib/warnings.py Fri Mar 13 09:04:34 2015 +0200 +++ b/Lib/warnings.py Fri Mar 13 22:17:17 2015 +0200 @@ -31,7 +31,7 @@ def _show_warning(message, category, fil 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,