mirror of https://github.com/python/cpython
bpo-30228: FileIO seek() and tell() set seekable (#1384)
FileIO.seek() and FileIO.tell() method now set the internal seekable attribute to avoid one syscall on open() (in buffered or text mode). The seekable property is now also more reliable since its value is set correctly on memory allocation failure.
This commit is contained in:
parent
1dae7450c6
commit
9997073736
|
@ -317,6 +317,9 @@ Extension Modules
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- bpo-30228: The seek() and tell() methods of io.FileIO now set the internal
|
||||||
|
seekable attribute to avoid one syscall on open() (in buffered or text mode).
|
||||||
|
|
||||||
- bpo-30190: unittest's assertAlmostEqual and assertNotAlmostEqual provide a
|
- bpo-30190: unittest's assertAlmostEqual and assertNotAlmostEqual provide a
|
||||||
better message in case of failure which includes the difference between
|
better message in case of failure which includes the difference between
|
||||||
left and right arguments. (patch by Giampaolo Rodola')
|
left and right arguments. (patch by Giampaolo Rodola')
|
||||||
|
|
|
@ -73,6 +73,9 @@ _Py_IDENTIFIER(name);
|
||||||
|
|
||||||
#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
|
#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence);
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyFileIO_closed(PyObject *self)
|
_PyFileIO_closed(PyObject *self)
|
||||||
{
|
{
|
||||||
|
@ -98,11 +101,6 @@ fileio_dealloc_warn(fileio *self, PyObject *source)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
portable_lseek(int fd, PyObject *posobj, int whence);
|
|
||||||
|
|
||||||
static PyObject *portable_lseek(int fd, PyObject *posobj, int whence);
|
|
||||||
|
|
||||||
/* Returns 0 on success, -1 with exception set on failure. */
|
/* Returns 0 on success, -1 with exception set on failure. */
|
||||||
static int
|
static int
|
||||||
internal_close(fileio *self)
|
internal_close(fileio *self)
|
||||||
|
@ -478,7 +476,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
|
||||||
/* For consistent behaviour, we explicitly seek to the
|
/* For consistent behaviour, we explicitly seek to the
|
||||||
end of file (otherwise, it might be done only on the
|
end of file (otherwise, it might be done only on the
|
||||||
first write()). */
|
first write()). */
|
||||||
PyObject *pos = portable_lseek(self->fd, NULL, 2);
|
PyObject *pos = portable_lseek(self, NULL, 2);
|
||||||
if (pos == NULL)
|
if (pos == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
Py_DECREF(pos);
|
Py_DECREF(pos);
|
||||||
|
@ -600,13 +598,14 @@ _io_FileIO_seekable_impl(fileio *self)
|
||||||
if (self->fd < 0)
|
if (self->fd < 0)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
if (self->seekable < 0) {
|
if (self->seekable < 0) {
|
||||||
PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR);
|
/* portable_lseek() sets the seekable attribute */
|
||||||
|
PyObject *pos = portable_lseek(self, NULL, SEEK_CUR);
|
||||||
|
assert(self->seekable >= 0);
|
||||||
if (pos == NULL) {
|
if (pos == NULL) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
self->seekable = 0;
|
}
|
||||||
} else {
|
else {
|
||||||
Py_DECREF(pos);
|
Py_DECREF(pos);
|
||||||
self->seekable = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PyBool_FromLong((long) self->seekable);
|
return PyBool_FromLong((long) self->seekable);
|
||||||
|
@ -865,9 +864,10 @@ _io_FileIO_write_impl(fileio *self, Py_buffer *b)
|
||||||
|
|
||||||
/* Cribbed from posix_lseek() */
|
/* Cribbed from posix_lseek() */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
portable_lseek(int fd, PyObject *posobj, int whence)
|
portable_lseek(fileio *self, PyObject *posobj, int whence)
|
||||||
{
|
{
|
||||||
Py_off_t pos, res;
|
Py_off_t pos, res;
|
||||||
|
int fd = self->fd;
|
||||||
|
|
||||||
#ifdef SEEK_SET
|
#ifdef SEEK_SET
|
||||||
/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
|
/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
|
||||||
|
@ -884,8 +884,9 @@ portable_lseek(int fd, PyObject *posobj, int whence)
|
||||||
}
|
}
|
||||||
#endif /* SEEK_SET */
|
#endif /* SEEK_SET */
|
||||||
|
|
||||||
if (posobj == NULL)
|
if (posobj == NULL) {
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if(PyFloat_Check(posobj)) {
|
if(PyFloat_Check(posobj)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
||||||
|
@ -909,6 +910,11 @@ portable_lseek(int fd, PyObject *posobj, int whence)
|
||||||
#endif
|
#endif
|
||||||
_Py_END_SUPPRESS_IPH
|
_Py_END_SUPPRESS_IPH
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
if (self->seekable < 0) {
|
||||||
|
self->seekable = (res >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return PyErr_SetFromErrno(PyExc_OSError);
|
return PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
|
||||||
|
@ -943,7 +949,7 @@ _io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence)
|
||||||
if (self->fd < 0)
|
if (self->fd < 0)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
|
|
||||||
return portable_lseek(self->fd, pos, whence);
|
return portable_lseek(self, pos, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
@ -961,7 +967,7 @@ _io_FileIO_tell_impl(fileio *self)
|
||||||
if (self->fd < 0)
|
if (self->fd < 0)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
|
|
||||||
return portable_lseek(self->fd, NULL, 1);
|
return portable_lseek(self, NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_FTRUNCATE
|
#ifdef HAVE_FTRUNCATE
|
||||||
|
@ -992,7 +998,7 @@ _io_FileIO_truncate_impl(fileio *self, PyObject *posobj)
|
||||||
|
|
||||||
if (posobj == Py_None || posobj == NULL) {
|
if (posobj == Py_None || posobj == NULL) {
|
||||||
/* Get the current position. */
|
/* Get the current position. */
|
||||||
posobj = portable_lseek(fd, NULL, 1);
|
posobj = portable_lseek(self, NULL, 1);
|
||||||
if (posobj == NULL)
|
if (posobj == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue