diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2014-06-09 06:13:04 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2014-06-09 06:13:04 (GMT) |
commit | 8a8f7f983099f172d1f7c25d4fd99f5c0eb14072 (patch) | |
tree | ece2ee26d3edfee06c27e325f7aff80cf9c2adfb | |
parent | b1f59cecc97000396604a3852804932512598938 (diff) | |
download | cpython-8a8f7f983099f172d1f7c25d4fd99f5c0eb14072.zip cpython-8a8f7f983099f172d1f7c25d4fd99f5c0eb14072.tar.gz cpython-8a8f7f983099f172d1f7c25d4fd99f5c0eb14072.tar.bz2 |
Issue #21677: Fixed chaining nonnormalized exceptions in io close() methods.
-rw-r--r-- | Lib/test/test_io.py | 51 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Modules/_io/bufferedio.c | 1 | ||||
-rw-r--r-- | 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 index ef1e056..a94b85a 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -792,9 +792,27 @@ class CommonBufferedTests: 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 @@ class TextIOWrapperTest(unittest.TestCase): 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() @@ -22,6 +22,8 @@ Core and Builtins 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 index 7494646..d0e92e5 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -549,6 +549,7 @@ buffered_close(buffered *self, PyObject *args) } 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 index ba5789d..55392b4 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -2614,6 +2614,7 @@ textiowrapper_close(textio *self, PyObject *args) } else { PyObject *val2; + PyErr_NormalizeException(&exc, &val, &tb); Py_DECREF(exc); Py_XDECREF(tb); PyErr_Fetch(&exc, &val2, &tb); |