diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 89ec8cbbbcd649..5e00700cdaa259 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -771,6 +771,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_restype_)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_showwarnmsg)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_shutdown)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_size)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_slotnames)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_strptime_datetime)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_swappedbytes_)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 62c3ee3ae2a0bd..78ad389c8c4320 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -260,6 +260,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(_restype_) STRUCT_FOR_ID(_showwarnmsg) STRUCT_FOR_ID(_shutdown) + STRUCT_FOR_ID(_size) STRUCT_FOR_ID(_slotnames) STRUCT_FOR_ID(_strptime_datetime) STRUCT_FOR_ID(_swappedbytes_) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 1defa39f816e78..05d27b40fd543f 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -769,6 +769,7 @@ extern "C" { INIT_ID(_restype_), \ INIT_ID(_showwarnmsg), \ INIT_ID(_shutdown), \ + INIT_ID(_size), \ INIT_ID(_slotnames), \ INIT_ID(_strptime_datetime), \ INIT_ID(_swappedbytes_), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index be9baa3eebecfc..b4c1329624e7fd 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -621,6 +621,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(_shutdown); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(_size); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(_slotnames); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 32698abac78d25..a4a28a17643f7f 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -238,7 +238,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, result = raw try: line_buffering = False - if buffering == 1 or buffering < 0 and raw.isatty(): + if buffering == 1 or buffering < 0 and getattr(raw, '_size', 0) == 0 and raw.isatty(): buffering = -1 line_buffering = True if buffering < 0: @@ -1571,6 +1571,7 @@ def __init__(self, file, mode='r', closefd=True, opener=None): self._blksize = getattr(fdfstat, 'st_blksize', 0) if self._blksize <= 1: self._blksize = DEFAULT_BUFFER_SIZE + self._size = fdfstat.st_size if _setmode: # don't translate newlines (\r\n <=> \n) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 173f5b55e5f732..8cf501fa383d64 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -209,6 +209,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, char rawmode[6], *m; int line_buffering, is_number, isatty = 0; + __int64_t size = 0; PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL, *path_or_fd = NULL; @@ -346,6 +347,16 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, /* buffering */ if (buffering < 0) { + PyObject *size_obj; + size_obj = PyObject_GetAttr(raw, &_Py_ID(_size)); + if (size_obj == NULL) + goto error; + size = PyLong_AsLongLong(size_obj); + Py_DECREF(size_obj); + if (size == -1 && PyErr_Occurred()) + goto error; + } + if (buffering < 0 && size == 0) { PyObject *res = PyObject_CallMethodNoArgs(raw, &_Py_ID(isatty)); if (res == NULL) goto error; diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 8a73ea0365b7a3..f3f0bf147124ed 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -72,6 +72,7 @@ typedef struct { unsigned int closefd : 1; char finalizing; unsigned int blksize; + __int64_t size; PyObject *weakreflist; PyObject *dict; } fileio; @@ -196,6 +197,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self->appending = 0; self->seekable = -1; self->blksize = 0; + self->size = 0; self->closefd = 1; self->weakreflist = NULL; } @@ -475,6 +477,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, if (fdfstat.st_blksize > 1) self->blksize = fdfstat.st_blksize; #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ + self->size = fdfstat.st_size; } #if defined(MS_WINDOWS) || defined(__CYGWIN__) @@ -1205,6 +1208,7 @@ static PyGetSetDef fileio_getsetlist[] = { static PyMemberDef fileio_members[] = { {"_blksize", Py_T_UINT, offsetof(fileio, blksize), 0}, + {"_size", T_UINT, offsetof(fileio, size), 0}, {"_finalizing", Py_T_BOOL, offsetof(fileio, finalizing), 0}, {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(fileio, weakreflist), Py_READONLY}, {"__dictoffset__", Py_T_PYSSIZET, offsetof(fileio, dict), Py_READONLY},