Skip to content

Commit

Permalink
pythongh-109611: Add convenient C API function _PyFile_Flush() (pytho…
Browse files Browse the repository at this point in the history
  • Loading branch information
serhiy-storchaka authored Sep 23, 2023
1 parent 92af0cc commit b8d1744
Show file tree
Hide file tree
Showing 11 changed files with 54 additions and 97 deletions.
2 changes: 2 additions & 0 deletions Include/internal/pycore_fileutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 5 additions & 9 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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;
Expand Down
15 changes: 5 additions & 10 deletions Modules/_io/iobase.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down
44 changes: 15 additions & 29 deletions Modules/_io/textio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 1 addition & 3 deletions Modules/_threadmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
5 changes: 1 addition & 4 deletions Modules/faulthandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
12 changes: 12 additions & 0 deletions Objects/fileobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
22 changes: 7 additions & 15 deletions Python/bltinmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down
4 changes: 1 addition & 3 deletions Python/errors.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
17 changes: 3 additions & 14 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
12 changes: 2 additions & 10 deletions Python/pythonrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
}
Expand Down

0 comments on commit b8d1744

Please sign in to comment.