[Python-checkins] bpo-37467: Fix PyErr_Display() for bytes filename (GH-14504) (GH-14515)

Victor Stinner webhook-mailer at python.org
Mon Jul 1 11:41:50 EDT 2019


https://github.com/python/cpython/commit/8cbffc4d96d1da0fbc38da6f34f2da30c5ffd601
commit: 8cbffc4d96d1da0fbc38da6f34f2da30c5ffd601
branch: 3.7
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019年07月01日T17:41:38+02:00
summary:
bpo-37467: Fix PyErr_Display() for bytes filename (GH-14504) (GH-14515)
Fix sys.excepthook() and PyErr_Display() if a filename is a bytes
string. For example, for a SyntaxError exception where the filename
attribute is a bytes string.
Cleanup also test_sys:
* Sort imports.
* Rename numruns global var to INTERN_NUMRUNS.
* Add DisplayHookTest and ExceptHookTest test case classes.
* Don't save/restore sys.stdout and sys.displayhook using
 setUp()/tearDown(): do it in each test method.
* Test error case (call hook with no argument) after the success case.
(cherry picked from commit f9b7457bd7f438263e0d2dd1f70589ad56a2585e)
files:
A Misc/NEWS.d/next/Core and Builtins/2019-07-01-12-22-44.bpo-37467.u-XyEu.rst
M Lib/test/test_sys.py
M Python/pythonrun.c
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index ef3fee13b961..84927a393f17 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -1,82 +1,103 @@
-import unittest, test.support
+from test import support
 from test.support.script_helper import assert_python_ok, assert_python_failure
-import sys, io, os
+import builtins
+import codecs
+import gc
+import locale
+import operator
+import os
 import struct
 import subprocess
+import sys
+import sysconfig
+import test.support
 import textwrap
+import unittest
 import warnings
-import operator
-import codecs
-import gc
-import sysconfig
-import locale
-import threading
+
 
 # count the number of test runs, used to create unique
 # strings to intern in test_intern()
-numruns = 0
+INTERN_NUMRUNS = 0
 
 
-class SysModuleTest(unittest.TestCase):
+class DisplayHookTest(unittest.TestCase):
 
- def setUp(self):
- self.orig_stdout = sys.stdout
- self.orig_stderr = sys.stderr
- self.orig_displayhook = sys.displayhook
+ def test_original_displayhook(self):
+ dh = sys.__displayhook__
 
- def tearDown(self):
- sys.stdout = self.orig_stdout
- sys.stderr = self.orig_stderr
- sys.displayhook = self.orig_displayhook
- test.support.reap_children()
+ with support.captured_stdout() as out:
+ dh(42)
 
- def test_original_displayhook(self):
- import builtins
- out = io.StringIO()
- sys.stdout = out
+ self.assertEqual(out.getvalue(), "42\n")
+ self.assertEqual(builtins._, 42)
 
- dh = sys.__displayhook__
+ del builtins._
 
- self.assertRaises(TypeError, dh)
- if hasattr(builtins, "_"):
- del builtins._
+ with support.captured_stdout() as out:
+ dh(None)
 
- dh(None)
 self.assertEqual(out.getvalue(), "")
 self.assertTrue(not hasattr(builtins, "_"))
- dh(42)
- self.assertEqual(out.getvalue(), "42\n")
- self.assertEqual(builtins._, 42)
 
- del sys.stdout
- self.assertRaises(RuntimeError, dh, 42)
+ # sys.displayhook() requires arguments
+ self.assertRaises(TypeError, dh)
+
+ stdout = sys.stdout
+ try:
+ del sys.stdout
+ self.assertRaises(RuntimeError, dh, 42)
+ finally:
+ sys.stdout = stdout
 
 def test_lost_displayhook(self):
- del sys.displayhook
- code = compile("42", "<string>", "single")
- self.assertRaises(RuntimeError, eval, code)
+ displayhook = sys.displayhook
+ try:
+ del sys.displayhook
+ code = compile("42", "<string>", "single")
+ self.assertRaises(RuntimeError, eval, code)
+ finally:
+ sys.displayhook = displayhook
 
 def test_custom_displayhook(self):
 def baddisplayhook(obj):
 raise ValueError
- sys.displayhook = baddisplayhook
- code = compile("42", "<string>", "single")
- self.assertRaises(ValueError, eval, code)
 
- def test_original_excepthook(self):
- err = io.StringIO()
- sys.stderr = err
+ with support.swap_attr(sys, 'displayhook', baddisplayhook):
+ code = compile("42", "<string>", "single")
+ self.assertRaises(ValueError, eval, code)
+
 
- eh = sys.__excepthook__
+class ExceptHookTest(unittest.TestCase):
 
- self.assertRaises(TypeError, eh)
+ def test_original_excepthook(self):
 try:
 raise ValueError(42)
 except ValueError as exc:
- eh(*sys.exc_info())
+ with support.captured_stderr() as err:
+ sys.__excepthook__(*sys.exc_info())
 
 self.assertTrue(err.getvalue().endswith("ValueError: 42\n"))
 
+ self.assertRaises(TypeError, sys.__excepthook__)
+
+ def test_excepthook_bytes_filename(self):
+ # bpo-37467: sys.excepthook() must not crash if a filename
+ # is a bytes string
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', BytesWarning)
+
+ try:
+ raise SyntaxError("msg", (b"bytes_filename", 123, 0, "text"))
+ except SyntaxError as exc:
+ with support.captured_stderr() as err:
+ sys.__excepthook__(*sys.exc_info())
+
+ err = err.getvalue()
+ self.assertIn(""" File "b'bytes_filename'", line 123\n""", err)
+ self.assertIn(""" text\n""", err)
+ self.assertTrue(err.endswith("SyntaxError: msg\n"))
+
 def test_excepthook(self):
 with test.support.captured_output("stderr") as stderr:
 sys.excepthook(1, '1', 1)
@@ -86,6 +107,12 @@ def test_excepthook(self):
 # FIXME: testing the code for a lost or replaced excepthook in
 # Python/pythonrun.c::PyErr_PrintEx() is tricky.
 
+
+class SysModuleTest(unittest.TestCase):
+
+ def tearDown(self):
+ test.support.reap_children()
+
 def test_exit(self):
 # call with two arguments
 self.assertRaises(TypeError, sys.exit, 42, 42)
@@ -502,10 +529,10 @@ def test_43581(self):
 self.assertEqual(sys.__stdout__.encoding, sys.__stderr__.encoding)
 
 def test_intern(self):
- global numruns
- numruns += 1
+ global INTERN_NUMRUNS
+ INTERN_NUMRUNS += 1
 self.assertRaises(TypeError, sys.intern)
- s = "never interned before" + str(numruns)
+ s = "never interned before" + str(INTERN_NUMRUNS)
 self.assertTrue(sys.intern(s) is s)
 s2 = s.swapcase().swapcase()
 self.assertTrue(sys.intern(s2) is s)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-07-01-12-22-44.bpo-37467.u-XyEu.rst b/Misc/NEWS.d/next/Core and Builtins/2019-07-01-12-22-44.bpo-37467.u-XyEu.rst
new file mode 100644
index 000000000000..5e809646b4b8
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-07-01-12-22-44.bpo-37467.u-XyEu.rst	
@@ -0,0 +1,3 @@
+Fix :func:`sys.excepthook` and :c:func:`PyErr_Display` if a filename is a
+bytes string. For example, for a SyntaxError exception where the filename
+attribute is a bytes string.
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index c4ec5ac66c47..4c974cef39c7 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -750,7 +750,7 @@ print_exception(PyObject *f, PyObject *value)
 Py_DECREF(value);
 value = message;
 
- line = PyUnicode_FromFormat(" File \"%U\", line %d\n",
+ line = PyUnicode_FromFormat(" File \"%S\", line %d\n",
 filename, lineno);
 Py_DECREF(filename);
 if (line != NULL) {


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /