Author: Amaury Forgeot d'Arc <[email protected]>
Branch: 
Changeset: r78090:0117c2d4c183
Date: 2015-06-14 16:38 +0200
http://bitbucket.org/pypy/pypy/changeset/0117c2d4c183/

Log:    CPython Issue #21802: The reader in BufferedRWPair now is closed
        even when closing writer failed in BufferedRWPair.close()

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
@@ -972,9 +972,26 @@
             method, writer=True)
 
     # forward to both
-    for method in ['close']:
-        locals()[method + '_w'] = make_forwarding_method(
-            method, writer=True, reader=True)
+    def close_w(self, space, __args__):
+        if self.w_writer is None:
+            raise oefmt(space.w_ValueError,
+                        "I/O operation on uninitialized object")
+        w_meth = space.getattr(self.w_writer, space.wrap("close"))
+        try:
+            space.call_args(w_meth, __args__)
+        except OperationError as e:
+            pass
+        else:
+            e = None
+
+        if self.w_reader is None:
+            raise oefmt(space.w_ValueError,
+                        "I/O operation on uninitialized object")
+        w_meth = space.getattr(self.w_reader, space.wrap("close"))
+        space.call_args(w_meth, __args__)
+
+        if e:
+            raise e
 
     def isatty_w(self, space):
         if space.is_true(space.call_method(self.w_writer, "isatty")):
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
@@ -592,6 +592,47 @@
 
         raises(IOError, _io.BufferedRWPair, _io.BytesIO(), NotWritable())
 
+    def test_writer_close_error_on_close(self):
+        import _io
+        class MockRawIO(_io._IOBase):
+            def readable(self):
+                return True
+            def writable(self):
+                return True
+        def writer_close():
+            writer_non_existing
+        reader = MockRawIO()
+        writer = MockRawIO()
+        writer.close = writer_close
+        pair = _io.BufferedRWPair(reader, writer)
+        err = raises(NameError, pair.close)
+        assert 'writer_non_existing' in str(err.value)
+        assert not pair.closed
+        assert reader.closed
+        assert not writer.closed
+
+    def test_reader_writer_close_error_on_close(self):
+        import _io
+        class MockRawIO(_io._IOBase):
+            def readable(self):
+                return True
+            def writable(self):
+                return True
+        def reader_close():
+            reader_non_existing
+        def writer_close():
+            writer_non_existing
+        reader = MockRawIO()
+        reader.close = reader_close
+        writer = MockRawIO()
+        writer.close = writer_close
+        pair = _io.BufferedRWPair(reader, writer)
+        err = raises(NameError, pair.close)
+        assert 'reader_non_existing' in str(err.value)
+        assert not pair.closed
+        assert not reader.closed
+        assert not writer.closed
+
 class AppTestBufferedRandom:
     spaceconfig = dict(usemodules=['_io'])
 
diff --git a/pypy/module/_io/test/test_fileio.py 
b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -197,17 +197,13 @@
     def test_mode_strings(self):
         import _io
         import os
-        try:
-            for modes in [('w', 'wb'), ('wb', 'wb'), ('wb+', 'rb+'),
-                          ('w+b', 'rb+'), ('a', 'ab'), ('ab', 'ab'),
-                          ('ab+', 'ab+'), ('a+b', 'ab+'), ('r', 'rb'),
-                          ('rb', 'rb'), ('rb+', 'rb+'), ('r+b', 'rb+')]:
-                # read modes are last so that TESTFN will exist first
-                with _io.FileIO(self.tmpfile, modes[0]) as f:
-                    assert f.mode == modes[1]
-        finally:
-            if os.path.exists(self.tmpfile):
-                os.unlink(self.tmpfile)
+        for modes in [('w', 'wb'), ('wb', 'wb'), ('wb+', 'rb+'),
+                      ('w+b', 'rb+'), ('a', 'ab'), ('ab', 'ab'),
+                      ('ab+', 'ab+'), ('a+b', 'ab+'), ('r', 'rb'),
+                      ('rb', 'rb'), ('rb+', 'rb+'), ('r+b', 'rb+')]:
+            # read modes are last so that TESTFN will exist first
+            with _io.FileIO(self.tmpfile, modes[0]) as f:
+                assert f.mode == modes[1]
 
     def test_flush_error_on_close(self):
         # Test that the file is closed despite failed flush
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to