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

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


http://hg.python.org/cpython/rev/d6ac4b6020b9
changeset: 91101:d6ac4b6020b9
parent: 91099:524d73b8f29e
parent: 91100:a3b7b89da34f
user: Serhiy Storchaka <storchaka at gmail.com>
date: Mon Jun 09 09:15:42 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
@@ -92,6 +92,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
@@ -2620,6 +2620,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

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