]> granicus.if.org Git - python/commitdiff
Merged revisions 68484-68485 via svnmerge from
authorAntoine Pitrou <solipsis@pitrou.net>
Sat, 10 Jan 2009 16:22:51 +0000 (16:22 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Sat, 10 Jan 2009 16:22:51 +0000 (16:22 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r68484 | antoine.pitrou | 2009-01-10 17:13:45 +0100 (sam., 10 janv. 2009) | 3 lines

  Issue #3860: GzipFile and BZ2File now support the context manager protocol.
........
  r68485 | antoine.pitrou | 2009-01-10 17:15:24 +0100 (sam., 10 janv. 2009) | 1 line

  Add NEWS entry for r68484.
........

Lib/gzip.py
Lib/test/test_bz2.py
Lib/test/test_gzip.py
Misc/NEWS
Modules/bz2module.c

index 560a722bae91d2caa74f4dd4389debe44cbf0624..019c3e2df1f1e0d5862922c05f60b5350664082c 100644 (file)
@@ -472,6 +472,14 @@ class GzipFile:
         else:
             raise StopIteration
 
+    def __enter__(self):
+        if self.fileobj is None:
+            raise ValueError("I/O operation on closed GzipFile object")
+        return self
+
+    def __exit__(self, *args):
+        self.close()
+
 
 def _test():
     # Act like gzip; with -d, act like gunzip.
index 366ab7a16fe3f26e2f9f78836466f1b38485f57f..18d84bb60e24a42372705f1a32a70e160d1b4757 100644 (file)
@@ -258,6 +258,28 @@ class BZ2FileTest(BaseTest):
         bz2f.close()
         self.assertEqual(xlines, [b'Test'])
 
+    def testContextProtocol(self):
+        # BZ2File supports the context management protocol
+        f = None
+        with BZ2File(self.filename, "wb") as f:
+            f.write(b"xxx")
+        f = BZ2File(self.filename, "rb")
+        f.close()
+        try:
+            with f:
+                pass
+        except ValueError:
+            pass
+        else:
+            self.fail("__enter__ on a closed file didn't raise an exception")
+        try:
+            with BZ2File(self.filename, "wb") as f:
+                1/0
+        except ZeroDivisionError:
+            pass
+        else:
+            self.fail("1/0 didn't raise an exception")
+
 
 class BZ2CompressorTest(BaseTest):
     def testCompress(self):
index e758826fa7369253deabaf72722151e96aec08e6..baf3a21f8744a620848ec0e831343e5a0d00719a 100644 (file)
@@ -166,7 +166,6 @@ class TestGzip(unittest.TestCase):
         fWrite = gzip.GzipFile(self.filename, 'w', mtime = mtime)
         fWrite.write(data1)
         fWrite.close()
-
         fRead = gzip.GzipFile(self.filename)
         dataRead = fRead.read()
         self.assertEqual(dataRead, data1)
@@ -223,6 +222,27 @@ class TestGzip(unittest.TestCase):
 
         fRead.close()
 
+    def test_with_open(self):
+        # GzipFile supports the context management protocol
+        with gzip.GzipFile(self.filename, "wb") as f:
+            f.write(b"xxx")
+        f = gzip.GzipFile(self.filename, "rb")
+        f.close()
+        try:
+            with f:
+                pass
+        except ValueError:
+            pass
+        else:
+            self.fail("__enter__ on a closed file didn't raise an exception")
+        try:
+            with gzip.GzipFile(self.filename, "wb") as f:
+                1/0
+        except ZeroDivisionError:
+            pass
+        else:
+            self.fail("1/0 didn't raise an exception")
+
 def test_main(verbose=None):
     support.run_unittest(TestGzip)
 
index 16e1eddc4dff26f6a442330a5df1d0397da9d0e9..d29fcf8ea33cf359c150951384699be44c1085c4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -111,6 +111,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #3860: GzipFile and BZ2File now support the context manager protocol.
+
 - Issue #4867: Fixed a crash in ctypes when passing a string to a
   function without defining argtypes.
 
index 4bf31ee2f920d0f82810881faa82c6dc50e4fd38..c7cc7671bb1bc89d2dfbda3110eccc0e40b3aa7e 100644 (file)
@@ -1086,6 +1086,36 @@ BZ2File_close(BZ2FileObject *self)
        return ret;
 }
 
+PyDoc_STRVAR(BZ2File_enter_doc,
+"__enter__() -> self.");
+
+static PyObject *
+BZ2File_enter(BZ2FileObject *self)
+{
+       if (self->mode == MODE_CLOSED) {
+               PyErr_SetString(PyExc_ValueError,
+                       "I/O operation on closed file");
+               return NULL;
+       }
+       Py_INCREF(self);
+       return (PyObject *) self;
+}
+
+PyDoc_STRVAR(BZ2File_exit_doc,
+"__exit__(*excinfo) -> None.  Closes the file.");
+
+static PyObject *
+BZ2File_exit(BZ2FileObject *self, PyObject *args)
+{
+       PyObject *ret = PyObject_CallMethod((PyObject *) self, "close", NULL);
+       if (!ret)
+               /* If error occurred, pass through */
+               return NULL;
+       Py_DECREF(ret);
+       Py_RETURN_NONE;
+}
+
+
 static PyObject *BZ2File_getiter(BZ2FileObject *self);
 
 static PyMethodDef BZ2File_methods[] = {
@@ -1097,6 +1127,8 @@ static PyMethodDef BZ2File_methods[] = {
        {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
        {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
        {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
+       {"__enter__", (PyCFunction)BZ2File_enter, METH_NOARGS, BZ2File_enter_doc},
+       {"__exit__", (PyCFunction)BZ2File_exit, METH_VARARGS, BZ2File_exit_doc},
        {NULL,          NULL}           /* sentinel */
 };