diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/tools/python3/src/Python/_warnings.c | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/python3/src/Python/_warnings.c')
-rw-r--r-- | contrib/tools/python3/src/Python/_warnings.c | 2262 |
1 files changed, 1131 insertions, 1131 deletions
diff --git a/contrib/tools/python3/src/Python/_warnings.c b/contrib/tools/python3/src/Python/_warnings.c index 91a78fe72b..99f50a1443 100644 --- a/contrib/tools/python3/src/Python/_warnings.c +++ b/contrib/tools/python3/src/Python/_warnings.c @@ -1,23 +1,23 @@ -#include "Python.h" +#include "Python.h" #include "pycore_initconfig.h" #include "pycore_interp.h" // PyInterpreterState.warnings #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() #include "frameobject.h" // PyFrame_GetBack() -#include "clinic/_warnings.c.h" - -#define MODULE_NAME "_warnings" - -PyDoc_STRVAR(warnings__doc__, -MODULE_NAME " provides basic warning filtering support.\n" -"It is a helper module to speed up interpreter start-up."); - -_Py_IDENTIFIER(stderr); -#ifndef Py_DEBUG -_Py_IDENTIFIER(default); -_Py_IDENTIFIER(ignore); -#endif - +#include "clinic/_warnings.c.h" + +#define MODULE_NAME "_warnings" + +PyDoc_STRVAR(warnings__doc__, +MODULE_NAME " provides basic warning filtering support.\n" +"It is a helper module to speed up interpreter start-up."); + +_Py_IDENTIFIER(stderr); +#ifndef Py_DEBUG +_Py_IDENTIFIER(default); +_Py_IDENTIFIER(ignore); +#endif + /*************************************************************************/ @@ -116,7 +116,7 @@ init_filters(void) } /* Initialize the given warnings module state. */ -static int +static int warnings_init_state(WarningsState *st) { if (st->filters == NULL) { @@ -153,638 +153,638 @@ error: /*************************************************************************/ static int -check_matched(PyObject *obj, PyObject *arg) -{ - PyObject *result; - _Py_IDENTIFIER(match); - int rc; - - /* A 'None' filter always matches */ - if (obj == Py_None) - return 1; - - /* An internal plain text default filter must match exactly */ - if (PyUnicode_CheckExact(obj)) { - int cmp_result = PyUnicode_Compare(obj, arg); - if (cmp_result == -1 && PyErr_Occurred()) { - return -1; - } - return !cmp_result; - } - - /* Otherwise assume a regex filter and call its match() method */ +check_matched(PyObject *obj, PyObject *arg) +{ + PyObject *result; + _Py_IDENTIFIER(match); + int rc; + + /* A 'None' filter always matches */ + if (obj == Py_None) + return 1; + + /* An internal plain text default filter must match exactly */ + if (PyUnicode_CheckExact(obj)) { + int cmp_result = PyUnicode_Compare(obj, arg); + if (cmp_result == -1 && PyErr_Occurred()) { + return -1; + } + return !cmp_result; + } + + /* Otherwise assume a regex filter and call its match() method */ result = _PyObject_CallMethodIdOneArg(obj, &PyId_match, arg); - if (result == NULL) - return -1; - - rc = PyObject_IsTrue(result); - Py_DECREF(result); - return rc; -} - -/* - Returns a new reference. - A NULL return value can mean false or an error. -*/ -static PyObject * -get_warnings_attr(_Py_Identifier *attr_id, int try_import) -{ - PyObject *warnings_str; - PyObject *warnings_module, *obj; - _Py_IDENTIFIER(warnings); - - warnings_str = _PyUnicode_FromId(&PyId_warnings); - if (warnings_str == NULL) { - return NULL; - } - - /* don't try to import after the start of the Python finallization */ - if (try_import && !_Py_IsFinalizing()) { - warnings_module = PyImport_Import(warnings_str); - if (warnings_module == NULL) { - /* Fallback to the C implementation if we cannot get - the Python implementation */ - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - PyErr_Clear(); - } - return NULL; - } - } - else { - /* if we're so late into Python finalization that the module dict is - gone, then we can't even use PyImport_GetModule without triggering - an interpreter abort. - */ + if (result == NULL) + return -1; + + rc = PyObject_IsTrue(result); + Py_DECREF(result); + return rc; +} + +/* + Returns a new reference. + A NULL return value can mean false or an error. +*/ +static PyObject * +get_warnings_attr(_Py_Identifier *attr_id, int try_import) +{ + PyObject *warnings_str; + PyObject *warnings_module, *obj; + _Py_IDENTIFIER(warnings); + + warnings_str = _PyUnicode_FromId(&PyId_warnings); + if (warnings_str == NULL) { + return NULL; + } + + /* don't try to import after the start of the Python finallization */ + if (try_import && !_Py_IsFinalizing()) { + warnings_module = PyImport_Import(warnings_str); + if (warnings_module == NULL) { + /* Fallback to the C implementation if we cannot get + the Python implementation */ + if (PyErr_ExceptionMatches(PyExc_ImportError)) { + PyErr_Clear(); + } + return NULL; + } + } + else { + /* if we're so late into Python finalization that the module dict is + gone, then we can't even use PyImport_GetModule without triggering + an interpreter abort. + */ if (!_PyInterpreterState_GET()->modules) { - return NULL; - } - warnings_module = PyImport_GetModule(warnings_str); - if (warnings_module == NULL) - return NULL; - } - - (void)_PyObject_LookupAttrId(warnings_module, attr_id, &obj); - Py_DECREF(warnings_module); - return obj; -} - - -static PyObject * + return NULL; + } + warnings_module = PyImport_GetModule(warnings_str); + if (warnings_module == NULL) + return NULL; + } + + (void)_PyObject_LookupAttrId(warnings_module, attr_id, &obj); + Py_DECREF(warnings_module); + return obj; +} + + +static PyObject * get_once_registry(WarningsState *st) -{ - PyObject *registry; - _Py_IDENTIFIER(onceregistry); - - registry = get_warnings_attr(&PyId_onceregistry, 0); - if (registry == NULL) { - if (PyErr_Occurred()) - return NULL; +{ + PyObject *registry; + _Py_IDENTIFIER(onceregistry); + + registry = get_warnings_attr(&PyId_onceregistry, 0); + if (registry == NULL) { + if (PyErr_Occurred()) + return NULL; assert(st->once_registry); return st->once_registry; - } - if (!PyDict_Check(registry)) { - PyErr_Format(PyExc_TypeError, - MODULE_NAME ".onceregistry must be a dict, " - "not '%.200s'", - Py_TYPE(registry)->tp_name); - Py_DECREF(registry); - return NULL; - } + } + if (!PyDict_Check(registry)) { + PyErr_Format(PyExc_TypeError, + MODULE_NAME ".onceregistry must be a dict, " + "not '%.200s'", + Py_TYPE(registry)->tp_name); + Py_DECREF(registry); + return NULL; + } Py_SETREF(st->once_registry, registry); - return registry; -} - - -static PyObject * + return registry; +} + + +static PyObject * get_default_action(WarningsState *st) -{ - PyObject *default_action; - _Py_IDENTIFIER(defaultaction); - - default_action = get_warnings_attr(&PyId_defaultaction, 0); - if (default_action == NULL) { - if (PyErr_Occurred()) { - return NULL; - } +{ + PyObject *default_action; + _Py_IDENTIFIER(defaultaction); + + default_action = get_warnings_attr(&PyId_defaultaction, 0); + if (default_action == NULL) { + if (PyErr_Occurred()) { + return NULL; + } assert(st->default_action); return st->default_action; - } - if (!PyUnicode_Check(default_action)) { - PyErr_Format(PyExc_TypeError, - MODULE_NAME ".defaultaction must be a string, " - "not '%.200s'", - Py_TYPE(default_action)->tp_name); - Py_DECREF(default_action); - return NULL; - } + } + if (!PyUnicode_Check(default_action)) { + PyErr_Format(PyExc_TypeError, + MODULE_NAME ".defaultaction must be a string, " + "not '%.200s'", + Py_TYPE(default_action)->tp_name); + Py_DECREF(default_action); + return NULL; + } Py_SETREF(st->default_action, default_action); - return default_action; -} - - -/* The item is a new reference. */ -static PyObject* -get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, - PyObject *module, PyObject **item) -{ - PyObject *action; - Py_ssize_t i; - PyObject *warnings_filters; - _Py_IDENTIFIER(filters); + return default_action; +} + + +/* The item is a new reference. */ +static PyObject* +get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, + PyObject *module, PyObject **item) +{ + PyObject *action; + Py_ssize_t i; + PyObject *warnings_filters; + _Py_IDENTIFIER(filters); WarningsState *st = warnings_get_state(); if (st == NULL) { return NULL; } - - warnings_filters = get_warnings_attr(&PyId_filters, 0); - if (warnings_filters == NULL) { - if (PyErr_Occurred()) - return NULL; - } - else { + + warnings_filters = get_warnings_attr(&PyId_filters, 0); + if (warnings_filters == NULL) { + if (PyErr_Occurred()) + return NULL; + } + else { Py_SETREF(st->filters, warnings_filters); - } - + } + PyObject *filters = st->filters; - if (filters == NULL || !PyList_Check(filters)) { - PyErr_SetString(PyExc_ValueError, - MODULE_NAME ".filters must be a list"); - return NULL; - } - + if (filters == NULL || !PyList_Check(filters)) { + PyErr_SetString(PyExc_ValueError, + MODULE_NAME ".filters must be a list"); + return NULL; + } + /* WarningsState.filters could change while we are iterating over it. */ - for (i = 0; i < PyList_GET_SIZE(filters); i++) { - PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj; - Py_ssize_t ln; - int is_subclass, good_msg, good_mod; - - tmp_item = PyList_GET_ITEM(filters, i); - if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) { - PyErr_Format(PyExc_ValueError, - MODULE_NAME ".filters item %zd isn't a 5-tuple", i); - return NULL; - } - - /* Python code: action, msg, cat, mod, ln = item */ - Py_INCREF(tmp_item); - action = PyTuple_GET_ITEM(tmp_item, 0); - msg = PyTuple_GET_ITEM(tmp_item, 1); - cat = PyTuple_GET_ITEM(tmp_item, 2); - mod = PyTuple_GET_ITEM(tmp_item, 3); - ln_obj = PyTuple_GET_ITEM(tmp_item, 4); - - if (!PyUnicode_Check(action)) { - PyErr_Format(PyExc_TypeError, - "action must be a string, not '%.200s'", - Py_TYPE(action)->tp_name); - Py_DECREF(tmp_item); - return NULL; - } - - good_msg = check_matched(msg, text); - if (good_msg == -1) { - Py_DECREF(tmp_item); - return NULL; - } - - good_mod = check_matched(mod, module); - if (good_mod == -1) { - Py_DECREF(tmp_item); - return NULL; - } - - is_subclass = PyObject_IsSubclass(category, cat); - if (is_subclass == -1) { - Py_DECREF(tmp_item); - return NULL; - } - - ln = PyLong_AsSsize_t(ln_obj); - if (ln == -1 && PyErr_Occurred()) { - Py_DECREF(tmp_item); - return NULL; - } - - if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) { - *item = tmp_item; - return action; - } - - Py_DECREF(tmp_item); - } - + for (i = 0; i < PyList_GET_SIZE(filters); i++) { + PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj; + Py_ssize_t ln; + int is_subclass, good_msg, good_mod; + + tmp_item = PyList_GET_ITEM(filters, i); + if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) { + PyErr_Format(PyExc_ValueError, + MODULE_NAME ".filters item %zd isn't a 5-tuple", i); + return NULL; + } + + /* Python code: action, msg, cat, mod, ln = item */ + Py_INCREF(tmp_item); + action = PyTuple_GET_ITEM(tmp_item, 0); + msg = PyTuple_GET_ITEM(tmp_item, 1); + cat = PyTuple_GET_ITEM(tmp_item, 2); + mod = PyTuple_GET_ITEM(tmp_item, 3); + ln_obj = PyTuple_GET_ITEM(tmp_item, 4); + + if (!PyUnicode_Check(action)) { + PyErr_Format(PyExc_TypeError, + "action must be a string, not '%.200s'", + Py_TYPE(action)->tp_name); + Py_DECREF(tmp_item); + return NULL; + } + + good_msg = check_matched(msg, text); + if (good_msg == -1) { + Py_DECREF(tmp_item); + return NULL; + } + + good_mod = check_matched(mod, module); + if (good_mod == -1) { + Py_DECREF(tmp_item); + return NULL; + } + + is_subclass = PyObject_IsSubclass(category, cat); + if (is_subclass == -1) { + Py_DECREF(tmp_item); + return NULL; + } + + ln = PyLong_AsSsize_t(ln_obj); + if (ln == -1 && PyErr_Occurred()) { + Py_DECREF(tmp_item); + return NULL; + } + + if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) { + *item = tmp_item; + return action; + } + + Py_DECREF(tmp_item); + } + action = get_default_action(st); - if (action != NULL) { - Py_INCREF(Py_None); - *item = Py_None; - return action; - } - - return NULL; -} - - -static int -already_warned(PyObject *registry, PyObject *key, int should_set) -{ - PyObject *version_obj, *already_warned; - _Py_IDENTIFIER(version); - - if (key == NULL) - return -1; - + if (action != NULL) { + Py_INCREF(Py_None); + *item = Py_None; + return action; + } + + return NULL; +} + + +static int +already_warned(PyObject *registry, PyObject *key, int should_set) +{ + PyObject *version_obj, *already_warned; + _Py_IDENTIFIER(version); + + if (key == NULL) + return -1; + WarningsState *st = warnings_get_state(); if (st == NULL) { return -1; } version_obj = _PyDict_GetItemIdWithError(registry, &PyId_version); - if (version_obj == NULL - || !PyLong_CheckExact(version_obj) + if (version_obj == NULL + || !PyLong_CheckExact(version_obj) || PyLong_AsLong(version_obj) != st->filters_version) - { - if (PyErr_Occurred()) { - return -1; - } - PyDict_Clear(registry); + { + if (PyErr_Occurred()) { + return -1; + } + PyDict_Clear(registry); version_obj = PyLong_FromLong(st->filters_version); - if (version_obj == NULL) - return -1; - if (_PyDict_SetItemId(registry, &PyId_version, version_obj) < 0) { - Py_DECREF(version_obj); - return -1; - } - Py_DECREF(version_obj); - } - else { + if (version_obj == NULL) + return -1; + if (_PyDict_SetItemId(registry, &PyId_version, version_obj) < 0) { + Py_DECREF(version_obj); + return -1; + } + Py_DECREF(version_obj); + } + else { already_warned = PyDict_GetItemWithError(registry, key); - if (already_warned != NULL) { - int rc = PyObject_IsTrue(already_warned); - if (rc != 0) - return rc; - } + if (already_warned != NULL) { + int rc = PyObject_IsTrue(already_warned); + if (rc != 0) + return rc; + } else if (PyErr_Occurred()) { return -1; } - } - - /* This warning wasn't found in the registry, set it. */ - if (should_set) - return PyDict_SetItem(registry, key, Py_True); - return 0; -} - -/* New reference. */ -static PyObject * -normalize_module(PyObject *filename) -{ - PyObject *module; - int kind; + } + + /* This warning wasn't found in the registry, set it. */ + if (should_set) + return PyDict_SetItem(registry, key, Py_True); + return 0; +} + +/* New reference. */ +static PyObject * +normalize_module(PyObject *filename) +{ + PyObject *module; + int kind; const void *data; - Py_ssize_t len; - - len = PyUnicode_GetLength(filename); - if (len < 0) - return NULL; - - if (len == 0) - return PyUnicode_FromString("<unknown>"); - - kind = PyUnicode_KIND(filename); - data = PyUnicode_DATA(filename); - - /* if filename.endswith(".py"): */ - if (len >= 3 && - PyUnicode_READ(kind, data, len-3) == '.' && - PyUnicode_READ(kind, data, len-2) == 'p' && - PyUnicode_READ(kind, data, len-1) == 'y') - { - module = PyUnicode_Substring(filename, 0, len-3); - } - else { - module = filename; - Py_INCREF(module); - } - return module; -} - -static int -update_registry(PyObject *registry, PyObject *text, PyObject *category, - int add_zero) -{ - PyObject *altkey; - int rc; - - if (add_zero) - altkey = PyTuple_Pack(3, text, category, _PyLong_Zero); - else - altkey = PyTuple_Pack(2, text, category); - - rc = already_warned(registry, altkey, 1); - Py_XDECREF(altkey); - return rc; -} - -static void -show_warning(PyObject *filename, int lineno, PyObject *text, - PyObject *category, PyObject *sourceline) -{ - PyObject *f_stderr; - PyObject *name; - char lineno_str[128]; - - PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno); - - name = _PyObject_GetAttrId(category, &PyId___name__); + Py_ssize_t len; + + len = PyUnicode_GetLength(filename); + if (len < 0) + return NULL; + + if (len == 0) + return PyUnicode_FromString("<unknown>"); + + kind = PyUnicode_KIND(filename); + data = PyUnicode_DATA(filename); + + /* if filename.endswith(".py"): */ + if (len >= 3 && + PyUnicode_READ(kind, data, len-3) == '.' && + PyUnicode_READ(kind, data, len-2) == 'p' && + PyUnicode_READ(kind, data, len-1) == 'y') + { + module = PyUnicode_Substring(filename, 0, len-3); + } + else { + module = filename; + Py_INCREF(module); + } + return module; +} + +static int +update_registry(PyObject *registry, PyObject *text, PyObject *category, + int add_zero) +{ + PyObject *altkey; + int rc; + + if (add_zero) + altkey = PyTuple_Pack(3, text, category, _PyLong_Zero); + else + altkey = PyTuple_Pack(2, text, category); + + rc = already_warned(registry, altkey, 1); + Py_XDECREF(altkey); + return rc; +} + +static void +show_warning(PyObject *filename, int lineno, PyObject *text, + PyObject *category, PyObject *sourceline) +{ + PyObject *f_stderr; + PyObject *name; + char lineno_str[128]; + + PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno); + + name = _PyObject_GetAttrId(category, &PyId___name__); if (name == NULL) { - goto error; - } - - f_stderr = _PySys_GetObjectId(&PyId_stderr); - if (f_stderr == NULL) { - fprintf(stderr, "lost sys.stderr\n"); - goto error; - } - - /* Print "filename:lineno: category: text\n" */ - if (PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW) < 0) - goto error; - if (PyFile_WriteString(lineno_str, f_stderr) < 0) - goto error; - if (PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW) < 0) - goto error; - if (PyFile_WriteString(": ", f_stderr) < 0) - goto error; - if (PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW) < 0) - goto error; - if (PyFile_WriteString("\n", f_stderr) < 0) - goto error; - Py_CLEAR(name); - - /* Print " source_line\n" */ - if (sourceline) { - int kind; + goto error; + } + + f_stderr = _PySys_GetObjectId(&PyId_stderr); + if (f_stderr == NULL) { + fprintf(stderr, "lost sys.stderr\n"); + goto error; + } + + /* Print "filename:lineno: category: text\n" */ + if (PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW) < 0) + goto error; + if (PyFile_WriteString(lineno_str, f_stderr) < 0) + goto error; + if (PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW) < 0) + goto error; + if (PyFile_WriteString(": ", f_stderr) < 0) + goto error; + if (PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW) < 0) + goto error; + if (PyFile_WriteString("\n", f_stderr) < 0) + goto error; + Py_CLEAR(name); + + /* Print " source_line\n" */ + if (sourceline) { + int kind; const void *data; - Py_ssize_t i, len; - Py_UCS4 ch; - PyObject *truncated; - - if (PyUnicode_READY(sourceline) < 1) - goto error; - - kind = PyUnicode_KIND(sourceline); - data = PyUnicode_DATA(sourceline); - len = PyUnicode_GET_LENGTH(sourceline); - for (i=0; i<len; i++) { - ch = PyUnicode_READ(kind, data, i); - if (ch != ' ' && ch != '\t' && ch != '\014') - break; - } - - truncated = PyUnicode_Substring(sourceline, i, len); - if (truncated == NULL) - goto error; - - PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW); - Py_DECREF(truncated); - PyFile_WriteString("\n", f_stderr); - } - else { - _Py_DisplaySourceLine(f_stderr, filename, lineno, 2); - } - -error: - Py_XDECREF(name); - PyErr_Clear(); -} - -static int -call_show_warning(PyObject *category, PyObject *text, PyObject *message, - PyObject *filename, int lineno, PyObject *lineno_obj, - PyObject *sourceline, PyObject *source) -{ - PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL; - _Py_IDENTIFIER(_showwarnmsg); - _Py_IDENTIFIER(WarningMessage); - - /* 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 doesn't. */ - show_fn = get_warnings_attr(&PyId__showwarnmsg, source != NULL); - if (show_fn == NULL) { - if (PyErr_Occurred()) - return -1; - show_warning(filename, lineno, text, category, sourceline); - return 0; - } - - if (!PyCallable_Check(show_fn)) { - PyErr_SetString(PyExc_TypeError, - "warnings._showwarnmsg() must be set to a callable"); - goto error; - } - - warnmsg_cls = get_warnings_attr(&PyId_WarningMessage, 0); - if (warnmsg_cls == NULL) { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_RuntimeError, - "unable to get warnings.WarningMessage"); - } - goto error; - } - - msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category, - filename, lineno_obj, Py_None, Py_None, source, - NULL); - Py_DECREF(warnmsg_cls); - if (msg == NULL) - goto error; - + Py_ssize_t i, len; + Py_UCS4 ch; + PyObject *truncated; + + if (PyUnicode_READY(sourceline) < 1) + goto error; + + kind = PyUnicode_KIND(sourceline); + data = PyUnicode_DATA(sourceline); + len = PyUnicode_GET_LENGTH(sourceline); + for (i=0; i<len; i++) { + ch = PyUnicode_READ(kind, data, i); + if (ch != ' ' && ch != '\t' && ch != '\014') + break; + } + + truncated = PyUnicode_Substring(sourceline, i, len); + if (truncated == NULL) + goto error; + + PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW); + Py_DECREF(truncated); + PyFile_WriteString("\n", f_stderr); + } + else { + _Py_DisplaySourceLine(f_stderr, filename, lineno, 2); + } + +error: + Py_XDECREF(name); + PyErr_Clear(); +} + +static int +call_show_warning(PyObject *category, PyObject *text, PyObject *message, + PyObject *filename, int lineno, PyObject *lineno_obj, + PyObject *sourceline, PyObject *source) +{ + PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL; + _Py_IDENTIFIER(_showwarnmsg); + _Py_IDENTIFIER(WarningMessage); + + /* 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 doesn't. */ + show_fn = get_warnings_attr(&PyId__showwarnmsg, source != NULL); + if (show_fn == NULL) { + if (PyErr_Occurred()) + return -1; + show_warning(filename, lineno, text, category, sourceline); + return 0; + } + + if (!PyCallable_Check(show_fn)) { + PyErr_SetString(PyExc_TypeError, + "warnings._showwarnmsg() must be set to a callable"); + goto error; + } + + warnmsg_cls = get_warnings_attr(&PyId_WarningMessage, 0); + if (warnmsg_cls == NULL) { + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, + "unable to get warnings.WarningMessage"); + } + goto error; + } + + msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category, + filename, lineno_obj, Py_None, Py_None, source, + NULL); + Py_DECREF(warnmsg_cls); + if (msg == NULL) + goto error; + res = PyObject_CallOneArg(show_fn, msg); - Py_DECREF(show_fn); - Py_DECREF(msg); - - if (res == NULL) - return -1; - - Py_DECREF(res); - return 0; - -error: - Py_XDECREF(show_fn); - return -1; -} - -static PyObject * -warn_explicit(PyObject *category, PyObject *message, - PyObject *filename, int lineno, - PyObject *module, PyObject *registry, PyObject *sourceline, - PyObject *source) -{ - PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL; - PyObject *item = NULL; - PyObject *action; - int rc; - - /* module can be None if a warning is emitted late during Python shutdown. - In this case, the Python warnings module was probably unloaded, filters - are no more available to choose as action. It is safer to ignore the - warning and do nothing. */ - if (module == Py_None) - Py_RETURN_NONE; - - if (registry && !PyDict_Check(registry) && (registry != Py_None)) { - PyErr_SetString(PyExc_TypeError, "'registry' must be a dict or None"); - return NULL; - } - - /* Normalize module. */ - if (module == NULL) { - module = normalize_module(filename); - if (module == NULL) - return NULL; - } - else - Py_INCREF(module); - - /* Normalize message. */ - Py_INCREF(message); /* DECREF'ed in cleanup. */ - rc = PyObject_IsInstance(message, PyExc_Warning); - if (rc == -1) { - goto cleanup; - } - if (rc == 1) { - text = PyObject_Str(message); - if (text == NULL) - goto cleanup; + Py_DECREF(show_fn); + Py_DECREF(msg); + + if (res == NULL) + return -1; + + Py_DECREF(res); + return 0; + +error: + Py_XDECREF(show_fn); + return -1; +} + +static PyObject * +warn_explicit(PyObject *category, PyObject *message, + PyObject *filename, int lineno, + PyObject *module, PyObject *registry, PyObject *sourceline, + PyObject *source) +{ + PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL; + PyObject *item = NULL; + PyObject *action; + int rc; + + /* module can be None if a warning is emitted late during Python shutdown. + In this case, the Python warnings module was probably unloaded, filters + are no more available to choose as action. It is safer to ignore the + warning and do nothing. */ + if (module == Py_None) + Py_RETURN_NONE; + + if (registry && !PyDict_Check(registry) && (registry != Py_None)) { + PyErr_SetString(PyExc_TypeError, "'registry' must be a dict or None"); + return NULL; + } + + /* Normalize module. */ + if (module == NULL) { + module = normalize_module(filename); + if (module == NULL) + return NULL; + } + else + Py_INCREF(module); + + /* Normalize message. */ + Py_INCREF(message); /* DECREF'ed in cleanup. */ + rc = PyObject_IsInstance(message, PyExc_Warning); + if (rc == -1) { + goto cleanup; + } + if (rc == 1) { + text = PyObject_Str(message); + if (text == NULL) + goto cleanup; category = (PyObject*)Py_TYPE(message); - } - else { - text = message; + } + else { + text = message; message = PyObject_CallOneArg(category, message); - if (message == NULL) - goto cleanup; - } - - lineno_obj = PyLong_FromLong(lineno); - if (lineno_obj == NULL) - goto cleanup; - - if (source == Py_None) { - source = NULL; - } - - /* Create key. */ - key = PyTuple_Pack(3, text, category, lineno_obj); - if (key == NULL) - goto cleanup; - - if ((registry != NULL) && (registry != Py_None)) { - rc = already_warned(registry, key, 0); - if (rc == -1) - goto cleanup; - else if (rc == 1) - goto return_none; - /* Else this warning hasn't been generated before. */ - } - - action = get_filter(category, text, lineno, module, &item); - if (action == NULL) - goto cleanup; - - if (_PyUnicode_EqualToASCIIString(action, "error")) { - PyErr_SetObject(category, message); - goto cleanup; - } - - if (_PyUnicode_EqualToASCIIString(action, "ignore")) { - goto return_none; - } - - /* Store in the registry that we've been here, *except* when the action - is "always". */ - rc = 0; - if (!_PyUnicode_EqualToASCIIString(action, "always")) { - if (registry != NULL && registry != Py_None && - PyDict_SetItem(registry, key, Py_True) < 0) - { - goto cleanup; - } - - if (_PyUnicode_EqualToASCIIString(action, "once")) { - if (registry == NULL || registry == Py_None) { + if (message == NULL) + goto cleanup; + } + + lineno_obj = PyLong_FromLong(lineno); + if (lineno_obj == NULL) + goto cleanup; + + if (source == Py_None) { + source = NULL; + } + + /* Create key. */ + key = PyTuple_Pack(3, text, category, lineno_obj); + if (key == NULL) + goto cleanup; + + if ((registry != NULL) && (registry != Py_None)) { + rc = already_warned(registry, key, 0); + if (rc == -1) + goto cleanup; + else if (rc == 1) + goto return_none; + /* Else this warning hasn't been generated before. */ + } + + action = get_filter(category, text, lineno, module, &item); + if (action == NULL) + goto cleanup; + + if (_PyUnicode_EqualToASCIIString(action, "error")) { + PyErr_SetObject(category, message); + goto cleanup; + } + + if (_PyUnicode_EqualToASCIIString(action, "ignore")) { + goto return_none; + } + + /* Store in the registry that we've been here, *except* when the action + is "always". */ + rc = 0; + if (!_PyUnicode_EqualToASCIIString(action, "always")) { + if (registry != NULL && registry != Py_None && + PyDict_SetItem(registry, key, Py_True) < 0) + { + goto cleanup; + } + + if (_PyUnicode_EqualToASCIIString(action, "once")) { + if (registry == NULL || registry == Py_None) { WarningsState *st = warnings_get_state(); if (st == NULL) { goto cleanup; } registry = get_once_registry(st); - if (registry == NULL) - goto cleanup; - } + if (registry == NULL) + goto cleanup; + } /* WarningsState.once_registry[(text, category)] = 1 */ - rc = update_registry(registry, text, category, 0); - } - else if (_PyUnicode_EqualToASCIIString(action, "module")) { - /* registry[(text, category, 0)] = 1 */ - if (registry != NULL && registry != Py_None) - rc = update_registry(registry, text, category, 0); - } - else if (!_PyUnicode_EqualToASCIIString(action, "default")) { - PyErr_Format(PyExc_RuntimeError, - "Unrecognized action (%R) in warnings.filters:\n %R", - action, item); - goto cleanup; - } - } - - if (rc == 1) /* Already warned for this module. */ - goto return_none; - if (rc == 0) { - if (call_show_warning(category, text, message, filename, lineno, - lineno_obj, sourceline, source) < 0) - goto cleanup; - } - else /* if (rc == -1) */ - goto cleanup; - - return_none: - result = Py_None; - Py_INCREF(result); - - cleanup: - Py_XDECREF(item); - Py_XDECREF(key); - Py_XDECREF(text); - Py_XDECREF(lineno_obj); - Py_DECREF(module); - Py_XDECREF(message); - return result; /* Py_None or NULL. */ -} - -static int -is_internal_frame(PyFrameObject *frame) -{ - static PyObject *importlib_string = NULL; - static PyObject *bootstrap_string = NULL; - int contains; - - if (importlib_string == NULL) { - importlib_string = PyUnicode_FromString("importlib"); - if (importlib_string == NULL) { - return 0; - } - - bootstrap_string = PyUnicode_FromString("_bootstrap"); - if (bootstrap_string == NULL) { - Py_DECREF(importlib_string); - return 0; - } - Py_INCREF(importlib_string); - Py_INCREF(bootstrap_string); - } - + rc = update_registry(registry, text, category, 0); + } + else if (_PyUnicode_EqualToASCIIString(action, "module")) { + /* registry[(text, category, 0)] = 1 */ + if (registry != NULL && registry != Py_None) + rc = update_registry(registry, text, category, 0); + } + else if (!_PyUnicode_EqualToASCIIString(action, "default")) { + PyErr_Format(PyExc_RuntimeError, + "Unrecognized action (%R) in warnings.filters:\n %R", + action, item); + goto cleanup; + } + } + + if (rc == 1) /* Already warned for this module. */ + goto return_none; + if (rc == 0) { + if (call_show_warning(category, text, message, filename, lineno, + lineno_obj, sourceline, source) < 0) + goto cleanup; + } + else /* if (rc == -1) */ + goto cleanup; + + return_none: + result = Py_None; + Py_INCREF(result); + + cleanup: + Py_XDECREF(item); + Py_XDECREF(key); + Py_XDECREF(text); + Py_XDECREF(lineno_obj); + Py_DECREF(module); + Py_XDECREF(message); + return result; /* Py_None or NULL. */ +} + +static int +is_internal_frame(PyFrameObject *frame) +{ + static PyObject *importlib_string = NULL; + static PyObject *bootstrap_string = NULL; + int contains; + + if (importlib_string == NULL) { + importlib_string = PyUnicode_FromString("importlib"); + if (importlib_string == NULL) { + return 0; + } + + bootstrap_string = PyUnicode_FromString("_bootstrap"); + if (bootstrap_string == NULL) { + Py_DECREF(importlib_string); + return 0; + } + Py_INCREF(importlib_string); + Py_INCREF(bootstrap_string); + } + if (frame == NULL) { - return 0; - } + return 0; + } PyCodeObject *code = PyFrame_GetCode(frame); PyObject *filename = code->co_filename; @@ -793,360 +793,360 @@ is_internal_frame(PyFrameObject *frame) if (filename == NULL) { return 0; } - if (!PyUnicode_Check(filename)) { - return 0; - } - - contains = PyUnicode_Contains(filename, importlib_string); - if (contains < 0) { - return 0; - } - else if (contains > 0) { - contains = PyUnicode_Contains(filename, bootstrap_string); - if (contains < 0) { - return 0; - } - else if (contains > 0) { - return 1; - } - } - - return 0; -} - -static PyFrameObject * -next_external_frame(PyFrameObject *frame) -{ - do { + if (!PyUnicode_Check(filename)) { + return 0; + } + + contains = PyUnicode_Contains(filename, importlib_string); + if (contains < 0) { + return 0; + } + else if (contains > 0) { + contains = PyUnicode_Contains(filename, bootstrap_string); + if (contains < 0) { + return 0; + } + else if (contains > 0) { + return 1; + } + } + + return 0; +} + +static PyFrameObject * +next_external_frame(PyFrameObject *frame) +{ + do { PyFrameObject *back = PyFrame_GetBack(frame); Py_DECREF(frame); frame = back; - } while (frame != NULL && is_internal_frame(frame)); - - return frame; -} - -/* filename, module, and registry are new refs, globals is borrowed */ -/* Returns 0 on error (no new refs), 1 on success */ -static int -setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, - PyObject **module, PyObject **registry) -{ + } while (frame != NULL && is_internal_frame(frame)); + + return frame; +} + +/* filename, module, and registry are new refs, globals is borrowed */ +/* Returns 0 on error (no new refs), 1 on success */ +static int +setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, + PyObject **module, PyObject **registry) +{ _Py_IDENTIFIER(__warningregistry__); - PyObject *globals; - + PyObject *globals; + /* Setup globals, filename and lineno. */ PyThreadState *tstate = _PyThreadState_GET(); PyFrameObject *f = PyThreadState_GetFrame(tstate); - // Stack level comparisons to Python code is off by one as there is no - // warnings-related stack level to avoid. - if (stack_level <= 0 || is_internal_frame(f)) { - while (--stack_level > 0 && f != NULL) { + // Stack level comparisons to Python code is off by one as there is no + // warnings-related stack level to avoid. + if (stack_level <= 0 || is_internal_frame(f)) { + while (--stack_level > 0 && f != NULL) { PyFrameObject *back = PyFrame_GetBack(f); Py_DECREF(f); f = back; - } - } - else { - while (--stack_level > 0 && f != NULL) { - f = next_external_frame(f); - } - } - - if (f == NULL) { + } + } + else { + while (--stack_level > 0 && f != NULL) { + f = next_external_frame(f); + } + } + + if (f == NULL) { globals = _PyInterpreterState_GET()->sysdict; *filename = PyUnicode_FromString("sys"); - *lineno = 1; - } - else { - globals = f->f_globals; + *lineno = 1; + } + else { + globals = f->f_globals; PyCodeObject *code = PyFrame_GetCode(f); *filename = code->co_filename; Py_DECREF(code); Py_INCREF(*filename); - *lineno = PyFrame_GetLineNumber(f); + *lineno = PyFrame_GetLineNumber(f); Py_DECREF(f); - } - - *module = NULL; - - /* Setup registry. */ - assert(globals != NULL); - assert(PyDict_Check(globals)); + } + + *module = NULL; + + /* Setup registry. */ + assert(globals != NULL); + assert(PyDict_Check(globals)); *registry = _PyDict_GetItemIdWithError(globals, &PyId___warningregistry__); - if (*registry == NULL) { - int rc; - + if (*registry == NULL) { + int rc; + if (_PyErr_Occurred(tstate)) { goto handle_error; } - *registry = PyDict_New(); - if (*registry == NULL) + *registry = PyDict_New(); + if (*registry == NULL) goto handle_error; - + rc = _PyDict_SetItemId(globals, &PyId___warningregistry__, *registry); - if (rc < 0) - goto handle_error; - } - else - Py_INCREF(*registry); - - /* Setup module. */ + if (rc < 0) + goto handle_error; + } + else + Py_INCREF(*registry); + + /* Setup module. */ *module = _PyDict_GetItemIdWithError(globals, &PyId___name__); - if (*module == Py_None || (*module != NULL && PyUnicode_Check(*module))) { - Py_INCREF(*module); - } + if (*module == Py_None || (*module != NULL && PyUnicode_Check(*module))) { + Py_INCREF(*module); + } else if (_PyErr_Occurred(tstate)) { goto handle_error; } - else { - *module = PyUnicode_FromString("<string>"); - if (*module == NULL) - goto handle_error; - } - - return 1; - - handle_error: - Py_XDECREF(*registry); - Py_XDECREF(*module); + else { + *module = PyUnicode_FromString("<string>"); + if (*module == NULL) + goto handle_error; + } + + return 1; + + handle_error: + Py_XDECREF(*registry); + Py_XDECREF(*module); Py_DECREF(*filename); - return 0; -} - -static PyObject * -get_category(PyObject *message, PyObject *category) -{ - int rc; - - /* Get category. */ - rc = PyObject_IsInstance(message, PyExc_Warning); - if (rc == -1) - return NULL; - - if (rc == 1) + return 0; +} + +static PyObject * +get_category(PyObject *message, PyObject *category) +{ + int rc; + + /* Get category. */ + rc = PyObject_IsInstance(message, PyExc_Warning); + if (rc == -1) + return NULL; + + if (rc == 1) category = (PyObject*)Py_TYPE(message); - else if (category == NULL || category == Py_None) - category = PyExc_UserWarning; - - /* Validate category. */ - rc = PyObject_IsSubclass(category, PyExc_Warning); - /* category is not a subclass of PyExc_Warning or - PyObject_IsSubclass raised an error */ - if (rc == -1 || rc == 0) { - PyErr_Format(PyExc_TypeError, - "category must be a Warning subclass, not '%s'", - Py_TYPE(category)->tp_name); - return NULL; - } - - return category; -} - -static PyObject * -do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level, - PyObject *source) -{ - PyObject *filename, *module, *registry, *res; - int lineno; - - if (!setup_context(stack_level, &filename, &lineno, &module, ®istry)) - return NULL; - - res = warn_explicit(category, message, filename, lineno, module, registry, - NULL, source); - Py_DECREF(filename); - Py_DECREF(registry); - Py_DECREF(module); - return res; -} - -/*[clinic input] -warn as warnings_warn - - message: object - category: object = None - stacklevel: Py_ssize_t = 1 - source: object = None - -Issue a warning, or maybe ignore it or raise an exception. -[clinic start generated code]*/ - -static PyObject * -warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category, - Py_ssize_t stacklevel, PyObject *source) -/*[clinic end generated code: output=31ed5ab7d8d760b2 input=bfdf5cf99f6c4edd]*/ -{ - category = get_category(message, category); - if (category == NULL) - return NULL; - return do_warn(message, category, stacklevel, source); -} - -static PyObject * -get_source_line(PyObject *module_globals, int lineno) -{ - _Py_IDENTIFIER(get_source); - _Py_IDENTIFIER(__loader__); - PyObject *loader; - PyObject *module_name; - PyObject *get_source; - PyObject *source; - PyObject *source_list; - PyObject *source_line; - - /* Check/get the requisite pieces needed for the loader. */ - loader = _PyDict_GetItemIdWithError(module_globals, &PyId___loader__); - if (loader == NULL) { - return NULL; - } - Py_INCREF(loader); - module_name = _PyDict_GetItemIdWithError(module_globals, &PyId___name__); - if (!module_name) { - Py_DECREF(loader); - return NULL; - } - Py_INCREF(module_name); - - /* Make sure the loader implements the optional get_source() method. */ - (void)_PyObject_LookupAttrId(loader, &PyId_get_source, &get_source); - Py_DECREF(loader); - if (!get_source) { - Py_DECREF(module_name); - return NULL; - } - /* Call get_source() to get the source code. */ + else if (category == NULL || category == Py_None) + category = PyExc_UserWarning; + + /* Validate category. */ + rc = PyObject_IsSubclass(category, PyExc_Warning); + /* category is not a subclass of PyExc_Warning or + PyObject_IsSubclass raised an error */ + if (rc == -1 || rc == 0) { + PyErr_Format(PyExc_TypeError, + "category must be a Warning subclass, not '%s'", + Py_TYPE(category)->tp_name); + return NULL; + } + + return category; +} + +static PyObject * +do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level, + PyObject *source) +{ + PyObject *filename, *module, *registry, *res; + int lineno; + + if (!setup_context(stack_level, &filename, &lineno, &module, ®istry)) + return NULL; + + res = warn_explicit(category, message, filename, lineno, module, registry, + NULL, source); + Py_DECREF(filename); + Py_DECREF(registry); + Py_DECREF(module); + return res; +} + +/*[clinic input] +warn as warnings_warn + + message: object + category: object = None + stacklevel: Py_ssize_t = 1 + source: object = None + +Issue a warning, or maybe ignore it or raise an exception. +[clinic start generated code]*/ + +static PyObject * +warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category, + Py_ssize_t stacklevel, PyObject *source) +/*[clinic end generated code: output=31ed5ab7d8d760b2 input=bfdf5cf99f6c4edd]*/ +{ + category = get_category(message, category); + if (category == NULL) + return NULL; + return do_warn(message, category, stacklevel, source); +} + +static PyObject * +get_source_line(PyObject *module_globals, int lineno) +{ + _Py_IDENTIFIER(get_source); + _Py_IDENTIFIER(__loader__); + PyObject *loader; + PyObject *module_name; + PyObject *get_source; + PyObject *source; + PyObject *source_list; + PyObject *source_line; + + /* Check/get the requisite pieces needed for the loader. */ + loader = _PyDict_GetItemIdWithError(module_globals, &PyId___loader__); + if (loader == NULL) { + return NULL; + } + Py_INCREF(loader); + module_name = _PyDict_GetItemIdWithError(module_globals, &PyId___name__); + if (!module_name) { + Py_DECREF(loader); + return NULL; + } + Py_INCREF(module_name); + + /* Make sure the loader implements the optional get_source() method. */ + (void)_PyObject_LookupAttrId(loader, &PyId_get_source, &get_source); + Py_DECREF(loader); + if (!get_source) { + Py_DECREF(module_name); + return NULL; + } + /* Call get_source() to get the source code. */ source = PyObject_CallOneArg(get_source, module_name); - Py_DECREF(get_source); - Py_DECREF(module_name); - if (!source) { - return NULL; - } - if (source == Py_None) { - Py_DECREF(source); - return NULL; - } - - /* Split the source into lines. */ - source_list = PyUnicode_Splitlines(source, 0); - Py_DECREF(source); - if (!source_list) { - return NULL; - } - - /* Get the source line. */ - source_line = PyList_GetItem(source_list, lineno-1); - Py_XINCREF(source_line); - Py_DECREF(source_list); - return source_line; -} - -static PyObject * -warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwd_list[] = {"message", "category", "filename", "lineno", - "module", "registry", "module_globals", - "source", 0}; - PyObject *message; - PyObject *category; - PyObject *filename; - int lineno; - PyObject *module = NULL; - PyObject *registry = NULL; - PyObject *module_globals = NULL; - PyObject *sourceobj = NULL; - PyObject *source_line = NULL; - PyObject *returned; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit", - kwd_list, &message, &category, &filename, &lineno, &module, - ®istry, &module_globals, &sourceobj)) - return NULL; - - if (module_globals && module_globals != Py_None) { - if (!PyDict_Check(module_globals)) { - PyErr_Format(PyExc_TypeError, - "module_globals must be a dict, not '%.200s'", - Py_TYPE(module_globals)->tp_name); - return NULL; - } - - source_line = get_source_line(module_globals, lineno); - if (source_line == NULL && PyErr_Occurred()) { - return NULL; - } - } - returned = warn_explicit(category, message, filename, lineno, module, - registry, source_line, sourceobj); - Py_XDECREF(source_line); - return returned; -} - -static PyObject * -warnings_filters_mutated(PyObject *self, PyObject *args) -{ + Py_DECREF(get_source); + Py_DECREF(module_name); + if (!source) { + return NULL; + } + if (source == Py_None) { + Py_DECREF(source); + return NULL; + } + + /* Split the source into lines. */ + source_list = PyUnicode_Splitlines(source, 0); + Py_DECREF(source); + if (!source_list) { + return NULL; + } + + /* Get the source line. */ + source_line = PyList_GetItem(source_list, lineno-1); + Py_XINCREF(source_line); + Py_DECREF(source_list); + return source_line; +} + +static PyObject * +warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwd_list[] = {"message", "category", "filename", "lineno", + "module", "registry", "module_globals", + "source", 0}; + PyObject *message; + PyObject *category; + PyObject *filename; + int lineno; + PyObject *module = NULL; + PyObject *registry = NULL; + PyObject *module_globals = NULL; + PyObject *sourceobj = NULL; + PyObject *source_line = NULL; + PyObject *returned; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit", + kwd_list, &message, &category, &filename, &lineno, &module, + ®istry, &module_globals, &sourceobj)) + return NULL; + + if (module_globals && module_globals != Py_None) { + if (!PyDict_Check(module_globals)) { + PyErr_Format(PyExc_TypeError, + "module_globals must be a dict, not '%.200s'", + Py_TYPE(module_globals)->tp_name); + return NULL; + } + + source_line = get_source_line(module_globals, lineno); + if (source_line == NULL && PyErr_Occurred()) { + return NULL; + } + } + returned = warn_explicit(category, message, filename, lineno, module, + registry, source_line, sourceobj); + Py_XDECREF(source_line); + return returned; +} + +static PyObject * +warnings_filters_mutated(PyObject *self, PyObject *args) +{ WarningsState *st = warnings_get_state(); if (st == NULL) { return NULL; } st->filters_version++; - Py_RETURN_NONE; -} - - -/* Function to issue a warning message; may raise an exception. */ - -static int -warn_unicode(PyObject *category, PyObject *message, - Py_ssize_t stack_level, PyObject *source) -{ - PyObject *res; - - if (category == NULL) - category = PyExc_RuntimeWarning; - - res = do_warn(message, category, stack_level, source); - if (res == NULL) - return -1; - Py_DECREF(res); - - return 0; -} - -static int -_PyErr_WarnFormatV(PyObject *source, - PyObject *category, Py_ssize_t stack_level, - const char *format, va_list vargs) -{ - PyObject *message; - int res; - - message = PyUnicode_FromFormatV(format, vargs); - if (message == NULL) - return -1; - - res = warn_unicode(category, message, stack_level, source); - Py_DECREF(message); - return res; -} - -int -PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, - const char *format, ...) -{ - int res; - va_list vargs; - -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); -#else - va_start(vargs); -#endif - res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs); - va_end(vargs); - return res; -} - + Py_RETURN_NONE; +} + + +/* Function to issue a warning message; may raise an exception. */ + +static int +warn_unicode(PyObject *category, PyObject *message, + Py_ssize_t stack_level, PyObject *source) +{ + PyObject *res; + + if (category == NULL) + category = PyExc_RuntimeWarning; + + res = do_warn(message, category, stack_level, source); + if (res == NULL) + return -1; + Py_DECREF(res); + + return 0; +} + +static int +_PyErr_WarnFormatV(PyObject *source, + PyObject *category, Py_ssize_t stack_level, + const char *format, va_list vargs) +{ + PyObject *message; + int res; + + message = PyUnicode_FromFormatV(format, vargs); + if (message == NULL) + return -1; + + res = warn_unicode(category, message, stack_level, source); + Py_DECREF(message); + return res; +} + +int +PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, + const char *format, ...) +{ + int res; + va_list vargs; + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs); + va_end(vargs); + return res; +} + static int _PyErr_WarnFormat(PyObject *source, PyObject *category, Py_ssize_t stack_level, const char *format, ...) @@ -1164,200 +1164,200 @@ _PyErr_WarnFormat(PyObject *source, PyObject *category, Py_ssize_t stack_level, return res; } +int +PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level, + const char *format, ...) +{ + int res; + va_list vargs; + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning, + stack_level, format, vargs); + va_end(vargs); + return res; +} + + +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, NULL); + Py_DECREF(message); + return ret; +} + +/* PyErr_Warn is only for backwards compatibility and will be removed. + Use PyErr_WarnEx instead. */ + +#undef PyErr_Warn + int -PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level, - const char *format, ...) -{ - int res; - va_list vargs; - -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); -#else - va_start(vargs); -#endif - res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning, - stack_level, format, vargs); - va_end(vargs); - return res; -} - - -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, NULL); - Py_DECREF(message); - return ret; -} - -/* PyErr_Warn is only for backwards compatibility and will be removed. - Use PyErr_WarnEx instead. */ - -#undef PyErr_Warn - -int -PyErr_Warn(PyObject *category, const char *text) -{ - return PyErr_WarnEx(category, text, 1); -} - -/* Warning with explicit origin */ -int -PyErr_WarnExplicitObject(PyObject *category, PyObject *message, - PyObject *filename, int lineno, - PyObject *module, PyObject *registry) -{ - PyObject *res; - if (category == NULL) - category = PyExc_RuntimeWarning; - res = warn_explicit(category, message, filename, lineno, - module, registry, NULL, NULL); - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; -} - -int -PyErr_WarnExplicit(PyObject *category, const char *text, - const char *filename_str, int lineno, - const char *module_str, PyObject *registry) -{ - PyObject *message = PyUnicode_FromString(text); - PyObject *filename = PyUnicode_DecodeFSDefault(filename_str); - PyObject *module = NULL; - int ret = -1; - - if (message == NULL || filename == NULL) - goto exit; - if (module_str != NULL) { - module = PyUnicode_FromString(module_str); - if (module == NULL) - goto exit; - } - - ret = PyErr_WarnExplicitObject(category, message, filename, lineno, - module, registry); - - exit: - Py_XDECREF(message); - Py_XDECREF(module); - Py_XDECREF(filename); - return ret; -} - -int -PyErr_WarnExplicitFormat(PyObject *category, - const char *filename_str, int lineno, - const char *module_str, PyObject *registry, - const char *format, ...) -{ - PyObject *message; - PyObject *module = NULL; - PyObject *filename = PyUnicode_DecodeFSDefault(filename_str); - int ret = -1; - va_list vargs; - - if (filename == NULL) - goto exit; - if (module_str != NULL) { - module = PyUnicode_FromString(module_str); - if (module == NULL) - goto exit; - } - -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); -#else - va_start(vargs); -#endif - message = PyUnicode_FromFormatV(format, vargs); - if (message != NULL) { - PyObject *res; - res = warn_explicit(category, message, filename, lineno, - module, registry, NULL, NULL); - Py_DECREF(message); - if (res != NULL) { - Py_DECREF(res); - ret = 0; - } - } - va_end(vargs); -exit: - Py_XDECREF(module); - Py_XDECREF(filename); - return ret; -} - -void -_PyErr_WarnUnawaitedCoroutine(PyObject *coro) -{ - /* First, we attempt to funnel the warning through - warnings._warn_unawaited_coroutine. - - This could raise an exception, due to: - - a bug - - some kind of shutdown-related brokenness - - succeeding, but with an "error" warning filter installed, so the - warning is converted into a RuntimeWarning exception - - In the first two cases, we want to print the error (so we know what it - is!), and then print a warning directly as a fallback. In the last - case, we want to print the error (since it's the warning!), but *not* - do a fallback. And after we print the error we can't check for what - type of error it was (because PyErr_WriteUnraisable clears it), so we - need a flag to keep track. - - Since this is called from __del__ context, it's careful to never raise - an exception. - */ - _Py_IDENTIFIER(_warn_unawaited_coroutine); - int warned = 0; - PyObject *fn = get_warnings_attr(&PyId__warn_unawaited_coroutine, 1); - if (fn) { +PyErr_Warn(PyObject *category, const char *text) +{ + return PyErr_WarnEx(category, text, 1); +} + +/* Warning with explicit origin */ +int +PyErr_WarnExplicitObject(PyObject *category, PyObject *message, + PyObject *filename, int lineno, + PyObject *module, PyObject *registry) +{ + PyObject *res; + if (category == NULL) + category = PyExc_RuntimeWarning; + res = warn_explicit(category, message, filename, lineno, + module, registry, NULL, NULL); + if (res == NULL) + return -1; + Py_DECREF(res); + return 0; +} + +int +PyErr_WarnExplicit(PyObject *category, const char *text, + const char *filename_str, int lineno, + const char *module_str, PyObject *registry) +{ + PyObject *message = PyUnicode_FromString(text); + PyObject *filename = PyUnicode_DecodeFSDefault(filename_str); + PyObject *module = NULL; + int ret = -1; + + if (message == NULL || filename == NULL) + goto exit; + if (module_str != NULL) { + module = PyUnicode_FromString(module_str); + if (module == NULL) + goto exit; + } + + ret = PyErr_WarnExplicitObject(category, message, filename, lineno, + module, registry); + + exit: + Py_XDECREF(message); + Py_XDECREF(module); + Py_XDECREF(filename); + return ret; +} + +int +PyErr_WarnExplicitFormat(PyObject *category, + const char *filename_str, int lineno, + const char *module_str, PyObject *registry, + const char *format, ...) +{ + PyObject *message; + PyObject *module = NULL; + PyObject *filename = PyUnicode_DecodeFSDefault(filename_str); + int ret = -1; + va_list vargs; + + if (filename == NULL) + goto exit; + if (module_str != NULL) { + module = PyUnicode_FromString(module_str); + if (module == NULL) + goto exit; + } + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + message = PyUnicode_FromFormatV(format, vargs); + if (message != NULL) { + PyObject *res; + res = warn_explicit(category, message, filename, lineno, + module, registry, NULL, NULL); + Py_DECREF(message); + if (res != NULL) { + Py_DECREF(res); + ret = 0; + } + } + va_end(vargs); +exit: + Py_XDECREF(module); + Py_XDECREF(filename); + return ret; +} + +void +_PyErr_WarnUnawaitedCoroutine(PyObject *coro) +{ + /* First, we attempt to funnel the warning through + warnings._warn_unawaited_coroutine. + + This could raise an exception, due to: + - a bug + - some kind of shutdown-related brokenness + - succeeding, but with an "error" warning filter installed, so the + warning is converted into a RuntimeWarning exception + + In the first two cases, we want to print the error (so we know what it + is!), and then print a warning directly as a fallback. In the last + case, we want to print the error (since it's the warning!), but *not* + do a fallback. And after we print the error we can't check for what + type of error it was (because PyErr_WriteUnraisable clears it), so we + need a flag to keep track. + + Since this is called from __del__ context, it's careful to never raise + an exception. + */ + _Py_IDENTIFIER(_warn_unawaited_coroutine); + int warned = 0; + PyObject *fn = get_warnings_attr(&PyId__warn_unawaited_coroutine, 1); + if (fn) { PyObject *res = PyObject_CallOneArg(fn, coro); - Py_DECREF(fn); - if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) { - warned = 1; - } - Py_XDECREF(res); - } - - if (PyErr_Occurred()) { - PyErr_WriteUnraisable(coro); - } - if (!warned) { + Py_DECREF(fn); + if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) { + warned = 1; + } + Py_XDECREF(res); + } + + if (PyErr_Occurred()) { + PyErr_WriteUnraisable(coro); + } + if (!warned) { if (_PyErr_WarnFormat(coro, PyExc_RuntimeWarning, 1, "coroutine '%S' was never awaited", ((PyCoroObject *)coro)->cr_qualname) < 0) - { - PyErr_WriteUnraisable(coro); - } - } -} - -PyDoc_STRVAR(warn_explicit_doc, + { + PyErr_WriteUnraisable(coro); + } + } +} + +PyDoc_STRVAR(warn_explicit_doc, "Low-level interface to warnings functionality."); - -static PyMethodDef warnings_functions[] = { - WARNINGS_WARN_METHODDEF + +static PyMethodDef warnings_functions[] = { + WARNINGS_WARN_METHODDEF {"warn_explicit", (PyCFunction)(void(*)(void))warnings_warn_explicit, - METH_VARARGS | METH_KEYWORDS, warn_explicit_doc}, - {"_filters_mutated", (PyCFunction)warnings_filters_mutated, METH_NOARGS, - NULL}, - /* XXX(brett.cannon): add showwarning? */ - /* XXX(brett.cannon): Reasonable to add formatwarning? */ - {NULL, NULL} /* sentinel */ -}; - - -static struct PyModuleDef warningsmodule = { - PyModuleDef_HEAD_INIT, + METH_VARARGS | METH_KEYWORDS, warn_explicit_doc}, + {"_filters_mutated", (PyCFunction)warnings_filters_mutated, METH_NOARGS, + NULL}, + /* XXX(brett.cannon): add showwarning? */ + /* XXX(brett.cannon): Reasonable to add formatwarning? */ + {NULL, NULL} /* sentinel */ +}; + + +static struct PyModuleDef warningsmodule = { + PyModuleDef_HEAD_INIT, MODULE_NAME, /* m_name */ warnings__doc__, /* m_doc */ 0, /* m_size */ @@ -1366,9 +1366,9 @@ static struct PyModuleDef warningsmodule = { NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ -}; - - +}; + + PyStatus _PyWarnings_InitState(PyThreadState *tstate) { @@ -1379,40 +1379,40 @@ _PyWarnings_InitState(PyThreadState *tstate) } -PyMODINIT_FUNC -_PyWarnings_Init(void) -{ - PyObject *m; - - m = PyModule_Create(&warningsmodule); +PyMODINIT_FUNC +_PyWarnings_Init(void) +{ + PyObject *m; + + m = PyModule_Create(&warningsmodule); if (m == NULL) { - return NULL; + return NULL; } - + WarningsState *st = warnings_get_state(); if (st == NULL) { goto error; - } + } if (warnings_init_state(st) < 0) { goto error; } - + Py_INCREF(st->filters); if (PyModule_AddObject(m, "filters", st->filters) < 0) { goto error; - } - + } + Py_INCREF(st->once_registry); if (PyModule_AddObject(m, "_onceregistry", st->once_registry) < 0) { goto error; - } - + } + Py_INCREF(st->default_action); if (PyModule_AddObject(m, "_defaultaction", st->default_action) < 0) { goto error; } - return m; + return m; error: if (st != NULL) { @@ -1420,7 +1420,7 @@ error: } Py_DECREF(m); return NULL; -} +} // We need this to ensure that warnings still work until late in finalization. void |