summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/sys.rst13
-rw-r--r--Include/sysmodule.h6
-rw-r--r--Misc/NEWS4
-rw-r--r--Python/sysmodule.c82
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);
}