[Python-checkins] cpython (3.4): Issue #21677: Fixed chaining nonnormalized exceptions in io close() methods.

serhiy.storchaka python-checkins at python.org
Mon Jun 9 08:34:18 CEST 2014


http://hg.python.org/cpython/rev/a3b7b89da34f
changeset:   91100:a3b7b89da34f
branch:      3.4
parent:      91098:454d4a9a3088
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Mon Jun 09 09:13:04 2014 +0300
summary:
  Issue #21677: Fixed chaining nonnormalized exceptions in io close() methods.

files:
  Lib/test/test_io.py      |  51 ++++++++++++++++++++++++++++
  Misc/NEWS                |   2 +
  Modules/_io/bufferedio.c |   1 +
  Modules/_io/textio.c     |   1 +
  4 files changed, 55 insertions(+), 0 deletions(-)


diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -792,9 +792,27 @@
         with self.assertRaises(OSError) as err: # exception not swallowed
             b.close()
         self.assertEqual(err.exception.args, ('close',))
+        self.assertIsInstance(err.exception.__context__, OSError)
         self.assertEqual(err.exception.__context__.args, ('flush',))
         self.assertFalse(b.closed)
 
+    def test_nonnormalized_close_error_on_close(self):
+        # Issue #21677
+        raw = self.MockRawIO()
+        def bad_flush():
+            raise non_existing_flush
+        def bad_close():
+            raise non_existing_close
+        raw.close = bad_close
+        b = self.tp(raw)
+        b.flush = bad_flush
+        with self.assertRaises(NameError) as err: # exception not swallowed
+            b.close()
+        self.assertIn('non_existing_close', str(err.exception))
+        self.assertIsInstance(err.exception.__context__, NameError)
+        self.assertIn('non_existing_flush', str(err.exception.__context__))
+        self.assertFalse(b.closed)
+
     def test_multi_close(self):
         raw = self.MockRawIO()
         b = self.tp(raw)
@@ -2576,6 +2594,39 @@
         self.assertRaises(OSError, txt.close) # exception not swallowed
         self.assertTrue(txt.closed)
 
+    def test_close_error_on_close(self):
+        buffer = self.BytesIO(self.testdata)
+        def bad_flush():
+            raise OSError('flush')
+        def bad_close():
+            raise OSError('close')
+        buffer.close = bad_close
+        txt = self.TextIOWrapper(buffer, encoding="ascii")
+        txt.flush = bad_flush
+        with self.assertRaises(OSError) as err: # exception not swallowed
+            txt.close()
+        self.assertEqual(err.exception.args, ('close',))
+        self.assertIsInstance(err.exception.__context__, OSError)
+        self.assertEqual(err.exception.__context__.args, ('flush',))
+        self.assertFalse(txt.closed)
+
+    def test_nonnormalized_close_error_on_close(self):
+        # Issue #21677
+        buffer = self.BytesIO(self.testdata)
+        def bad_flush():
+            raise non_existing_flush
+        def bad_close():
+            raise non_existing_close
+        buffer.close = bad_close
+        txt = self.TextIOWrapper(buffer, encoding="ascii")
+        txt.flush = bad_flush
+        with self.assertRaises(NameError) as err: # exception not swallowed
+            txt.close()
+        self.assertIn('non_existing_close', str(err.exception))
+        self.assertIsInstance(err.exception.__context__, NameError)
+        self.assertIn('non_existing_flush', str(err.exception.__context__))
+        self.assertFalse(txt.closed)
+
     def test_multi_close(self):
         txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii")
         txt.close()
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,8 @@
 Library
 -------
 
+- Issue #21677: Fixed chaining nonnormalized exceptions in io close() methods.
+
 - Issue #11709: Fix the pydoc.help function to not fail when sys.stdin is not a
   valid file.
 
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -549,6 +549,7 @@
         }
         else {
             PyObject *val2;
+            PyErr_NormalizeException(&exc, &val, &tb);
             Py_DECREF(exc);
             Py_XDECREF(tb);
             PyErr_Fetch(&exc, &val2, &tb);
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -2614,6 +2614,7 @@
             }
             else {
                 PyObject *val2;
+                PyErr_NormalizeException(&exc, &val, &tb);
                 Py_DECREF(exc);
                 Py_XDECREF(tb);
                 PyErr_Fetch(&exc, &val2, &tb);

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list