Author: Amaury Forgeot d'Arc <amaur...@gmail.com>
Branch: py3.5
Changeset: r91087:0f983f4075de
Date: 2017-04-18 19:03 +0200
http://bitbucket.org/pypy/pypy/changeset/0f983f4075de/

Log:    Chain exceptions when close() contains multiple operations that can
        fail.

diff --git a/pypy/module/_io/interp_bufferedio.py 
b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -1030,7 +1030,12 @@
             raise oefmt(space.w_ValueError,
                         "I/O operation on uninitialized object")
         w_meth = space.getattr(self.w_reader, space.newtext("close"))
-        space.call_args(w_meth, __args__)
+        try:
+            space.call_args(w_meth, __args__)
+        except OperationError as e2:
+            if e:
+                e2.chain_exceptions(space, e)
+            e = e2
 
         if e:
             raise e
diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -528,13 +528,20 @@
 
     def close_w(self, space):
         self._check_attached(space)
-        if not space.is_true(space.getattr(self.w_buffer,
-                                           space.newtext("closed"))):
+        if space.is_true(space.getattr(self.w_buffer,
+                                       space.newtext("closed"))):
+            return
+        try:
+            space.call_method(self, "flush")
+        except OperationError as e:
             try:
-                space.call_method(self, "flush")
-            finally:
                 ret = space.call_method(self.w_buffer, "close")
-            return ret
+            except OperationError as e2:
+                e2.chain_exceptions(space, e)
+            raise
+        else:
+            ret = space.call_method(self.w_buffer, "close")
+        return ret
 
     def _dealloc_warn_w(self, space, w_source):
         space.call_method(self.w_buffer, "_dealloc_warn", w_source)
diff --git a/pypy/module/_io/test/test_bufferedio.py 
b/pypy/module/_io/test/test_bufferedio.py
--- a/pypy/module/_io/test/test_bufferedio.py
+++ b/pypy/module/_io/test/test_bufferedio.py
@@ -707,6 +707,7 @@
         pair = _io.BufferedRWPair(reader, writer)
         err = raises(NameError, pair.close)
         assert 'reader_non_existing' in str(err.value)
+        assert 'writer_non_existing' in str(err.value.__context__)
         assert not pair.closed
         assert not reader.closed
         assert not writer.closed
diff --git a/pypy/module/_io/test/test_textio.py 
b/pypy/module/_io/test/test_textio.py
--- a/pypy/module/_io/test/test_textio.py
+++ b/pypy/module/_io/test/test_textio.py
@@ -365,6 +365,22 @@
         raises(IOError, txt.close)  # exception not swallowed
         assert txt.closed
 
+    def test_close_error_on_close(self):
+        import _io as io
+        buffer = io.BytesIO(b'testdata')
+        def bad_flush():
+            raise OSError('flush')
+        def bad_close():
+            raise OSError('close')
+        buffer.close = bad_close
+        txt = io.TextIOWrapper(buffer, encoding="ascii")
+        txt.flush = bad_flush
+        err = raises(OSError, txt.close)
+        assert err.value.args == ('close',)
+        assert isinstance(err.value.__context__, OSError)
+        assert err.value.__context__.args == ('flush',)
+        assert not txt.closed
+
     def test_illegal_decoder(self):
         import _io
         raises(LookupError, _io.TextIOWrapper, _io.BytesIO(),
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to