Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 308705e

Browse files
committed
Merged revisions 68484-68485 via svnmerge from
svn+ssh://[email protected]/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. ........
1 parent ab86831 commit 308705e

5 files changed

Lines changed: 85 additions & 1 deletion

File tree

Lib/gzip.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,14 @@ def __next__(self):
472472
else:
473473
raise StopIteration
474474

475+
def __enter__(self):
476+
if self.fileobj is None:
477+
raise ValueError("I/O operation on closed GzipFile object")
478+
return self
479+
480+
def __exit__(self, *args):
481+
self.close()
482+
475483

476484
def _test():
477485
# Act like gzip; with -d, act like gunzip.

Lib/test/test_bz2.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,28 @@ def testBug1191043(self):
258258
bz2f.close()
259259
self.assertEqual(xlines, [b'Test'])
260260

261+
def testContextProtocol(self):
262+
# BZ2File supports the context management protocol
263+
f = None
264+
with BZ2File(self.filename, "wb") as f:
265+
f.write(b"xxx")
266+
f = BZ2File(self.filename, "rb")
267+
f.close()
268+
try:
269+
with f:
270+
pass
271+
except ValueError:
272+
pass
273+
else:
274+
self.fail("__enter__ on a closed file didn't raise an exception")
275+
try:
276+
with BZ2File(self.filename, "wb") as f:
277+
1/0
278+
except ZeroDivisionError:
279+
pass
280+
else:
281+
self.fail("1/0 didn't raise an exception")
282+
261283

262284
class BZ2CompressorTest(BaseTest):
263285
def testCompress(self):

Lib/test/test_gzip.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ def test_mtime(self):
166166
fWrite = gzip.GzipFile(self.filename, 'w', mtime = mtime)
167167
fWrite.write(data1)
168168
fWrite.close()
169-
170169
fRead = gzip.GzipFile(self.filename)
171170
dataRead = fRead.read()
172171
self.assertEqual(dataRead, data1)
@@ -223,6 +222,27 @@ def test_metadata(self):
223222

224223
fRead.close()
225224

225+
def test_with_open(self):
226+
# GzipFile supports the context management protocol
227+
with gzip.GzipFile(self.filename, "wb") as f:
228+
f.write(b"xxx")
229+
f = gzip.GzipFile(self.filename, "rb")
230+
f.close()
231+
try:
232+
with f:
233+
pass
234+
except ValueError:
235+
pass
236+
else:
237+
self.fail("__enter__ on a closed file didn't raise an exception")
238+
try:
239+
with gzip.GzipFile(self.filename, "wb") as f:
240+
1/0
241+
except ZeroDivisionError:
242+
pass
243+
else:
244+
self.fail("1/0 didn't raise an exception")
245+
226246
def test_main(verbose=None):
227247
support.run_unittest(TestGzip)
228248

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ Core and Builtins
111111
Library
112112
-------
113113

114+
- Issue #3860: GzipFile and BZ2File now support the context manager protocol.
115+
114116
- Issue #4867: Fixed a crash in ctypes when passing a string to a
115117
function without defining argtypes.
116118

Modules/bz2module.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,36 @@ BZ2File_close(BZ2FileObject *self)
10861086
return ret;
10871087
}
10881088

1089+
PyDoc_STRVAR(BZ2File_enter_doc,
1090+
"__enter__() -> self.");
1091+
1092+
static PyObject *
1093+
BZ2File_enter(BZ2FileObject *self)
1094+
{
1095+
if (self->mode == MODE_CLOSED) {
1096+
PyErr_SetString(PyExc_ValueError,
1097+
"I/O operation on closed file");
1098+
return NULL;
1099+
}
1100+
Py_INCREF(self);
1101+
return (PyObject *) self;
1102+
}
1103+
1104+
PyDoc_STRVAR(BZ2File_exit_doc,
1105+
"__exit__(*excinfo) -> None. Closes the file.");
1106+
1107+
static PyObject *
1108+
BZ2File_exit(BZ2FileObject *self, PyObject *args)
1109+
{
1110+
PyObject *ret = PyObject_CallMethod((PyObject *) self, "close", NULL);
1111+
if (!ret)
1112+
/* If error occurred, pass through */
1113+
return NULL;
1114+
Py_DECREF(ret);
1115+
Py_RETURN_NONE;
1116+
}
1117+
1118+
10891119
static PyObject *BZ2File_getiter(BZ2FileObject *self);
10901120

10911121
static PyMethodDef BZ2File_methods[] = {
@@ -1097,6 +1127,8 @@ static PyMethodDef BZ2File_methods[] = {
10971127
{"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
10981128
{"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
10991129
{"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1130+
{"__enter__", (PyCFunction)BZ2File_enter, METH_NOARGS, BZ2File_enter_doc},
1131+
{"__exit__", (PyCFunction)BZ2File_exit, METH_VARARGS, BZ2File_exit_doc},
11001132
{NULL, NULL} /* sentinel */
11011133
};
11021134

0 commit comments

Comments
 (0)