summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2005-08-21 14:16:04 (GMT)
committerGeorg Brandl <georg@python.org>2005-08-21 14:16:04 (GMT)
commit33a5f2af59ddcf3f1b0447a8dbd0576fd78de303 (patch)
treec3a2210fc27ba900882d74769b56bb4443325753
parentf755432f4141fb9f9885435c7ba2d2f6a17d03fe (diff)
downloadcpython-33a5f2af59ddcf3f1b0447a8dbd0576fd78de303.zip
cpython-33a5f2af59ddcf3f1b0447a8dbd0576fd78de303.tar.gz
cpython-33a5f2af59ddcf3f1b0447a8dbd0576fd78de303.tar.bz2
Fix BZ2File.(x)readlines() for files without a newline.
-rw-r--r--Lib/test/test_bz2.py18
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/bz2module.c39
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 <niemeyer@conectiva.com>\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);