mirror of https://github.com/python/cpython
_warnings.warn_explicit(): try to import warnings
Issue #26592: _warnings.warn_explicit() now tries to import the warnings module (Python implementation) if the source parameter is set to be able to log the traceback where the source was allocated.
This commit is contained in:
parent
7bfa409ff8
commit
e98445a4de
|
@ -40,11 +40,11 @@ check_matched(PyObject *obj, PyObject *arg)
|
|||
A NULL return value can mean false or an error.
|
||||
*/
|
||||
static PyObject *
|
||||
get_warnings_attr(const char *attr)
|
||||
get_warnings_attr(const char *attr, int try_import)
|
||||
{
|
||||
static PyObject *warnings_str = NULL;
|
||||
PyObject *all_modules;
|
||||
PyObject *warnings_module;
|
||||
PyObject *warnings_module, *obj;
|
||||
int result;
|
||||
|
||||
if (warnings_str == NULL) {
|
||||
|
@ -53,15 +53,34 @@ get_warnings_attr(const char *attr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
all_modules = PyImport_GetModuleDict();
|
||||
result = PyDict_Contains(all_modules, warnings_str);
|
||||
if (result == -1 || result == 0)
|
||||
return NULL;
|
||||
|
||||
warnings_module = PyDict_GetItem(all_modules, warnings_str);
|
||||
if (!PyObject_HasAttrString(warnings_module, attr))
|
||||
/* don't try to import after the start of the Python finallization */
|
||||
if (try_import && _Py_Finalizing == NULL) {
|
||||
warnings_module = PyImport_Import(warnings_str);
|
||||
if (warnings_module == NULL) {
|
||||
/* Fallback to the C implementation if we cannot get
|
||||
the Python implementation */
|
||||
PyErr_Clear();
|
||||
return NULL;
|
||||
return PyObject_GetAttrString(warnings_module, attr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
all_modules = PyImport_GetModuleDict();
|
||||
result = PyDict_Contains(all_modules, warnings_str);
|
||||
if (result == -1 || result == 0)
|
||||
return NULL;
|
||||
|
||||
warnings_module = PyDict_GetItem(all_modules, warnings_str);
|
||||
Py_INCREF(warnings_module);
|
||||
}
|
||||
|
||||
if (!PyObject_HasAttrString(warnings_module, attr)) {
|
||||
Py_DECREF(warnings_module);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj = PyObject_GetAttrString(warnings_module, attr);
|
||||
Py_DECREF(warnings_module);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,7 +89,7 @@ get_once_registry(void)
|
|||
{
|
||||
PyObject *registry;
|
||||
|
||||
registry = get_warnings_attr("onceregistry");
|
||||
registry = get_warnings_attr("onceregistry", 0);
|
||||
if (registry == NULL) {
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
|
@ -87,7 +106,7 @@ get_default_action(void)
|
|||
{
|
||||
PyObject *default_action;
|
||||
|
||||
default_action = get_warnings_attr("defaultaction");
|
||||
default_action = get_warnings_attr("defaultaction", 0);
|
||||
if (default_action == NULL) {
|
||||
if (PyErr_Occurred()) {
|
||||
return NULL;
|
||||
|
@ -110,7 +129,7 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
|
|||
Py_ssize_t i;
|
||||
PyObject *warnings_filters;
|
||||
|
||||
warnings_filters = get_warnings_attr("filters");
|
||||
warnings_filters = get_warnings_attr("filters", 0);
|
||||
if (warnings_filters == NULL) {
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
|
@ -366,7 +385,10 @@ call_show_warning(PyObject *category, PyObject *text, PyObject *message,
|
|||
{
|
||||
PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;
|
||||
|
||||
show_fn = get_warnings_attr("_showwarnmsg");
|
||||
/* If the source parameter is set, try to get the Python implementation.
|
||||
The Python implementation is able to log the traceback where the source
|
||||
was allocated, whereas the C implementation doesnt. */
|
||||
show_fn = get_warnings_attr("_showwarnmsg", source != NULL);
|
||||
if (show_fn == NULL) {
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
|
@ -380,7 +402,7 @@ call_show_warning(PyObject *category, PyObject *text, PyObject *message,
|
|||
goto error;
|
||||
}
|
||||
|
||||
warnmsg_cls = get_warnings_attr("WarningMessage");
|
||||
warnmsg_cls = get_warnings_attr("WarningMessage", 0);
|
||||
if (warnmsg_cls == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"unable to get warnings.WarningMessage");
|
||||
|
|
Loading…
Reference in New Issue