From 79766636b6fbc7e01af160008df9cd31112716d6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 16 Aug 2010 17:36:42 +0000 Subject: Issue #9599: Create PySys_FormatStdout() and PySys_FormatStderr() Write a message formatted by PyUnicode_FromFormatV() to sys.stdout and sys.stderr. --- Doc/c-api/sys.rst | 13 ++++++++- Include/sysmodule.h | 6 ++-- Misc/NEWS | 4 +++ Python/sysmodule.c | 82 +++++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 87 insertions(+), 18 deletions(-) diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst index bc4cbae..d4d2795 100644 --- a/Doc/c-api/sys.rst +++ b/Doc/c-api/sys.rst @@ -109,8 +109,19 @@ accessible to C code. They all work with the current interpreter thread's .. cfunction:: void PySys_WriteStderr(const char *format, ...) - As above, but write to :data:`sys.stderr` or *stderr* instead. + As :cfunc:`PySys_WriteStdout`, but write to :data:`sys.stderr` or *stderr* + instead. +.. cfunction:: void PySys_FormatStdout(const char *format, ...) + + Function similar to PySys_WriteStdout() but format the message using + :cfunc:`PyUnicode_FromFormatV` and don't truncate the message to an + arbitrary length. + +.. cfunction:: void PySys_FormatStderr(const char *format, ...) + + As :cfunc:`PySys_FormatStdout`, but write to :data:`sys.stderr` or *stderr* + instead. .. _processcontrol: diff --git a/Include/sysmodule.h b/Include/sysmodule.h index 786d46a..e43f378 100644 --- a/Include/sysmodule.h +++ b/Include/sysmodule.h @@ -14,9 +14,11 @@ PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); PyAPI_FUNC(void) PySys_SetPath(const wchar_t *); PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) - Py_GCC_ATTRIBUTE((format(printf, 1, 2))); + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...) - Py_GCC_ATTRIBUTE((format(printf, 1, 2))); + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); +PyAPI_FUNC(void) PySys_FormatStdout(const char *format, ...); +PyAPI_FUNC(void) PySys_FormatStderr(const char *format, ...); PyAPI_DATA(PyObject *) _PySys_TraceFunc, *_PySys_ProfileFunc; diff --git a/Misc/NEWS b/Misc/NEWS index 9ad66f5..7deedeb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,10 @@ What's New in Python 3.2 Alpha 2? Core and Builtins ----------------- +- Issue #9599: Create PySys_FormatStdout() and PySys_FormatStderr() functions + to write a message formatted by PyUnicode_FromFormatV() to sys.stdout and + sys.stderr. + - Issue #9542: Create PyUnicode_FSDecoder() function, a ParseTuple converter: decode bytes objects to unicode using PyUnicode_DecodeFSDefaultAndSize(); str objects are output as-is. diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 61c9b1e..7bf2c4c 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1834,18 +1834,14 @@ PySys_SetArgv(int argc, wchar_t **argv) PyErr_CheckSignals(): avoid the call to PyObject_Str(). */ static int -sys_pyfile_write(const char *text, PyObject *file) +sys_pyfile_write_unicode(PyObject *unicode, PyObject *file) { - PyObject *unicode = NULL, *writer = NULL, *args = NULL, *result = NULL; + PyObject *writer = NULL, *args = NULL, *result = NULL; int err; if (file == NULL) return -1; - unicode = PyUnicode_FromString(text); - if (unicode == NULL) - goto error; - writer = PyObject_GetAttrString(file, "write"); if (writer == NULL) goto error; @@ -1865,13 +1861,29 @@ sys_pyfile_write(const char *text, PyObject *file) error: err = -1; finally: - Py_XDECREF(unicode); Py_XDECREF(writer); Py_XDECREF(args); Py_XDECREF(result); return err; } +static int +sys_pyfile_write(const char *text, PyObject *file) +{ + PyObject *unicode = NULL; + int err; + + if (file == NULL) + return -1; + + unicode = PyUnicode_FromString(text); + if (unicode == NULL) + return -1; + + err = sys_pyfile_write_unicode(unicode, file); + Py_DECREF(unicode); + return err; +} /* APIs to write to sys.stdout or sys.stderr using a printf-like interface. Adapted from code submitted by Just van Rossum. @@ -1884,8 +1896,8 @@ finally: no exceptions are raised. PyErr_CheckSignals() is not called to avoid the execution of the Python - signal handlers: they may raise a new exception whereas mywrite() ignores - all exceptions. + signal handlers: they may raise a new exception whereas sys_write() + ignores all exceptions. Both take a printf-style format string as their first argument followed by a variable length argument list determined by the format string. @@ -1902,7 +1914,7 @@ finally: */ static void -mywrite(char *name, FILE *fp, const char *format, va_list va) +sys_write(char *name, FILE *fp, const char *format, va_list va) { PyObject *file; PyObject *error_type, *error_value, *error_traceback; @@ -1918,10 +1930,8 @@ mywrite(char *name, FILE *fp, const char *format, va_list va) } if (written < 0 || (size_t)written >= sizeof(buffer)) { const char *truncated = "... truncated"; - if (sys_pyfile_write(truncated, file) != 0) { - PyErr_Clear(); + if (sys_pyfile_write(truncated, file) != 0) fputs(truncated, fp); - } } PyErr_Restore(error_type, error_value, error_traceback); } @@ -1932,7 +1942,7 @@ PySys_WriteStdout(const char *format, ...) va_list va; va_start(va, format); - mywrite("stdout", stdout, format, va); + sys_write("stdout", stdout, format, va); va_end(va); } @@ -1942,6 +1952,48 @@ PySys_WriteStderr(const char *format, ...) va_list va; va_start(va, format); - mywrite("stderr", stderr, format, va); + sys_write("stderr", stderr, format, va); + va_end(va); +} + +static void +sys_format(char *name, FILE *fp, const char *format, va_list va) +{ + PyObject *file, *message; + PyObject *error_type, *error_value, *error_traceback; + char *utf8; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); + file = PySys_GetObject(name); + message = PyUnicode_FromFormatV(format, va); + if (message != NULL) { + if (sys_pyfile_write_unicode(message, file) != 0) { + PyErr_Clear(); + utf8 = _PyUnicode_AsString(message); + if (utf8 != NULL) + fputs(utf8, fp); + } + Py_DECREF(message); + } + PyErr_Restore(error_type, error_value, error_traceback); +} + +void +PySys_FormatStdout(const char *format, ...) +{ + va_list va; + + va_start(va, format); + sys_format("stdout", stdout, format, va); + va_end(va); +} + +void +PySys_FormatStderr(const char *format, ...) +{ + va_list va; + + va_start(va, format); + sys_format("stderr", stderr, format, va); va_end(va); } -- cgit v0.12