Author: Brian Kearns <[email protected]>
Branch: stdlib-2.7.4
Changeset: r63214:ab324b210044
Date: 2013-04-10 18:19 -0400
http://bitbucket.org/pypy/pypy/changeset/ab324b210044/

Log:    _io: call close on stream even if flush raises (cpython issue16597)

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
@@ -311,9 +311,11 @@
         with self.lock:
             if self._closed(space):
                 return
-        space.call_method(self, "flush")
-        with self.lock:
-            space.call_method(self.w_raw, "close")
+        try:
+            space.call_method(self, "flush")
+        finally:
+            with self.lock:
+                space.call_method(self.w_raw, "close")
 
     def simple_flush_w(self, space):
         self._check_init(space)
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
@@ -494,8 +494,10 @@
         self._check_init(space)
         if not space.is_true(space.getattr(self.w_buffer,
                                            space.wrap("closed"))):
-            space.call_method(self, "flush")
-            return space.call_method(self.w_buffer, "close")
+            try:
+                space.call_method(self, "flush")
+            finally:
+                return space.call_method(self.w_buffer, "close")
 
     # _____________________________________________________________
     # read methods
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
@@ -513,6 +513,35 @@
         exc = raises(RuntimeError, bufio.flush)
         assert "reentrant" in str(exc.value)  # And not e.g. recursion limit.
 
+    def test_write_error_on_close(self):
+        import _io
+        class MockRawIO(_io._RawIOBase):
+            def writable(self):
+                return True
+            def write(self, data):
+                raise IOError()
+        raw = MockRawIO()
+        b = _io.BufferedWriter(raw)
+        b.write(b'spam')
+        raises(IOError, b.close)  # exception not swallowed
+        assert b.closed
+
+    def test_close_error_on_close(self):
+        import _io
+        class MockRawIO(_io._RawIOBase):
+            def writable(self):
+                return True
+            def close(self):
+                raise IOError('close')
+        def bad_flush():
+            raise IOError('flush')
+        raw = MockRawIO()
+        b = _io.BufferedWriter(raw)
+        b.flush = bad_flush
+        err = raises(IOError, b.close)  # exception not swallowed
+        assert err.value.args == ('close',)
+        assert not b.closed
+
 class AppTestBufferedRWPair:
     def test_pair(self):
         import _io
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
@@ -201,7 +201,6 @@
 
 
 class AppTestIncrementalNewlineDecoder:
-
     def test_newline_decoder(self):
         import _io
         def check_newline_decoding_utf8(decoder):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to