From 4a2b7a1b141fcbed6da81d942c9db776874c2fa9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 13 Aug 2010 14:03:48 +0000 Subject: Issue #9425: Create PyErr_WarnFormat() function Similar to PyErr_WarnEx() but use PyUnicode_FromFormatV() to format the warning message. Strip also some trailing spaces. --- Doc/c-api/exceptions.rst | 13 ++++++++++--- Include/warnings.h | 1 + Misc/NEWS | 5 ++++- Objects/moduleobject.c | 17 +++++++---------- Objects/typeobject.c | 11 ++++------- Objects/unicodeobject.c | 15 ++++++++------- Python/_warnings.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 7 files changed, 74 insertions(+), 34 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 619f0f6..fcbd50b 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -302,12 +302,12 @@ in various ways. There is a separate error indicator for each thread. use. -.. cfunction:: int PyErr_WarnEx(PyObject *category, char *message, int stacklevel) +.. cfunction:: int PyErr_WarnEx(PyObject *category, char *message, int stack_level) Issue a warning message. The *category* argument is a warning category (see - below) or *NULL*; the *message* argument is a message string. *stacklevel* is a + below) or *NULL*; the *message* argument is a message string. *stack_level* is a positive number giving a number of stack frames; the warning will be issued from - the currently executing line of code in that stack frame. A *stacklevel* of 1 + the currently executing line of code in that stack frame. A *stack_level* of 1 is the function calling :cfunc:`PyErr_WarnEx`, 2 is the function above that, and so forth. @@ -348,6 +348,13 @@ in various ways. There is a separate error indicator for each thread. described there. +.. cfunction:: int PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, const char *format, ...) + + Function similar to :cfunc:`PyErr_WarnEx`, but use + :cfunc:`PyUnicode_FromFormatV` to format the warning message. + + .. versionadded:: 3.2 + .. cfunction:: int PyErr_CheckSignals() .. index:: diff --git a/Include/warnings.h b/Include/warnings.h index f54eabd..c84cb9f 100644 --- a/Include/warnings.h +++ b/Include/warnings.h @@ -7,6 +7,7 @@ extern "C" { PyAPI_FUNC(PyObject*) _PyWarnings_Init(void); PyAPI_FUNC(int) PyErr_WarnEx(PyObject *, const char *, Py_ssize_t); +PyAPI_FUNC(int) PyErr_WarnFormat(PyObject *, Py_ssize_t, const char *, ...); PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *, const char *, int, const char *, PyObject *); diff --git a/Misc/NEWS b/Misc/NEWS index 4f6d3b3..dc3191f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 3.2 Alpha 2? Core and Builtins ----------------- +- Issue #9425: Create PyErr_WarnFormat() function, similar to PyErr_WarnEx() + but use PyUnicode_FromFormatV() to format the warning message. + - Issue #8530: Prevent stringlib fastsearch from reading beyond the front of an array. @@ -85,7 +88,7 @@ Library Thread-local objects involved in reference cycles will be deallocated timely by the cyclic GC, even if the underlying thread is still running. -- Issue #9452: Add read_file, read_string, and read_dict to the configparser +- Issue #9452: Add read_file, read_string, and read_dict to the configparser API; new source attribute to exceptions. - Issue #6231: Fix xml.etree.ElementInclude to include the tail of the diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 6c6eac1..7b8e1b6 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -56,10 +56,6 @@ PyModule_New(const char *name) return NULL; } -static char api_version_warning[] = -"Python C API version mismatch for module %.100s:\ - This Python has API version %d, module %.100s has version %d."; - PyObject * PyModule_Create2(struct PyModuleDef* module, int module_api_version) { @@ -79,12 +75,13 @@ PyModule_Create2(struct PyModuleDef* module, int module_api_version) } name = module->m_name; if (module_api_version != PYTHON_API_VERSION) { - char message[512]; - PyOS_snprintf(message, sizeof(message), - api_version_warning, name, - PYTHON_API_VERSION, name, - module_api_version); - if (PyErr_WarnEx(PyExc_RuntimeWarning, message, 1)) + int err; + err = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "Python C API version mismatch for module %.100s: " + "This Python has API version %d, module %.100s has version %d.", + name, + PYTHON_API_VERSION, name, module_api_version); + if (err) return NULL; } /* Make sure name is fully qualified. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 268a924..7bb6864 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3892,13 +3892,10 @@ PyType_Ready(PyTypeObject *type) tp_reserved) but not tp_richcompare. */ if (type->tp_reserved && !type->tp_richcompare) { int error; - char msg[240]; - PyOS_snprintf(msg, sizeof(msg), - "Type %.100s defines tp_reserved (formerly " - "tp_compare) but not tp_richcompare. " - "Comparisons may not behave as intended.", - type->tp_name); - error = PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1); + error = PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "Type %.100s defines tp_reserved (formerly tp_compare) " + "but not tp_richcompare. Comparisons may not behave as intended.", + type->tp_name); if (error == -1) goto error; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 849f33e..7c9b882 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -755,7 +755,7 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) char fmt[61]; /* should be enough for %0width.precisionlld */ const char *copy; - Py_VA_COPY(count, vargs); + Py_VA_COPY(count, vargs); /* step 1: count the number of %S/%R/%A/%s format specifications * (we call PyObject_Str()/PyObject_Repr()/PyObject_ASCII()/ * PyUnicode_DecodeUTF8() for these objects once during step 3 and put the @@ -1548,12 +1548,13 @@ PyObject *PyUnicode_AsEncodedString(PyObject *unicode, /* If the codec returns a buffer, raise a warning and convert to bytes */ if (PyByteArray_Check(v)) { - char msg[100]; + int error; PyObject *b; - PyOS_snprintf(msg, sizeof(msg), - "encoder %s returned buffer instead of bytes", - encoding); - if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) { + + error = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "encoder %s returned bytearray instead of bytes", + encoding); + if (error) { Py_DECREF(v); return NULL; } @@ -2279,7 +2280,7 @@ char utf8_code_length[256] = { illegal prefix. See RFC 3629 for details */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00-0F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, diff --git a/Python/_warnings.c b/Python/_warnings.c index 6067ce3..63bcbff 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -710,19 +710,17 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) /* Function to issue a warning message; may raise an exception. */ -int -PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) + +static int +warn_unicode(PyObject *category, PyObject *message, + Py_ssize_t stack_level) { PyObject *res; - PyObject *message = PyUnicode_FromString(text); - if (message == NULL) - return -1; if (category == NULL) category = PyExc_RuntimeWarning; res = do_warn(message, category, stack_level); - Py_DECREF(message); if (res == NULL) return -1; Py_DECREF(res); @@ -730,6 +728,42 @@ PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) return 0; } +int +PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, + const char *format, ...) +{ + int ret; + PyObject *message; + va_list vargs; + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + message = PyUnicode_FromFormatV(format, vargs); + if (message != NULL) { + ret = warn_unicode(category, message, stack_level); + Py_DECREF(message); + } + else + ret = -1; + va_end(vargs); + return ret; +} + +int +PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) +{ + int ret; + PyObject *message = PyUnicode_FromString(text); + if (message == NULL) + return -1; + ret = warn_unicode(category, message, stack_level); + Py_DECREF(message); + return ret; +} + /* PyErr_Warn is only for backwards compatability and will be removed. Use PyErr_WarnEx instead. */ -- cgit v0.12