Commit cb6aab12 authored by Victor Stinner's avatar Victor Stinner

_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.
parent 38f47b8f
......@@ -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)
/* 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;
}
}
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;
}
warnings_module = PyDict_GetItem(all_modules, warnings_str);
if (!PyObject_HasAttrString(warnings_module, attr))
return NULL;
return PyObject_GetAttrString(warnings_module, attr);
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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment