]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-109611: Add convenient C API function _PyFile_Flush() (GH-109612)
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 23 Sep 2023 06:35:30 +0000 (09:35 +0300)
committerGitHub <noreply@github.com>
Sat, 23 Sep 2023 06:35:30 +0000 (09:35 +0300)
Include/internal/pycore_fileutils.h
Modules/_io/bufferedio.c
Modules/_io/iobase.c
Modules/_io/textio.c
Modules/_threadmodule.c
Modules/faulthandler.c
Objects/fileobject.c
Python/bltinmodule.c
Python/errors.c
Python/pylifecycle.c
Python/pythonrun.c

index 9236e5907a48d58090f5dbac86d2e031724ab276..2f89da2c6ecd916a0f39e266cd1f72b549ef0d26 100644 (file)
@@ -318,6 +318,8 @@ PyAPI_FUNC(int) _PyLong_FileDescriptor_Converter(PyObject *, void *);
 // Export for test_peg_generator
 PyAPI_FUNC(char*) _Py_UniversalNewlineFgetsWithSize(char *, int, FILE*, PyObject *, size_t*);
 
+extern int _PyFile_Flush(PyObject *);
+
 #ifdef __cplusplus
 }
 #endif
index 0983a7bd151f409024489f9a0ffada06d5ca9ace..e8caf9f0df6dbf2a4280c51d1f2756aa4d5a6746 100644 (file)
@@ -553,17 +553,14 @@ _io__Buffered_close_impl(buffered *self)
     }
     /* flush() will most probably re-take the lock, so drop it first */
     LEAVE_BUFFERED(self)
-    res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
+    r = _PyFile_Flush((PyObject *)self);
     if (!ENTER_BUFFERED(self)) {
         return NULL;
     }
     PyObject *exc = NULL;
-    if (res == NULL) {
+    if (r < 0) {
         exc = PyErr_GetRaisedException();
     }
-    else {
-        Py_DECREF(res);
-    }
 
     res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close));
 
@@ -593,12 +590,11 @@ static PyObject *
 _io__Buffered_detach_impl(buffered *self)
 /*[clinic end generated code: output=dd0fc057b8b779f7 input=482762a345cc9f44]*/
 {
-    PyObject *raw, *res;
+    PyObject *raw;
     CHECK_INITIALIZED(self)
-    res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
-    if (res == NULL)
+    if (_PyFile_Flush((PyObject *)self) < 0) {
         return NULL;
-    Py_DECREF(res);
+    }
     raw = self->raw;
     self->raw = NULL;
     self->detached = 1;
index 78f0f949b68c06c11a7ee7cdd34d9c8b4b3e2632..4da8e5bd572d745214ed080ccbe7d383716daeee 100644 (file)
@@ -265,7 +265,7 @@ static PyObject *
 _io__IOBase_close_impl(PyObject *self)
 /*[clinic end generated code: output=63c6a6f57d783d6d input=f4494d5c31dbc6b7]*/
 {
-    int rc, closed = iobase_is_closed(self);
+    int rc1, rc2, closed = iobase_is_closed(self);
 
     if (closed < 0) {
         return NULL;
@@ -274,19 +274,14 @@ _io__IOBase_close_impl(PyObject *self)
         Py_RETURN_NONE;
     }
 
-    PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(flush));
-
+    rc1 = _PyFile_Flush(self);
     PyObject *exc = PyErr_GetRaisedException();
-    rc = PyObject_SetAttr(self, &_Py_ID(__IOBase_closed), Py_True);
+    rc2 = PyObject_SetAttr(self, &_Py_ID(__IOBase_closed), Py_True);
     _PyErr_ChainExceptions1(exc);
-    if (rc < 0) {
-        Py_CLEAR(res);
-    }
-
-    if (res == NULL)
+    if (rc1 < 0 || rc2 < 0) {
         return NULL;
+    }
 
-    Py_DECREF(res);
     Py_RETURN_NONE;
 }
 
index 91b677bde77dde1e8b3b4476aa1ddb34d41ecbca..10ef8a803c50fdee8c204c186b36003335f4fda0 100644 (file)
@@ -1368,11 +1368,9 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding,
         return NULL;
     }
 
-    PyObject *res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
-    if (res == NULL) {
+    if (_PyFile_Flush((PyObject *)self) < 0) {
         return NULL;
     }
-    Py_DECREF(res);
     self->b2cratio = 0;
 
     if (newline_obj != NULL && set_newline(self, newline) < 0) {
@@ -1508,12 +1506,11 @@ static PyObject *
 _io_TextIOWrapper_detach_impl(textio *self)
 /*[clinic end generated code: output=7ba3715cd032d5f2 input=e5a71fbda9e1d9f9]*/
 {
-    PyObject *buffer, *res;
+    PyObject *buffer;
     CHECK_ATTACHED(self);
-    res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
-    if (res == NULL)
+    if (_PyFile_Flush((PyObject *)self) < 0) {
         return NULL;
-    Py_DECREF(res);
+    }
     buffer = self->buffer;
     self->buffer = NULL;
     self->detached = 1;
@@ -1713,10 +1710,9 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
     }
 
     if (needflush) {
-        ret = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(flush));
-        if (ret == NULL)
+        if (_PyFile_Flush(self->buffer) < 0) {
             return NULL;
-        Py_DECREF(ret);
+        }
     }
 
     textiowrapper_set_decoded_chars(self, NULL);
@@ -2502,10 +2498,9 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence)
             goto fail;
         }
 
-        res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
-        if (res == NULL)
+        if (_PyFile_Flush((PyObject *)self) < 0) {
             goto fail;
-        Py_DECREF(res);
+        }
 
         textiowrapper_set_decoded_chars(self, NULL);
         Py_CLEAR(self->snapshot);
@@ -2550,10 +2545,9 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence)
         goto fail;
     }
 
-    res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
-    if (res == NULL)
+    if (_PyFile_Flush((PyObject *)self) < 0) {
         goto fail;
-    Py_DECREF(res);
+    }
 
     /* The strategy of seek() is to go back to the safe start point
      * and replay the effect of read(chars_to_skip) from there.
@@ -2677,10 +2671,9 @@ _io_TextIOWrapper_tell_impl(textio *self)
 
     if (_textiowrapper_writeflush(self) < 0)
         return NULL;
-    res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
-    if (res == NULL)
+    if (_PyFile_Flush((PyObject *)self) < 0) {
         goto fail;
-    Py_DECREF(res);
+    }
 
     posobj = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(tell));
     if (posobj == NULL)
@@ -2885,14 +2878,11 @@ static PyObject *
 _io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos)
 /*[clinic end generated code: output=90ec2afb9bb7745f input=56ec8baa65aea377]*/
 {
-    PyObject *res;
-
     CHECK_ATTACHED(self)
 
-    res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
-    if (res == NULL)
+    if (_PyFile_Flush((PyObject *)self) < 0) {
         return NULL;
-    Py_DECREF(res);
+    }
 
     return PyObject_CallMethodOneArg(self->buffer, &_Py_ID(truncate), pos);
 }
@@ -3076,13 +3066,9 @@ _io_TextIOWrapper_close_impl(textio *self)
                 PyErr_Clear();
             }
         }
-        res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
-        if (res == NULL) {
+        if (_PyFile_Flush((PyObject *)self) < 0) {
             exc = PyErr_GetRaisedException();
         }
-        else {
-            Py_DECREF(res);
-        }
 
         res = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(close));
         if (exc != NULL) {
index 7692bacccc4909c4fcb62a9756fd6a8db49d6ea7..9c915488f6e0de3048b9600a55a8248b6ab27d41 100644 (file)
@@ -1497,11 +1497,9 @@ thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
     _PyErr_Display(file, exc_type, exc_value, exc_traceback);
 
     /* Call file.flush() */
-    PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
-    if (!res) {
+    if (_PyFile_Flush(file) < 0) {
         return -1;
     }
-    Py_DECREF(res);
 
     return 0;
 }
index f05cdd9a37f8a4c1ebb8456614a84b51268993ca..b051c71b3ade9be4be14ddd7c762ba7fb9b5653a 100644 (file)
@@ -146,10 +146,7 @@ faulthandler_get_fileno(PyObject **file_ptr)
         return -1;
     }
 
-    result = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
-    if (result != NULL)
-        Py_DECREF(result);
-    else {
+    if (_PyFile_Flush(file) < 0) {
         /* ignore flush() error */
         PyErr_Clear();
     }
index 9c240250218838112d474db0925d1777542096dc..0cf2b47c3b3ae7d5f6bcda040ee08ab72c89886f 100644 (file)
@@ -529,6 +529,18 @@ PyFile_OpenCode(const char *utf8path)
 }
 
 
+int
+_PyFile_Flush(PyObject *file)
+{
+    PyObject *tmp = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
+    if (tmp == NULL) {
+        return -1;
+    }
+    Py_DECREF(tmp);
+    return 0;
+}
+
+
 #ifdef __cplusplus
 }
 #endif
index 8e234e085f16c91b636965dd7008ad2e54739113..69056bf23f4058864a0e218762355888170b8a67 100644 (file)
@@ -2083,11 +2083,9 @@ builtin_print_impl(PyObject *module, PyObject *args, PyObject *sep,
     }
 
     if (flush) {
-        PyObject *tmp = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
-        if (tmp == NULL) {
+        if (_PyFile_Flush(file) < 0) {
             return NULL;
         }
-        Py_DECREF(tmp);
     }
 
     Py_RETURN_NONE;
@@ -2146,11 +2144,9 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
     }
 
     /* First of all, flush stderr */
-    tmp = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush));
-    if (tmp == NULL)
+    if (_PyFile_Flush(ferr) < 0) {
         PyErr_Clear();
-    else
-        Py_DECREF(tmp);
+    }
 
     /* We should only use (GNU) readline if Python's sys.stdin and
        sys.stdout are the same as C's stdin and stdout, because we
@@ -2218,11 +2214,9 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
         if (stdin_errors_str == NULL) {
             goto _readline_errors;
         }
-        tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));
-        if (tmp == NULL)
+        if (_PyFile_Flush(fout) < 0) {
             PyErr_Clear();
-        else
-            Py_DECREF(tmp);
+        }
         if (prompt != NULL) {
             /* We have a prompt, encode it as stdout would */
             const char *stdout_encoding_str, *stdout_errors_str;
@@ -2325,11 +2319,9 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
         if (PyFile_WriteObject(prompt, fout, Py_PRINT_RAW) != 0)
             return NULL;
     }
-    tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));
-    if (tmp == NULL)
+    if (_PyFile_Flush(fout) < 0) {
         PyErr_Clear();
-    else
-        Py_DECREF(tmp);
+    }
     return PyFile_GetLine(fin, -1);
 }
 
index e6fa15f92b5315dfbd4971149823d267df392472..b05b3ef1dda8fe9593d0bd1816e85ac42dd857e6 100644 (file)
@@ -1513,11 +1513,9 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,
     }
 
     /* Explicitly call file.flush() */
-    PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
-    if (!res) {
+    if (_PyFile_Flush(file) < 0) {
         return -1;
     }
-    Py_DECREF(res);
 
     return 0;
 }
index 480001538540bb7f3514a9b038610a8f886d5456..aec8da10249d21d5103988575f48735459e0fcf3 100644 (file)
@@ -1639,27 +1639,20 @@ flush_std_files(void)
     PyThreadState *tstate = _PyThreadState_GET();
     PyObject *fout = _PySys_GetAttr(tstate, &_Py_ID(stdout));
     PyObject *ferr = _PySys_GetAttr(tstate, &_Py_ID(stderr));
-    PyObject *tmp;
     int status = 0;
 
     if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
-        tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));
-        if (tmp == NULL) {
+        if (_PyFile_Flush(fout) < 0) {
             PyErr_WriteUnraisable(fout);
             status = -1;
         }
-        else
-            Py_DECREF(tmp);
     }
 
     if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
-        tmp = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush));
-        if (tmp == NULL) {
+        if (_PyFile_Flush(ferr) < 0) {
             PyErr_Clear();
             status = -1;
         }
-        else
-            Py_DECREF(tmp);
     }
 
     return status;
@@ -2632,13 +2625,9 @@ _Py_FatalError_PrintExc(PyThreadState *tstate)
     Py_DECREF(exc);
 
     /* sys.stderr may be buffered: call sys.stderr.flush() */
-    PyObject *res = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush));
-    if (res == NULL) {
+    if (_PyFile_Flush(ferr) < 0) {
         _PyErr_Clear(tstate);
     }
-    else {
-        Py_DECREF(res);
-    }
 
     return has_tb;
 }
index e3d03a8c95d767ada9dd706da21f99f440d8ead4..81ab78e95ab68c48461ea4c9d2ebfc575ca737d5 100644 (file)
@@ -1562,14 +1562,10 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb)
     Py_XDECREF(ctx.seen);
 
     /* Call file.flush() */
-    PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
-    if (!res) {
+    if (_PyFile_Flush(file) < 0) {
         /* Silently ignore file.flush() error */
         PyErr_Clear();
     }
-    else {
-        Py_DECREF(res);
-    }
 }
 
 void
@@ -1674,11 +1670,7 @@ flush_io_stream(PyThreadState *tstate, PyObject *name)
 {
     PyObject *f = _PySys_GetAttr(tstate, name);
     if (f != NULL) {
-        PyObject *r = PyObject_CallMethodNoArgs(f, &_Py_ID(flush));
-        if (r) {
-            Py_DECREF(r);
-        }
-        else {
+        if (_PyFile_Flush(f) < 0) {
             PyErr_Clear();
         }
     }