Issue #9425: Create PyErr_WarnFormat() function

Similar to PyErr_WarnEx() but use PyUnicode_FromFormatV() to format the warning
message.

Strip also some trailing spaces.
This commit is contained in:
Victor Stinner 2010-08-13 14:03:48 +00:00
parent b4b8eb9163
commit 4a2b7a1b14
7 changed files with 74 additions and 34 deletions

View File

@ -302,12 +302,12 @@ in various ways. There is a separate error indicator for each thread.
use. 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 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 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, is the function calling :cfunc:`PyErr_WarnEx`, 2 is the function above that,
and so forth. and so forth.
@ -348,6 +348,13 @@ in various ways. There is a separate error indicator for each thread.
described there. 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() .. cfunction:: int PyErr_CheckSignals()
.. index:: .. index::

View File

@ -7,6 +7,7 @@ extern "C" {
PyAPI_FUNC(PyObject*) _PyWarnings_Init(void); PyAPI_FUNC(PyObject*) _PyWarnings_Init(void);
PyAPI_FUNC(int) PyErr_WarnEx(PyObject *, const char *, Py_ssize_t); 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, PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *, const char *, int,
const char *, PyObject *); const char *, PyObject *);

View File

@ -12,6 +12,9 @@ What's New in Python 3.2 Alpha 2?
Core and Builtins 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 - Issue #8530: Prevent stringlib fastsearch from reading beyond the front
of an array. of an array.
@ -85,7 +88,7 @@ Library
Thread-local objects involved in reference cycles will be deallocated Thread-local objects involved in reference cycles will be deallocated
timely by the cyclic GC, even if the underlying thread is still running. 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. API; new source attribute to exceptions.
- Issue #6231: Fix xml.etree.ElementInclude to include the tail of the - Issue #6231: Fix xml.etree.ElementInclude to include the tail of the

View File

@ -56,10 +56,6 @@ PyModule_New(const char *name)
return NULL; 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 * PyObject *
PyModule_Create2(struct PyModuleDef* module, int module_api_version) 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; name = module->m_name;
if (module_api_version != PYTHON_API_VERSION) { if (module_api_version != PYTHON_API_VERSION) {
char message[512]; int err;
PyOS_snprintf(message, sizeof(message), err = PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
api_version_warning, name, "Python C API version mismatch for module %.100s: "
PYTHON_API_VERSION, name, "This Python has API version %d, module %.100s has version %d.",
module_api_version); name,
if (PyErr_WarnEx(PyExc_RuntimeWarning, message, 1)) PYTHON_API_VERSION, name, module_api_version);
if (err)
return NULL; return NULL;
} }
/* Make sure name is fully qualified. /* Make sure name is fully qualified.

View File

@ -3892,13 +3892,10 @@ PyType_Ready(PyTypeObject *type)
tp_reserved) but not tp_richcompare. */ tp_reserved) but not tp_richcompare. */
if (type->tp_reserved && !type->tp_richcompare) { if (type->tp_reserved && !type->tp_richcompare) {
int error; int error;
char msg[240]; error = PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
PyOS_snprintf(msg, sizeof(msg), "Type %.100s defines tp_reserved (formerly tp_compare) "
"Type %.100s defines tp_reserved (formerly " "but not tp_richcompare. Comparisons may not behave as intended.",
"tp_compare) but not tp_richcompare. " type->tp_name);
"Comparisons may not behave as intended.",
type->tp_name);
error = PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1);
if (error == -1) if (error == -1)
goto error; goto error;
} }

View File

@ -755,7 +755,7 @@ PyUnicode_FromFormatV(const char *format, va_list vargs)
char fmt[61]; /* should be enough for %0width.precisionlld */ char fmt[61]; /* should be enough for %0width.precisionlld */
const char *copy; 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 /* step 1: count the number of %S/%R/%A/%s format specifications
* (we call PyObject_Str()/PyObject_Repr()/PyObject_ASCII()/ * (we call PyObject_Str()/PyObject_Repr()/PyObject_ASCII()/
* PyUnicode_DecodeUTF8() for these objects once during step 3 and put the * 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 the codec returns a buffer, raise a warning and convert to bytes */
if (PyByteArray_Check(v)) { if (PyByteArray_Check(v)) {
char msg[100]; int error;
PyObject *b; PyObject *b;
PyOS_snprintf(msg, sizeof(msg),
"encoder %s returned buffer instead of bytes", error = PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
encoding); "encoder %s returned bytearray instead of bytes",
if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) { encoding);
if (error) {
Py_DECREF(v); Py_DECREF(v);
return NULL; return NULL;
} }
@ -2279,7 +2280,7 @@ char utf8_code_length[256] = {
illegal prefix. See RFC 3629 for details */ 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, /* 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,
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,

View File

@ -710,19 +710,17 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
/* Function to issue a warning message; may raise an exception. */ /* 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 *res;
PyObject *message = PyUnicode_FromString(text);
if (message == NULL)
return -1;
if (category == NULL) if (category == NULL)
category = PyExc_RuntimeWarning; category = PyExc_RuntimeWarning;
res = do_warn(message, category, stack_level); res = do_warn(message, category, stack_level);
Py_DECREF(message);
if (res == NULL) if (res == NULL)
return -1; return -1;
Py_DECREF(res); Py_DECREF(res);
@ -730,6 +728,42 @@ PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
return 0; 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. /* PyErr_Warn is only for backwards compatability and will be removed.
Use PyErr_WarnEx instead. */ Use PyErr_WarnEx instead. */