diff options
Diffstat (limited to 'Python/_warnings.c')
-rw-r--r-- | Python/_warnings.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/Python/_warnings.c b/Python/_warnings.c index d03b452..12b1021 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -378,15 +378,47 @@ warn_explicit(PyObject *category, PyObject *message, show_warning(filename, lineno, text, category, sourceline); } else { - PyObject *res; - - res = PyObject_CallFunctionObjArgs(show_fxn, message, category, + const char *msg = "functions overriding warnings.showwarning() " + "must support the 'line' argument"; + const char *text_char = PyUnicode_AsString(text); + + if (strcmp(msg, text_char) == 0) { + /* Prevent infinite recursion by using built-in implementation + of showwarning(). */ + show_warning(filename, lineno, text, category, sourceline); + } + else { + PyObject *check_fxn; + PyObject *defaults; + PyObject *res; + + if (PyMethod_Check(show_fxn)) + check_fxn = PyMethod_Function(show_fxn); + else if (PyFunction_Check(show_fxn)) + check_fxn = show_fxn; + else { + PyErr_SetString(PyExc_TypeError, + "warnings.showwarning() must be set to a " + "function or method"); + Py_DECREF(show_fxn); + goto cleanup; + } + + defaults = PyFunction_GetDefaults(check_fxn); + /* A proper implementation of warnings.showwarning() should + have at least two default arguments. */ + if ((defaults == NULL) || (PyTuple_Size(defaults) < 2)) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) < 0) + goto cleanup; + } + res = PyObject_CallFunctionObjArgs(show_fxn, message, category, filename, lineno_obj, NULL); - Py_DECREF(show_fxn); - Py_XDECREF(res); - if (res == NULL) - goto cleanup; + Py_DECREF(show_fxn); + Py_XDECREF(res); + if (res == NULL) + goto cleanup; + } } } else /* if (rc == -1) */ |