From 33a5f2af59ddcf3f1b0447a8dbd0576fd78de303 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 21 Aug 2005 14:16:04 +0000 Subject: Fix BZ2File.(x)readlines() for files without a newline. --- Lib/test/test_bz2.py | 18 +++++++++++++++++- Misc/NEWS | 3 +++ Modules/bz2module.c | 39 +++++++++++++++++++++++++++++++-------- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index fc8213f..11a5c82 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -37,7 +37,7 @@ class BaseTest(unittest.TestCase): return bz2.decompress(data) class BZ2FileTest(BaseTest): - "Test MCRYPT type miscelaneous methods." + "Test BZ2File type miscellaneous methods." def setUp(self): self.filename = TESTFN @@ -245,6 +245,22 @@ class BZ2FileTest(BaseTest): self.assertEqual(f.tell(), len(self.DATA)) f.close() + def testBug1191043(self): + # readlines() for files containing no newline + data = 'BZh91AY&SY\xd9b\x89]\x00\x00\x00\x03\x80\x04\x00\x02\x00\x0c\x00 \x00!\x9ah3M\x13<]\xc9\x14\xe1BCe\x8a%t' + f = open(self.filename, "wb") + f.write(data) + f.close() + bz2f = BZ2File(self.filename) + lines = bz2f.readlines() + bz2f.close() + self.assertEqual(lines, ['Test']) + bz2f = BZ2File(self.filename) + xlines = bz2f.xreadlines() + bz2f.close() + self.assertEqual(lines, ['Test']) + + class BZ2CompressorTest(BaseTest): def testCompress(self): # "Test BZ2Compressor.compress()/flush()" diff --git a/Misc/NEWS b/Misc/NEWS index e3fbbab..8b4068e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1570,6 +1570,9 @@ Core and builtins Extension modules ----------------- +- Fix bz2.BZ2File.(x)readlines() for files containing one line without + newlines. + - Added socket.getservbyport(), and make the second argument in getservbyname() and getservbyport() optional. diff --git a/Modules/bz2module.c b/Modules/bz2module.c index b9874eb..4547815 100644 --- a/Modules/bz2module.c +++ b/Modules/bz2module.c @@ -22,6 +22,18 @@ static char __author__[] = Gustavo Niemeyer \n\ "; +/* Our very own off_t-like type, 64-bit if possible */ +/* copied from Objects/fileobject.c */ +#if !defined(HAVE_LARGEFILE_SUPPORT) +typedef off_t Py_off_t; +#elif SIZEOF_OFF_T >= 8 +typedef off_t Py_off_t; +#elif SIZEOF_FPOS_T >= 8 +typedef fpos_t Py_off_t; +#else +#error "Large file support, but neither off_t nor fpos_t is large enough." +#endif + #define BUF(v) PyString_AS_STRING((PyStringObject *)v) #define MODE_CLOSED 0 @@ -405,7 +417,9 @@ Util_ReadAhead(BZ2FileObject *f, int bufsize) Util_DropReadAhead(f); } if (f->mode == MODE_READ_EOF) { - return -1; + f->f_bufptr = f->f_buf; + f->f_bufend = f->f_buf; + return 0; } if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) { return -1; @@ -682,13 +696,13 @@ BZ2File_readlines(BZ2FileObject *self, PyObject *args) } totalread += nread; p = memchr(buffer+nfilled, '\n', nread); - if (p == NULL) { + if (!shortread && p == NULL) { /* Need a larger buffer to fit this line */ nfilled += nread; buffersize *= 2; if (buffersize > INT_MAX) { PyErr_SetString(PyExc_OverflowError, - "line is longer than a Python string can hold"); + "line is longer than a Python string can hold"); goto error; } if (big_buffer == NULL) { @@ -705,11 +719,11 @@ BZ2File_readlines(BZ2FileObject *self, PyObject *args) _PyString_Resize(&big_buffer, buffersize); buffer = PyString_AS_STRING(big_buffer); } - continue; + continue; } end = buffer+nfilled+nread; q = buffer; - do { + while (p != NULL) { /* Process complete lines */ p++; line = PyString_FromStringAndSize(q, p-q); @@ -721,7 +735,7 @@ BZ2File_readlines(BZ2FileObject *self, PyObject *args) goto error; q = p; p = memchr(q, '\n', end-q); - } while (p != NULL); + } /* Move the remaining incomplete line to the start */ nfilled = end-q; memmove(buffer, q, nfilled); @@ -962,7 +976,8 @@ static PyObject * BZ2File_seek(BZ2FileObject *self, PyObject *args) { int where = 0; - long offset; + PyObject *offobj; + Py_off_t offset; char small_buffer[SMALLCHUNK]; char *buffer = small_buffer; size_t buffersize = SMALLCHUNK; @@ -973,7 +988,15 @@ BZ2File_seek(BZ2FileObject *self, PyObject *args) int rewind = 0; PyObject *ret = NULL; - if (!PyArg_ParseTuple(args, "l|i:seek", &offset, &where)) + if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where)) + return NULL; +#if !defined(HAVE_LARGEFILE_SUPPORT) + offset = PyInt_AsLong(offobj); +#else + offset = PyLong_Check(offobj) ? + PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj); +#endif + if (PyErr_Occurred()) return NULL; ACQUIRE_LOCK(self); -- cgit v0.12