[Python-checkins] r68484 - in python/trunk: Lib/gzip.py Lib/test/test_bz2.py Lib/test/test_gzip.py Modules/bz2module.c

antoine.pitrou python-checkins at python.org
Sat Jan 10 17:13:45 CET 2009


Author: antoine.pitrou
Date: Sat Jan 10 17:13:45 2009
New Revision: 68484

Log:
Issue #3860: GzipFile and BZ2File now support the context manager protocol.



Modified:
   python/trunk/Lib/gzip.py
   python/trunk/Lib/test/test_bz2.py
   python/trunk/Lib/test/test_gzip.py
   python/trunk/Modules/bz2module.c

Modified: python/trunk/Lib/gzip.py
==============================================================================
--- python/trunk/Lib/gzip.py	(original)
+++ python/trunk/Lib/gzip.py	Sat Jan 10 17:13:45 2009
@@ -454,6 +454,14 @@
         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.

Modified: python/trunk/Lib/test/test_bz2.py
==============================================================================
--- python/trunk/Lib/test/test_bz2.py	(original)
+++ python/trunk/Lib/test/test_bz2.py	Sat Jan 10 17:13:45 2009
@@ -284,6 +284,28 @@
         bz2f.close()
         self.assertEqual(xlines, ['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):

Modified: python/trunk/Lib/test/test_gzip.py
==============================================================================
--- python/trunk/Lib/test/test_gzip.py	(original)
+++ python/trunk/Lib/test/test_gzip.py	Sat Jan 10 17:13:45 2009
@@ -166,7 +166,6 @@
         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)
@@ -222,6 +221,27 @@
 
         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):
     test_support.run_unittest(TestGzip)
 

Modified: python/trunk/Modules/bz2module.c
==============================================================================
--- python/trunk/Modules/bz2module.c	(original)
+++ python/trunk/Modules/bz2module.c	Sat Jan 10 17:13:45 2009
@@ -1201,6 +1201,36 @@
 	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[] = {
@@ -1213,6 +1243,8 @@
 	{"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 */
 };
 


More information about the Python-checkins mailing list