LCOV - code coverage report
Current view: | top level - Python - _warnings.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 235 | 702 | 33.5 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 24 | 45 | 53.3 %
|  |  | Branches: | 102 | 448 | 22.8 %

               Branch data     Line data    Source code
           1                 :            : #include "Python.h"
           2                 :            : #include "pycore_initconfig.h"
           3                 :            : #include "pycore_interp.h"        // PyInterpreterState.warnings
           4                 :            : #include "pycore_long.h"          // _PyLong_GetZero()
           5                 :            : #include "pycore_pyerrors.h"
           6                 :            : #include "pycore_pystate.h"       // _PyThreadState_GET()
           7                 :            : #include "pycore_frame.h"
           8                 :            : #include "clinic/_warnings.c.h"
           9                 :            :
          10                 :            : #define MODULE_NAME "_warnings"
          11                 :            :
          12                 :            : PyDoc_STRVAR(warnings__doc__,
          13                 :            : MODULE_NAME " provides basic warning filtering support.\n"
          14                 :            : "It is a helper module to speed up interpreter start-up.");
          15                 :            :
          16                 :            :
          17                 :            : /*************************************************************************/
          18                 :            :
          19                 :            : typedef struct _warnings_runtime_state WarningsState;
          20                 :            :
          21                 :            : static inline int
          22                 :        364 : check_interp(PyInterpreterState *interp)
          23                 :            : {
          24         [ -  + ]:        364 :     if (interp == NULL) {
          25                 :          0 :         PyErr_SetString(PyExc_RuntimeError,
          26                 :            :                         "warnings_get_state: could not identify "
          27                 :            :                         "current interpreter");
          28                 :          0 :         return 0;
          29                 :            :     }
          30                 :        364 :     return 1;
          31                 :            : }
          32                 :            :
          33                 :            : static inline PyInterpreterState *
          34                 :        356 : get_current_interp(void)
          35                 :            : {
          36                 :        356 :     PyInterpreterState *interp = _PyInterpreterState_GET();
          37         [ +  - ]:        356 :     return check_interp(interp) ? interp : NULL;
          38                 :            : }
          39                 :            :
          40                 :            : static inline PyThreadState *
          41                 :          8 : get_current_tstate(void)
          42                 :            : {
          43                 :          8 :     PyThreadState *tstate = _PyThreadState_GET();
          44         [ -  + ]:          8 :     if (tstate == NULL) {
          45                 :          0 :         (void)check_interp(NULL);
          46                 :          0 :         return NULL;
          47                 :            :     }
          48         [ +  - ]:          8 :     return check_interp(tstate->interp) ? tstate : NULL;
          49                 :            : }
          50                 :            :
          51                 :            : /* Given a module object, get its per-module state. */
          52                 :            : static WarningsState *
          53                 :        364 : warnings_get_state(PyInterpreterState *interp)
          54                 :            : {
          55                 :        364 :     return &interp->warnings;
          56                 :            : }
          57                 :            :
          58                 :            : /* Clear the given warnings module state. */
          59                 :            : static void
          60                 :         25 : warnings_clear_state(WarningsState *st)
          61                 :            : {
          62         [ +  - ]:         25 :     Py_CLEAR(st->filters);
          63         [ +  - ]:         25 :     Py_CLEAR(st->once_registry);
          64         [ +  - ]:         25 :     Py_CLEAR(st->default_action);
          65                 :         25 : }
          66                 :            :
          67                 :            : #ifndef Py_DEBUG
          68                 :            : static PyObject *
          69                 :        145 : create_filter(PyObject *category, PyObject *action_str, const char *modname)
          70                 :            : {
          71                 :        145 :     PyObject *modname_obj = NULL;
          72                 :            :
          73                 :            :     /* Default to "no module name" for initial filter set */
          74         [ +  + ]:        145 :     if (modname != NULL) {
          75                 :         29 :         modname_obj = PyUnicode_InternFromString(modname);
          76         [ -  + ]:         29 :         if (modname_obj == NULL) {
          77                 :          0 :             return NULL;
          78                 :            :         }
          79                 :            :     } else {
          80                 :        116 :         modname_obj = Py_NewRef(Py_None);
          81                 :            :     }
          82                 :            :
          83                 :            :     /* This assumes the line number is zero for now. */
          84                 :        145 :     PyObject *filter = PyTuple_Pack(5, action_str, Py_None,
          85                 :            :                                     category, modname_obj, _PyLong_GetZero());
          86                 :        145 :     Py_DECREF(modname_obj);
          87                 :        145 :     return filter;
          88                 :            : }
          89                 :            : #endif
          90                 :            :
          91                 :            : static PyObject *
          92                 :         29 : init_filters(PyInterpreterState *interp)
          93                 :            : {
          94                 :            : #ifdef Py_DEBUG
          95                 :            :     /* Py_DEBUG builds show all warnings by default */
          96                 :            :     return PyList_New(0);
          97                 :            : #else
          98                 :            :     /* Other builds ignore a number of warning categories by default */
          99                 :         29 :     PyObject *filters = PyList_New(5);
         100         [ -  + ]:         29 :     if (filters == NULL) {
         101                 :          0 :         return NULL;
         102                 :            :     }
         103                 :            :
         104                 :         29 :     size_t pos = 0;  /* Post-incremented in each use. */
         105                 :            : #define ADD(TYPE, ACTION, MODNAME) \
         106                 :            :     PyList_SET_ITEM(filters, pos++, \
         107                 :            :                     create_filter(TYPE, &_Py_ID(ACTION), MODNAME));
         108                 :         29 :     ADD(PyExc_DeprecationWarning, default, "__main__");
         109                 :         29 :     ADD(PyExc_DeprecationWarning, ignore, NULL);
         110                 :         29 :     ADD(PyExc_PendingDeprecationWarning, ignore, NULL);
         111                 :         29 :     ADD(PyExc_ImportWarning, ignore, NULL);
         112                 :         29 :     ADD(PyExc_ResourceWarning, ignore, NULL);
         113                 :            : #undef ADD
         114                 :            :
         115         [ +  + ]:        174 :     for (size_t x = 0; x < pos; x++) {
         116         [ -  + ]:        145 :         if (PyList_GET_ITEM(filters, x) == NULL) {
         117                 :          0 :             Py_DECREF(filters);
         118                 :          0 :             return NULL;
         119                 :            :         }
         120                 :            :     }
         121                 :         29 :     return filters;
         122                 :            : #endif
         123                 :            : }
         124                 :            :
         125                 :            : /* Initialize the given warnings module state. */
         126                 :            : int
         127                 :         29 : _PyWarnings_InitState(PyInterpreterState *interp)
         128                 :            : {
         129                 :         29 :     WarningsState *st = &interp->warnings;
         130                 :            :
         131         [ +  - ]:         29 :     if (st->filters == NULL) {
         132                 :         29 :         st->filters = init_filters(interp);
         133         [ -  + ]:         29 :         if (st->filters == NULL) {
         134                 :          0 :             return -1;
         135                 :            :         }
         136                 :            :     }
         137                 :            :
         138         [ +  - ]:         29 :     if (st->once_registry == NULL) {
         139                 :         29 :         st->once_registry = PyDict_New();
         140         [ -  + ]:         29 :         if (st->once_registry == NULL) {
         141                 :          0 :             return -1;
         142                 :            :         }
         143                 :            :     }
         144                 :            :
         145         [ +  - ]:         29 :     if (st->default_action == NULL) {
         146                 :         29 :         st->default_action = PyUnicode_FromString("default");
         147         [ -  + ]:         29 :         if (st->default_action == NULL) {
         148                 :          0 :             return -1;
         149                 :            :         }
         150                 :            :     }
         151                 :            :
         152                 :         29 :     st->filters_version = 0;
         153                 :         29 :     return 0;
         154                 :            : }
         155                 :            :
         156                 :            :
         157                 :            : /*************************************************************************/
         158                 :            :
         159                 :            : static int
         160                 :          8 : check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg)
         161                 :            : {
         162                 :            :     PyObject *result;
         163                 :            :     int rc;
         164                 :            :
         165                 :            :     /* A 'None' filter always matches */
         166         [ +  - ]:          8 :     if (obj == Py_None)
         167                 :          8 :         return 1;
         168                 :            :
         169                 :            :     /* An internal plain text default filter must match exactly */
         170         [ #  # ]:          0 :     if (PyUnicode_CheckExact(obj)) {
         171                 :          0 :         int cmp_result = PyUnicode_Compare(obj, arg);
         172   [ #  #  #  # ]:          0 :         if (cmp_result == -1 && PyErr_Occurred()) {
         173                 :          0 :             return -1;
         174                 :            :         }
         175                 :          0 :         return !cmp_result;
         176                 :            :     }
         177                 :            :
         178                 :            :     /* Otherwise assume a regex filter and call its match() method */
         179                 :          0 :     result = PyObject_CallMethodOneArg(obj, &_Py_ID(match), arg);
         180         [ #  # ]:          0 :     if (result == NULL)
         181                 :          0 :         return -1;
         182                 :            :
         183                 :          0 :     rc = PyObject_IsTrue(result);
         184                 :          0 :     Py_DECREF(result);
         185                 :          0 :     return rc;
         186                 :            : }
         187                 :            :
         188                 :            : #define GET_WARNINGS_ATTR(interp, ATTR, try_import) \
         189                 :            :     get_warnings_attr(interp, &_Py_ID(ATTR), try_import)
         190                 :            :
         191                 :            : /*
         192                 :            :    Returns a new reference.
         193                 :            :    A NULL return value can mean false or an error.
         194                 :            : */
         195                 :            : static PyObject *
         196                 :          4 : get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import)
         197                 :            : {
         198                 :            :     PyObject *warnings_module, *obj;
         199                 :            :
         200                 :            :     /* don't try to import after the start of the Python finallization */
         201   [ -  +  -  - ]:          4 :     if (try_import && !_Py_IsFinalizing()) {
         202                 :          0 :         warnings_module = PyImport_Import(&_Py_ID(warnings));
         203         [ #  # ]:          0 :         if (warnings_module == NULL) {
         204                 :            :             /* Fallback to the C implementation if we cannot get
         205                 :            :                the Python implementation */
         206         [ #  # ]:          0 :             if (PyErr_ExceptionMatches(PyExc_ImportError)) {
         207                 :          0 :                 PyErr_Clear();
         208                 :            :             }
         209                 :          0 :             return NULL;
         210                 :            :         }
         211                 :            :     }
         212                 :            :     else {
         213                 :            :         /* if we're so late into Python finalization that the module dict is
         214                 :            :            gone, then we can't even use PyImport_GetModule without triggering
         215                 :            :            an interpreter abort.
         216                 :            :         */
         217         [ -  + ]:          4 :         if (!_PyImport_GetModules(interp)) {
         218                 :          0 :             return NULL;
         219                 :            :         }
         220                 :          4 :         warnings_module = PyImport_GetModule(&_Py_ID(warnings));
         221         [ -  + ]:          4 :         if (warnings_module == NULL)
         222                 :          0 :             return NULL;
         223                 :            :     }
         224                 :            :
         225                 :          4 :     (void)_PyObject_LookupAttr(warnings_module, attr, &obj);
         226                 :          4 :     Py_DECREF(warnings_module);
         227                 :          4 :     return obj;
         228                 :            : }
         229                 :            :
         230                 :            :
         231                 :            : static PyObject *
         232                 :          0 : get_once_registry(PyInterpreterState *interp)
         233                 :            : {
         234                 :            :     PyObject *registry;
         235                 :            :
         236                 :          0 :     WarningsState *st = warnings_get_state(interp);
         237         [ #  # ]:          0 :     if (st == NULL) {
         238                 :          0 :         return NULL;
         239                 :            :     }
         240                 :            :
         241                 :          0 :     registry = GET_WARNINGS_ATTR(interp, onceregistry, 0);
         242         [ #  # ]:          0 :     if (registry == NULL) {
         243         [ #  # ]:          0 :         if (PyErr_Occurred())
         244                 :          0 :             return NULL;
         245                 :            :         assert(st->once_registry);
         246                 :          0 :         return st->once_registry;
         247                 :            :     }
         248         [ #  # ]:          0 :     if (!PyDict_Check(registry)) {
         249                 :          0 :         PyErr_Format(PyExc_TypeError,
         250                 :            :                      MODULE_NAME ".onceregistry must be a dict, "
         251                 :            :                      "not '%.200s'",
         252                 :          0 :                      Py_TYPE(registry)->tp_name);
         253                 :          0 :         Py_DECREF(registry);
         254                 :          0 :         return NULL;
         255                 :            :     }
         256                 :          0 :     Py_SETREF(st->once_registry, registry);
         257                 :          0 :     return registry;
         258                 :            : }
         259                 :            :
         260                 :            :
         261                 :            : static PyObject *
         262                 :          0 : get_default_action(PyInterpreterState *interp)
         263                 :            : {
         264                 :            :     PyObject *default_action;
         265                 :            :
         266                 :          0 :     WarningsState *st = warnings_get_state(interp);
         267         [ #  # ]:          0 :     if (st == NULL) {
         268                 :          0 :         return NULL;
         269                 :            :     }
         270                 :            :
         271                 :          0 :     default_action = GET_WARNINGS_ATTR(interp, defaultaction, 0);
         272         [ #  # ]:          0 :     if (default_action == NULL) {
         273         [ #  # ]:          0 :         if (PyErr_Occurred()) {
         274                 :          0 :             return NULL;
         275                 :            :         }
         276                 :            :         assert(st->default_action);
         277                 :          0 :         return st->default_action;
         278                 :            :     }
         279         [ #  # ]:          0 :     if (!PyUnicode_Check(default_action)) {
         280                 :          0 :         PyErr_Format(PyExc_TypeError,
         281                 :            :                      MODULE_NAME ".defaultaction must be a string, "
         282                 :            :                      "not '%.200s'",
         283                 :          0 :                      Py_TYPE(default_action)->tp_name);
         284                 :          0 :         Py_DECREF(default_action);
         285                 :          0 :         return NULL;
         286                 :            :     }
         287                 :          0 :     Py_SETREF(st->default_action, default_action);
         288                 :          0 :     return default_action;
         289                 :            : }
         290                 :            :
         291                 :            :
         292                 :            : /* The item is a new reference. */
         293                 :            : static PyObject*
         294                 :          4 : get_filter(PyInterpreterState *interp, PyObject *category,
         295                 :            :            PyObject *text, Py_ssize_t lineno,
         296                 :            :            PyObject *module, PyObject **item)
         297                 :            : {
         298                 :            :     PyObject *action;
         299                 :            :     Py_ssize_t i;
         300                 :            :     PyObject *warnings_filters;
         301                 :          4 :     WarningsState *st = warnings_get_state(interp);
         302         [ -  + ]:          4 :     if (st == NULL) {
         303                 :          0 :         return NULL;
         304                 :            :     }
         305                 :            :
         306                 :          4 :     warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
         307         [ -  + ]:          4 :     if (warnings_filters == NULL) {
         308         [ #  # ]:          0 :         if (PyErr_Occurred())
         309                 :          0 :             return NULL;
         310                 :            :     }
         311                 :            :     else {
         312                 :          4 :         Py_SETREF(st->filters, warnings_filters);
         313                 :            :     }
         314                 :            :
         315                 :          4 :     PyObject *filters = st->filters;
         316   [ +  -  -  + ]:          4 :     if (filters == NULL || !PyList_Check(filters)) {
         317                 :          0 :         PyErr_SetString(PyExc_ValueError,
         318                 :            :                         MODULE_NAME ".filters must be a list");
         319                 :          0 :         return NULL;
         320                 :            :     }
         321                 :            :
         322                 :            :     /* WarningsState.filters could change while we are iterating over it. */
         323         [ +  - ]:          4 :     for (i = 0; i < PyList_GET_SIZE(filters); i++) {
         324                 :            :         PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
         325                 :            :         Py_ssize_t ln;
         326                 :            :         int is_subclass, good_msg, good_mod;
         327                 :            :
         328                 :          4 :         tmp_item = PyList_GET_ITEM(filters, i);
         329   [ +  -  -  + ]:          4 :         if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {
         330                 :          0 :             PyErr_Format(PyExc_ValueError,
         331                 :            :                          MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
         332                 :          0 :             return NULL;
         333                 :            :         }
         334                 :            :
         335                 :            :         /* Python code: action, msg, cat, mod, ln = item */
         336                 :          4 :         Py_INCREF(tmp_item);
         337                 :          4 :         action = PyTuple_GET_ITEM(tmp_item, 0);
         338                 :          4 :         msg = PyTuple_GET_ITEM(tmp_item, 1);
         339                 :          4 :         cat = PyTuple_GET_ITEM(tmp_item, 2);
         340                 :          4 :         mod = PyTuple_GET_ITEM(tmp_item, 3);
         341                 :          4 :         ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
         342                 :            :
         343         [ -  + ]:          4 :         if (!PyUnicode_Check(action)) {
         344                 :          0 :             PyErr_Format(PyExc_TypeError,
         345                 :            :                          "action must be a string, not '%.200s'",
         346                 :          0 :                          Py_TYPE(action)->tp_name);
         347                 :          0 :             Py_DECREF(tmp_item);
         348                 :          0 :             return NULL;
         349                 :            :         }
         350                 :            :
         351                 :          4 :         good_msg = check_matched(interp, msg, text);
         352         [ -  + ]:          4 :         if (good_msg == -1) {
         353                 :          0 :             Py_DECREF(tmp_item);
         354                 :          0 :             return NULL;
         355                 :            :         }
         356                 :            :
         357                 :          4 :         good_mod = check_matched(interp, mod, module);
         358         [ -  + ]:          4 :         if (good_mod == -1) {
         359                 :          0 :             Py_DECREF(tmp_item);
         360                 :          0 :             return NULL;
         361                 :            :         }
         362                 :            :
         363                 :          4 :         is_subclass = PyObject_IsSubclass(category, cat);
         364         [ -  + ]:          4 :         if (is_subclass == -1) {
         365                 :          0 :             Py_DECREF(tmp_item);
         366                 :          0 :             return NULL;
         367                 :            :         }
         368                 :            :
         369                 :          4 :         ln = PyLong_AsSsize_t(ln_obj);
         370   [ -  +  -  - ]:          4 :         if (ln == -1 && PyErr_Occurred()) {
         371                 :          0 :             Py_DECREF(tmp_item);
         372                 :          0 :             return NULL;
         373                 :            :         }
         374                 :            :
         375   [ +  -  +  -  :          4 :         if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
              +  -  -  +  -
                          - ]
         376                 :          4 :             *item = tmp_item;
         377                 :          4 :             return action;
         378                 :            :         }
         379                 :            :
         380                 :          0 :         Py_DECREF(tmp_item);
         381                 :            :     }
         382                 :            :
         383                 :          0 :     action = get_default_action(interp);
         384         [ #  # ]:          0 :     if (action != NULL) {
         385                 :          0 :         *item = Py_NewRef(Py_None);
         386                 :          0 :         return action;
         387                 :            :     }
         388                 :            :
         389                 :          0 :     return NULL;
         390                 :            : }
         391                 :            :
         392                 :            :
         393                 :            : static int
         394                 :          4 : already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,
         395                 :            :                int should_set)
         396                 :            : {
         397                 :            :     PyObject *version_obj, *already_warned;
         398                 :            :
         399         [ -  + ]:          4 :     if (key == NULL)
         400                 :          0 :         return -1;
         401                 :            :
         402                 :          4 :     WarningsState *st = warnings_get_state(interp);
         403         [ -  + ]:          4 :     if (st == NULL) {
         404                 :          0 :         return -1;
         405                 :            :     }
         406                 :          4 :     version_obj = _PyDict_GetItemWithError(registry, &_Py_ID(version));
         407         [ +  + ]:          4 :     if (version_obj == NULL
         408         [ +  - ]:          3 :         || !PyLong_CheckExact(version_obj)
         409         [ +  - ]:          3 :         || PyLong_AsLong(version_obj) != st->filters_version)
         410                 :            :     {
         411         [ -  + ]:          4 :         if (PyErr_Occurred()) {
         412                 :          0 :             return -1;
         413                 :            :         }
         414                 :          4 :         PyDict_Clear(registry);
         415                 :          4 :         version_obj = PyLong_FromLong(st->filters_version);
         416         [ -  + ]:          4 :         if (version_obj == NULL)
         417                 :          0 :             return -1;
         418         [ -  + ]:          4 :         if (PyDict_SetItem(registry, &_Py_ID(version), version_obj) < 0) {
         419                 :          0 :             Py_DECREF(version_obj);
         420                 :          0 :             return -1;
         421                 :            :         }
         422                 :          4 :         Py_DECREF(version_obj);
         423                 :            :     }
         424                 :            :     else {
         425                 :          0 :         already_warned = PyDict_GetItemWithError(registry, key);
         426         [ #  # ]:          0 :         if (already_warned != NULL) {
         427                 :          0 :             int rc = PyObject_IsTrue(already_warned);
         428         [ #  # ]:          0 :             if (rc != 0)
         429                 :          0 :                 return rc;
         430                 :            :         }
         431         [ #  # ]:          0 :         else if (PyErr_Occurred()) {
         432                 :          0 :             return -1;
         433                 :            :         }
         434                 :            :     }
         435                 :            :
         436                 :            :     /* This warning wasn't found in the registry, set it. */
         437         [ -  + ]:          4 :     if (should_set)
         438                 :          0 :         return PyDict_SetItem(registry, key, Py_True);
         439                 :          4 :     return 0;
         440                 :            : }
         441                 :            :
         442                 :            : /* New reference. */
         443                 :            : static PyObject *
         444                 :          0 : normalize_module(PyObject *filename)
         445                 :            : {
         446                 :            :     PyObject *module;
         447                 :            :     int kind;
         448                 :            :     const void *data;
         449                 :            :     Py_ssize_t len;
         450                 :            :
         451                 :          0 :     len = PyUnicode_GetLength(filename);
         452         [ #  # ]:          0 :     if (len < 0)
         453                 :          0 :         return NULL;
         454                 :            :
         455         [ #  # ]:          0 :     if (len == 0)
         456                 :          0 :         return PyUnicode_FromString("<unknown>");
         457                 :            :
         458                 :          0 :     kind = PyUnicode_KIND(filename);
         459                 :          0 :     data = PyUnicode_DATA(filename);
         460                 :            :
         461                 :            :     /* if filename.endswith(".py"): */
         462   [ #  #  #  # ]:          0 :     if (len >= 3 &&
         463         [ #  # ]:          0 :         PyUnicode_READ(kind, data, len-3) == '.' &&
         464         [ #  # ]:          0 :         PyUnicode_READ(kind, data, len-2) == 'p' &&
         465                 :          0 :         PyUnicode_READ(kind, data, len-1) == 'y')
         466                 :            :     {
         467                 :          0 :         module = PyUnicode_Substring(filename, 0, len-3);
         468                 :            :     }
         469                 :            :     else {
         470                 :          0 :         module = Py_NewRef(filename);
         471                 :            :     }
         472                 :          0 :     return module;
         473                 :            : }
         474                 :            :
         475                 :            : static int
         476                 :          0 : update_registry(PyInterpreterState *interp, PyObject *registry, PyObject *text,
         477                 :            :                 PyObject *category, int add_zero)
         478                 :            : {
         479                 :            :     PyObject *altkey;
         480                 :            :     int rc;
         481                 :            :
         482         [ #  # ]:          0 :     if (add_zero)
         483                 :          0 :         altkey = PyTuple_Pack(3, text, category, _PyLong_GetZero());
         484                 :            :     else
         485                 :          0 :         altkey = PyTuple_Pack(2, text, category);
         486                 :            :
         487                 :          0 :     rc = already_warned(interp, registry, altkey, 1);
         488                 :          0 :     Py_XDECREF(altkey);
         489                 :          0 :     return rc;
         490                 :            : }
         491                 :            :
         492                 :            : static void
         493                 :          0 : show_warning(PyThreadState *tstate, PyObject *filename, int lineno,
         494                 :            :              PyObject *text, PyObject *category, PyObject *sourceline)
         495                 :            : {
         496                 :            :     PyObject *f_stderr;
         497                 :            :     PyObject *name;
         498                 :            :     char lineno_str[128];
         499                 :            :
         500                 :          0 :     PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
         501                 :            :
         502                 :          0 :     name = PyObject_GetAttr(category, &_Py_ID(__name__));
         503         [ #  # ]:          0 :     if (name == NULL) {
         504                 :          0 :         goto error;
         505                 :            :     }
         506                 :            :
         507                 :          0 :     f_stderr = _PySys_GetAttr(tstate, &_Py_ID(stderr));
         508         [ #  # ]:          0 :     if (f_stderr == NULL) {
         509                 :          0 :         fprintf(stderr, "lost sys.stderr\n");
         510                 :          0 :         goto error;
         511                 :            :     }
         512                 :            :
         513                 :            :     /* Print "filename:lineno: category: text\n" */
         514         [ #  # ]:          0 :     if (PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW) < 0)
         515                 :          0 :         goto error;
         516         [ #  # ]:          0 :     if (PyFile_WriteString(lineno_str, f_stderr) < 0)
         517                 :          0 :         goto error;
         518         [ #  # ]:          0 :     if (PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW) < 0)
         519                 :          0 :         goto error;
         520         [ #  # ]:          0 :     if (PyFile_WriteString(": ", f_stderr) < 0)
         521                 :          0 :         goto error;
         522         [ #  # ]:          0 :     if (PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW) < 0)
         523                 :          0 :         goto error;
         524         [ #  # ]:          0 :     if (PyFile_WriteString("\n", f_stderr) < 0)
         525                 :          0 :         goto error;
         526         [ #  # ]:          0 :     Py_CLEAR(name);
         527                 :            :
         528                 :            :     /* Print "  source_line\n" */
         529         [ #  # ]:          0 :     if (sourceline) {
         530                 :            :         int kind;
         531                 :            :         const void *data;
         532                 :            :         Py_ssize_t i, len;
         533                 :            :         Py_UCS4 ch;
         534                 :            :         PyObject *truncated;
         535                 :            :
         536         [ #  # ]:          0 :         if (PyUnicode_READY(sourceline) < 1)
         537                 :          0 :             goto error;
         538                 :            :
         539                 :          0 :         kind = PyUnicode_KIND(sourceline);
         540                 :          0 :         data = PyUnicode_DATA(sourceline);
         541                 :          0 :         len = PyUnicode_GET_LENGTH(sourceline);
         542         [ #  # ]:          0 :         for (i=0; i<len; i++) {
         543                 :          0 :             ch = PyUnicode_READ(kind, data, i);
         544   [ #  #  #  #  :          0 :             if (ch != ' ' && ch != '\t' && ch != '\014')
                       #  # ]
         545                 :          0 :                 break;
         546                 :            :         }
         547                 :            :
         548                 :          0 :         truncated = PyUnicode_Substring(sourceline, i, len);
         549         [ #  # ]:          0 :         if (truncated == NULL)
         550                 :          0 :             goto error;
         551                 :            :
         552                 :          0 :         PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW);
         553                 :          0 :         Py_DECREF(truncated);
         554                 :          0 :         PyFile_WriteString("\n", f_stderr);
         555                 :            :     }
         556                 :            :     else {
         557                 :          0 :         _Py_DisplaySourceLine(f_stderr, filename, lineno, 2, NULL, NULL);
         558                 :            :     }
         559                 :            :
         560                 :          0 : error:
         561                 :          0 :     Py_XDECREF(name);
         562                 :          0 :     PyErr_Clear();
         563                 :          0 : }
         564                 :            :
         565                 :            : static int
         566                 :          0 : call_show_warning(PyThreadState *tstate, PyObject *category,
         567                 :            :                   PyObject *text, PyObject *message,
         568                 :            :                   PyObject *filename, int lineno, PyObject *lineno_obj,
         569                 :            :                   PyObject *sourceline, PyObject *source)
         570                 :            : {
         571                 :          0 :     PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;
         572                 :          0 :     PyInterpreterState *interp = tstate->interp;
         573                 :            :
         574                 :            :     /* If the source parameter is set, try to get the Python implementation.
         575                 :            :        The Python implementation is able to log the traceback where the source
         576                 :            :        was allocated, whereas the C implementation doesn't. */
         577                 :          0 :     show_fn = GET_WARNINGS_ATTR(interp, _showwarnmsg, source != NULL);
         578         [ #  # ]:          0 :     if (show_fn == NULL) {
         579         [ #  # ]:          0 :         if (PyErr_Occurred())
         580                 :          0 :             return -1;
         581                 :          0 :         show_warning(tstate, filename, lineno, text, category, sourceline);
         582                 :          0 :         return 0;
         583                 :            :     }
         584                 :            :
         585         [ #  # ]:          0 :     if (!PyCallable_Check(show_fn)) {
         586                 :          0 :         PyErr_SetString(PyExc_TypeError,
         587                 :            :                 "warnings._showwarnmsg() must be set to a callable");
         588                 :          0 :         goto error;
         589                 :            :     }
         590                 :            :
         591                 :          0 :     warnmsg_cls = GET_WARNINGS_ATTR(interp, WarningMessage, 0);
         592         [ #  # ]:          0 :     if (warnmsg_cls == NULL) {
         593         [ #  # ]:          0 :         if (!PyErr_Occurred()) {
         594                 :          0 :             PyErr_SetString(PyExc_RuntimeError,
         595                 :            :                     "unable to get warnings.WarningMessage");
         596                 :            :         }
         597                 :          0 :         goto error;
         598                 :            :     }
         599                 :            :
         600                 :          0 :     msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category,
         601                 :            :             filename, lineno_obj, Py_None, Py_None, source,
         602                 :            :             NULL);
         603                 :          0 :     Py_DECREF(warnmsg_cls);
         604         [ #  # ]:          0 :     if (msg == NULL)
         605                 :          0 :         goto error;
         606                 :            :
         607                 :          0 :     res = PyObject_CallOneArg(show_fn, msg);
         608                 :          0 :     Py_DECREF(show_fn);
         609                 :          0 :     Py_DECREF(msg);
         610                 :            :
         611         [ #  # ]:          0 :     if (res == NULL)
         612                 :          0 :         return -1;
         613                 :            :
         614                 :          0 :     Py_DECREF(res);
         615                 :          0 :     return 0;
         616                 :            :
         617                 :          0 : error:
         618                 :          0 :     Py_XDECREF(show_fn);
         619                 :          0 :     return -1;
         620                 :            : }
         621                 :            :
         622                 :            : static PyObject *
         623                 :          4 : warn_explicit(PyThreadState *tstate, PyObject *category, PyObject *message,
         624                 :            :               PyObject *filename, int lineno,
         625                 :            :               PyObject *module, PyObject *registry, PyObject *sourceline,
         626                 :            :               PyObject *source)
         627                 :            : {
         628                 :          4 :     PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
         629                 :          4 :     PyObject *item = NULL;
         630                 :            :     PyObject *action;
         631                 :            :     int rc;
         632                 :          4 :     PyInterpreterState *interp = tstate->interp;
         633                 :            :
         634                 :            :     /* module can be None if a warning is emitted late during Python shutdown.
         635                 :            :        In this case, the Python warnings module was probably unloaded, filters
         636                 :            :        are no more available to choose as action. It is safer to ignore the
         637                 :            :        warning and do nothing. */
         638         [ -  + ]:          4 :     if (module == Py_None)
         639                 :          0 :         Py_RETURN_NONE;
         640                 :            :
         641   [ +  -  -  +  :          4 :     if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
                       -  - ]
         642                 :          0 :         PyErr_SetString(PyExc_TypeError, "'registry' must be a dict or None");
         643                 :          0 :         return NULL;
         644                 :            :     }
         645                 :            :
         646                 :            :     /* Normalize module. */
         647         [ -  + ]:          4 :     if (module == NULL) {
         648                 :          0 :         module = normalize_module(filename);
         649         [ #  # ]:          0 :         if (module == NULL)
         650                 :          0 :             return NULL;
         651                 :            :     }
         652                 :            :     else
         653                 :          4 :         Py_INCREF(module);
         654                 :            :
         655                 :            :     /* Normalize message. */
         656                 :          4 :     Py_INCREF(message);  /* DECREF'ed in cleanup. */
         657                 :          4 :     rc = PyObject_IsInstance(message, PyExc_Warning);
         658         [ -  + ]:          4 :     if (rc == -1) {
         659                 :          0 :         goto cleanup;
         660                 :            :     }
         661         [ -  + ]:          4 :     if (rc == 1) {
         662                 :          0 :         text = PyObject_Str(message);
         663         [ #  # ]:          0 :         if (text == NULL)
         664                 :          0 :             goto cleanup;
         665                 :          0 :         category = (PyObject*)Py_TYPE(message);
         666                 :            :     }
         667                 :            :     else {
         668                 :          4 :         text = message;
         669                 :          4 :         message = PyObject_CallOneArg(category, message);
         670         [ -  + ]:          4 :         if (message == NULL)
         671                 :          0 :             goto cleanup;
         672                 :            :     }
         673                 :            :
         674                 :          4 :     lineno_obj = PyLong_FromLong(lineno);
         675         [ -  + ]:          4 :     if (lineno_obj == NULL)
         676                 :          0 :         goto cleanup;
         677                 :            :
         678         [ -  + ]:          4 :     if (source == Py_None) {
         679                 :          0 :         source = NULL;
         680                 :            :     }
         681                 :            :
         682                 :            :     /* Create key. */
         683                 :          4 :     key = PyTuple_Pack(3, text, category, lineno_obj);
         684         [ -  + ]:          4 :     if (key == NULL)
         685                 :          0 :         goto cleanup;
         686                 :            :
         687   [ +  -  +  - ]:          4 :     if ((registry != NULL) && (registry != Py_None)) {
         688                 :          4 :         rc = already_warned(interp, registry, key, 0);
         689         [ -  + ]:          4 :         if (rc == -1)
         690                 :          0 :             goto cleanup;
         691         [ -  + ]:          4 :         else if (rc == 1)
         692                 :          0 :             goto return_none;
         693                 :            :         /* Else this warning hasn't been generated before. */
         694                 :            :     }
         695                 :            :
         696                 :          4 :     action = get_filter(interp, category, text, lineno, module, &item);
         697         [ -  + ]:          4 :     if (action == NULL)
         698                 :          0 :         goto cleanup;
         699                 :            :
         700         [ -  + ]:          4 :     if (_PyUnicode_EqualToASCIIString(action, "error")) {
         701                 :          0 :         PyErr_SetObject(category, message);
         702                 :          0 :         goto cleanup;
         703                 :            :     }
         704                 :            :
         705         [ +  - ]:          4 :     if (_PyUnicode_EqualToASCIIString(action, "ignore")) {
         706                 :          4 :         goto return_none;
         707                 :            :     }
         708                 :            :
         709                 :            :     /* Store in the registry that we've been here, *except* when the action
         710                 :            :        is "always". */
         711                 :          0 :     rc = 0;
         712         [ #  # ]:          0 :     if (!_PyUnicode_EqualToASCIIString(action, "always")) {
         713   [ #  #  #  #  :          0 :         if (registry != NULL && registry != Py_None &&
                       #  # ]
         714                 :          0 :             PyDict_SetItem(registry, key, Py_True) < 0)
         715                 :            :         {
         716                 :          0 :             goto cleanup;
         717                 :            :         }
         718                 :            :
         719         [ #  # ]:          0 :         if (_PyUnicode_EqualToASCIIString(action, "once")) {
         720   [ #  #  #  # ]:          0 :             if (registry == NULL || registry == Py_None) {
         721                 :          0 :                 registry = get_once_registry(interp);
         722         [ #  # ]:          0 :                 if (registry == NULL)
         723                 :          0 :                     goto cleanup;
         724                 :            :             }
         725                 :            :             /* WarningsState.once_registry[(text, category)] = 1 */
         726                 :          0 :             rc = update_registry(interp, registry, text, category, 0);
         727                 :            :         }
         728         [ #  # ]:          0 :         else if (_PyUnicode_EqualToASCIIString(action, "module")) {
         729                 :            :             /* registry[(text, category, 0)] = 1 */
         730   [ #  #  #  # ]:          0 :             if (registry != NULL && registry != Py_None)
         731                 :          0 :                 rc = update_registry(interp, registry, text, category, 0);
         732                 :            :         }
         733         [ #  # ]:          0 :         else if (!_PyUnicode_EqualToASCIIString(action, "default")) {
         734                 :          0 :             PyErr_Format(PyExc_RuntimeError,
         735                 :            :                         "Unrecognized action (%R) in warnings.filters:\n %R",
         736                 :            :                         action, item);
         737                 :          0 :             goto cleanup;
         738                 :            :         }
         739                 :            :     }
         740                 :            :
         741         [ #  # ]:          0 :     if (rc == 1)  /* Already warned for this module. */
         742                 :          0 :         goto return_none;
         743         [ #  # ]:          0 :     if (rc == 0) {
         744         [ #  # ]:          0 :         if (call_show_warning(tstate, category, text, message, filename,
         745                 :            :                               lineno, lineno_obj, sourceline, source) < 0)
         746                 :          0 :             goto cleanup;
         747                 :            :     }
         748                 :            :     else /* if (rc == -1) */
         749                 :          0 :         goto cleanup;
         750                 :            :
         751                 :          4 :  return_none:
         752                 :          4 :     result = Py_NewRef(Py_None);
         753                 :            :
         754                 :          4 :  cleanup:
         755                 :          4 :     Py_XDECREF(item);
         756                 :          4 :     Py_XDECREF(key);
         757                 :          4 :     Py_XDECREF(text);
         758                 :          4 :     Py_XDECREF(lineno_obj);
         759                 :          4 :     Py_DECREF(module);
         760                 :          4 :     Py_XDECREF(message);
         761                 :          4 :     return result;  /* Py_None or NULL. */
         762                 :            : }
         763                 :            :
         764                 :            : static PyObject *
         765                 :          4 : get_frame_filename(PyFrameObject *frame)
         766                 :            : {
         767                 :          4 :     PyCodeObject *code = PyFrame_GetCode(frame);
         768                 :          4 :     PyObject *filename = code->co_filename;
         769                 :          4 :     Py_DECREF(code);
         770                 :          4 :     return filename;
         771                 :            : }
         772                 :            :
         773                 :            : static bool
         774                 :          4 : is_internal_filename(PyObject *filename)
         775                 :            : {
         776         [ -  + ]:          4 :     if (!PyUnicode_Check(filename)) {
         777                 :          0 :         return false;
         778                 :            :     }
         779                 :            :
         780                 :          4 :     int contains = PyUnicode_Contains(filename, &_Py_ID(importlib));
         781         [ -  + ]:          4 :     if (contains < 0) {
         782                 :          0 :         return false;
         783                 :            :     }
         784         [ +  - ]:          4 :     else if (contains > 0) {
         785                 :          4 :         contains = PyUnicode_Contains(filename, &_Py_ID(_bootstrap));
         786         [ -  + ]:          4 :         if (contains < 0) {
         787                 :          0 :             return false;
         788                 :            :         }
         789         [ +  - ]:          4 :         else if (contains > 0) {
         790                 :          4 :             return true;
         791                 :            :         }
         792                 :            :     }
         793                 :            :
         794                 :          0 :     return false;
         795                 :            : }
         796                 :            :
         797                 :            : static bool
         798                 :          0 : is_filename_to_skip(PyObject *filename, PyTupleObject *skip_file_prefixes)
         799                 :            : {
         800         [ #  # ]:          0 :     if (skip_file_prefixes) {
         801         [ #  # ]:          0 :         if (!PyUnicode_Check(filename)) {
         802                 :          0 :             return false;
         803                 :            :         }
         804                 :            :
         805                 :          0 :         Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
         806         [ #  # ]:          0 :         for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
         807                 :            :         {
         808                 :          0 :             PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
         809                 :          0 :             Py_ssize_t found = PyUnicode_Tailmatch(filename, prefix, 0, -1, -1);
         810         [ #  # ]:          0 :             if (found == 1) {
         811                 :          0 :                 return true;
         812                 :            :             }
         813         [ #  # ]:          0 :             if (found < 0) {
         814                 :          0 :                 return false;
         815                 :            :             }
         816                 :            :         }
         817                 :            :     }
         818                 :          0 :     return false;
         819                 :            : }
         820                 :            :
         821                 :            : static bool
         822                 :          4 : is_internal_frame(PyFrameObject *frame)
         823                 :            : {
         824         [ -  + ]:          4 :     if (frame == NULL) {
         825                 :          0 :         return false;
         826                 :            :     }
         827                 :            :
         828                 :          4 :     PyObject *filename = get_frame_filename(frame);
         829         [ -  + ]:          4 :     if (filename == NULL) {
         830                 :          0 :         return false;
         831                 :            :     }
         832                 :            :
         833                 :          4 :     return is_internal_filename(filename);
         834                 :            : }
         835                 :            :
         836                 :            : static PyFrameObject *
         837                 :          0 : next_external_frame(PyFrameObject *frame, PyTupleObject *skip_file_prefixes)
         838                 :            : {
         839                 :            :     PyObject *frame_filename;
         840                 :            :     do {
         841                 :          0 :         PyFrameObject *back = PyFrame_GetBack(frame);
         842                 :          0 :         Py_SETREF(frame, back);
         843   [ #  #  #  # ]:          0 :     } while (frame != NULL && (frame_filename = get_frame_filename(frame)) &&
         844         [ #  # ]:          0 :              (is_internal_filename(frame_filename) ||
         845         [ #  # ]:          0 :               is_filename_to_skip(frame_filename, skip_file_prefixes)));
         846                 :            :
         847                 :          0 :     return frame;
         848                 :            : }
         849                 :            :
         850                 :            : /* filename, module, and registry are new refs, globals is borrowed */
         851                 :            : /* skip_file_prefixes is either NULL or a tuple of strs. */
         852                 :            : /* Returns 0 on error (no new refs), 1 on success */
         853                 :            : static int
         854                 :          4 : setup_context(Py_ssize_t stack_level,
         855                 :            :               PyTupleObject *skip_file_prefixes,
         856                 :            :               PyObject **filename, int *lineno,
         857                 :            :               PyObject **module, PyObject **registry)
         858                 :            : {
         859                 :            :     PyObject *globals;
         860                 :            :
         861                 :            :     /* Setup globals, filename and lineno. */
         862                 :          4 :     PyThreadState *tstate = get_current_tstate();
         863         [ -  + ]:          4 :     if (tstate == NULL) {
         864                 :          0 :         return 0;
         865                 :            :     }
         866         [ -  + ]:          4 :     if (skip_file_prefixes) {
         867                 :            :         /* Type check our data structure up front. Later code that uses it
         868                 :            :          * isn't structured to report errors. */
         869                 :          0 :         Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
         870         [ #  # ]:          0 :         for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
         871                 :            :         {
         872                 :          0 :             PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
         873         [ #  # ]:          0 :             if (!PyUnicode_Check(prefix)) {
         874                 :          0 :                 PyErr_Format(PyExc_TypeError,
         875                 :            :                              "Found non-str '%s' in skip_file_prefixes.",
         876                 :          0 :                              Py_TYPE(prefix)->tp_name);
         877                 :          0 :                 return 0;
         878                 :            :             }
         879                 :            :         }
         880                 :            :     }
         881                 :          4 :     PyInterpreterState *interp = tstate->interp;
         882                 :          4 :     PyFrameObject *f = PyThreadState_GetFrame(tstate);
         883                 :            :     // Stack level comparisons to Python code is off by one as there is no
         884                 :            :     // warnings-related stack level to avoid.
         885   [ +  -  +  - ]:          4 :     if (stack_level <= 0 || is_internal_frame(f)) {
         886   [ +  +  +  - ]:         28 :         while (--stack_level > 0 && f != NULL) {
         887                 :         24 :             PyFrameObject *back = PyFrame_GetBack(f);
         888                 :         24 :             Py_SETREF(f, back);
         889                 :            :         }
         890                 :            :     }
         891                 :            :     else {
         892   [ #  #  #  # ]:          0 :         while (--stack_level > 0 && f != NULL) {
         893                 :          0 :             f = next_external_frame(f, skip_file_prefixes);
         894                 :            :         }
         895                 :            :     }
         896                 :            :
         897         [ -  + ]:          4 :     if (f == NULL) {
         898                 :          0 :         globals = interp->sysdict;
         899                 :          0 :         *filename = PyUnicode_FromString("sys");
         900                 :          0 :         *lineno = 1;
         901                 :            :     }
         902                 :            :     else {
         903                 :          4 :         globals = f->f_frame->f_globals;
         904                 :          4 :         *filename = Py_NewRef(f->f_frame->f_code->co_filename);
         905                 :          4 :         *lineno = PyFrame_GetLineNumber(f);
         906                 :          4 :         Py_DECREF(f);
         907                 :            :     }
         908                 :            :
         909                 :          4 :     *module = NULL;
         910                 :            :
         911                 :            :     /* Setup registry. */
         912                 :            :     assert(globals != NULL);
         913                 :            :     assert(PyDict_Check(globals));
         914                 :          4 :     *registry = _PyDict_GetItemWithError(globals, &_Py_ID(__warningregistry__));
         915         [ +  + ]:          4 :     if (*registry == NULL) {
         916                 :            :         int rc;
         917                 :            :
         918         [ -  + ]:          1 :         if (_PyErr_Occurred(tstate)) {
         919                 :          0 :             goto handle_error;
         920                 :            :         }
         921                 :          1 :         *registry = PyDict_New();
         922         [ -  + ]:          1 :         if (*registry == NULL)
         923                 :          0 :             goto handle_error;
         924                 :            :
         925                 :          1 :          rc = PyDict_SetItem(globals, &_Py_ID(__warningregistry__), *registry);
         926         [ -  + ]:          1 :          if (rc < 0)
         927                 :          0 :             goto handle_error;
         928                 :            :     }
         929                 :            :     else
         930                 :          3 :         Py_INCREF(*registry);
         931                 :            :
         932                 :            :     /* Setup module. */
         933                 :          4 :     *module = _PyDict_GetItemWithError(globals, &_Py_ID(__name__));
         934   [ +  -  +  -  :          4 :     if (*module == Py_None || (*module != NULL && PyUnicode_Check(*module))) {
                       +  - ]
         935                 :          4 :         Py_INCREF(*module);
         936                 :            :     }
         937         [ #  # ]:          0 :     else if (_PyErr_Occurred(tstate)) {
         938                 :          0 :         goto handle_error;
         939                 :            :     }
         940                 :            :     else {
         941                 :          0 :         *module = PyUnicode_FromString("<string>");
         942         [ #  # ]:          0 :         if (*module == NULL)
         943                 :          0 :             goto handle_error;
         944                 :            :     }
         945                 :            :
         946                 :          4 :     return 1;
         947                 :            :
         948                 :          0 :  handle_error:
         949                 :          0 :     Py_XDECREF(*registry);
         950                 :          0 :     Py_XDECREF(*module);
         951                 :          0 :     Py_DECREF(*filename);
         952                 :          0 :     return 0;
         953                 :            : }
         954                 :            :
         955                 :            : static PyObject *
         956                 :          0 : get_category(PyObject *message, PyObject *category)
         957                 :            : {
         958                 :            :     int rc;
         959                 :            :
         960                 :            :     /* Get category. */
         961                 :          0 :     rc = PyObject_IsInstance(message, PyExc_Warning);
         962         [ #  # ]:          0 :     if (rc == -1)
         963                 :          0 :         return NULL;
         964                 :            :
         965         [ #  # ]:          0 :     if (rc == 1)
         966                 :          0 :         category = (PyObject*)Py_TYPE(message);
         967   [ #  #  #  # ]:          0 :     else if (category == NULL || category == Py_None)
         968                 :          0 :         category = PyExc_UserWarning;
         969                 :            :
         970                 :            :     /* Validate category. */
         971                 :          0 :     rc = PyObject_IsSubclass(category, PyExc_Warning);
         972                 :            :     /* category is not a subclass of PyExc_Warning or
         973                 :            :        PyObject_IsSubclass raised an error */
         974   [ #  #  #  # ]:          0 :     if (rc == -1 || rc == 0) {
         975                 :          0 :         PyErr_Format(PyExc_TypeError,
         976                 :            :                      "category must be a Warning subclass, not '%s'",
         977                 :          0 :                      Py_TYPE(category)->tp_name);
         978                 :          0 :         return NULL;
         979                 :            :     }
         980                 :            :
         981                 :          0 :     return category;
         982                 :            : }
         983                 :            :
         984                 :            : static PyObject *
         985                 :          4 : do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
         986                 :            :         PyObject *source, PyTupleObject *skip_file_prefixes)
         987                 :            : {
         988                 :            :     PyObject *filename, *module, *registry, *res;
         989                 :            :     int lineno;
         990                 :            :
         991                 :          4 :     PyThreadState *tstate = get_current_tstate();
         992         [ -  + ]:          4 :     if (tstate == NULL) {
         993                 :          0 :         return NULL;
         994                 :            :     }
         995                 :            :
         996         [ -  + ]:          4 :     if (!setup_context(stack_level, skip_file_prefixes,
         997                 :            :                        &filename, &lineno, &module, &registry))
         998                 :          0 :         return NULL;
         999                 :            :
        1000                 :          4 :     res = warn_explicit(tstate, category, message, filename, lineno, module, registry,
        1001                 :            :                         NULL, source);
        1002                 :          4 :     Py_DECREF(filename);
        1003                 :          4 :     Py_DECREF(registry);
        1004                 :          4 :     Py_DECREF(module);
        1005                 :          4 :     return res;
        1006                 :            : }
        1007                 :            :
        1008                 :            : /*[clinic input]
        1009                 :            : warn as warnings_warn
        1010                 :            :
        1011                 :            :     message: object
        1012                 :            :       Text of the warning message.
        1013                 :            :     category: object = None
        1014                 :            :       The Warning category subclass. Defaults to UserWarning.
        1015                 :            :     stacklevel: Py_ssize_t = 1
        1016                 :            :       How far up the call stack to make this warning appear. A value of 2 for
        1017                 :            :       example attributes the warning to the caller of the code calling warn().
        1018                 :            :     source: object = None
        1019                 :            :       If supplied, the destroyed object which emitted a ResourceWarning
        1020                 :            :     *
        1021                 :            :     skip_file_prefixes: object(type='PyTupleObject *', subclass_of='&PyTuple_Type') = NULL
        1022                 :            :       An optional tuple of module filename prefixes indicating frames to skip
        1023                 :            :       during stacklevel computations for stack frame attribution.
        1024                 :            :
        1025                 :            : Issue a warning, or maybe ignore it or raise an exception.
        1026                 :            : [clinic start generated code]*/
        1027                 :            :
        1028                 :            : static PyObject *
        1029                 :          0 : warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
        1030                 :            :                    Py_ssize_t stacklevel, PyObject *source,
        1031                 :            :                    PyTupleObject *skip_file_prefixes)
        1032                 :            : /*[clinic end generated code: output=a68e0f6906c65f80 input=eb37c6a18bec4ea1]*/
        1033                 :            : {
        1034                 :          0 :     category = get_category(message, category);
        1035         [ #  # ]:          0 :     if (category == NULL)
        1036                 :          0 :         return NULL;
        1037         [ #  # ]:          0 :     if (skip_file_prefixes) {
        1038         [ #  # ]:          0 :         if (PyTuple_GET_SIZE(skip_file_prefixes) > 0) {
        1039         [ #  # ]:          0 :             if (stacklevel < 2) {
        1040                 :          0 :                 stacklevel = 2;
        1041                 :            :             }
        1042                 :            :         } else {
        1043                 :          0 :             Py_DECREF((PyObject *)skip_file_prefixes);
        1044                 :          0 :             skip_file_prefixes = NULL;
        1045                 :            :         }
        1046                 :            :     }
        1047                 :          0 :     return do_warn(message, category, stacklevel, source, skip_file_prefixes);
        1048                 :            : }
        1049                 :            :
        1050                 :            : static PyObject *
        1051                 :          0 : get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno)
        1052                 :            : {
        1053                 :            :     PyObject *loader;
        1054                 :            :     PyObject *module_name;
        1055                 :            :     PyObject *get_source;
        1056                 :            :     PyObject *source;
        1057                 :            :     PyObject *source_list;
        1058                 :            :     PyObject *source_line;
        1059                 :            :
        1060                 :            :     /* stolen from import.c */
        1061                 :          0 :     loader = _PyImport_BlessMyLoader(interp, module_globals);
        1062         [ #  # ]:          0 :     if (loader == NULL) {
        1063                 :          0 :         return NULL;
        1064                 :            :     }
        1065                 :            :
        1066                 :          0 :     module_name = _PyDict_GetItemWithError(module_globals, &_Py_ID(__name__));
        1067         [ #  # ]:          0 :     if (!module_name) {
        1068                 :          0 :         Py_DECREF(loader);
        1069                 :          0 :         return NULL;
        1070                 :            :     }
        1071                 :          0 :     Py_INCREF(module_name);
        1072                 :            :
        1073                 :            :     /* Make sure the loader implements the optional get_source() method. */
        1074                 :          0 :     (void)_PyObject_LookupAttr(loader, &_Py_ID(get_source), &get_source);
        1075                 :          0 :     Py_DECREF(loader);
        1076         [ #  # ]:          0 :     if (!get_source) {
        1077                 :          0 :         Py_DECREF(module_name);
        1078                 :          0 :         return NULL;
        1079                 :            :     }
        1080                 :            :     /* Call get_source() to get the source code. */
        1081                 :          0 :     source = PyObject_CallOneArg(get_source, module_name);
        1082                 :          0 :     Py_DECREF(get_source);
        1083                 :          0 :     Py_DECREF(module_name);
        1084         [ #  # ]:          0 :     if (!source) {
        1085                 :          0 :         return NULL;
        1086                 :            :     }
        1087         [ #  # ]:          0 :     if (source == Py_None) {
        1088                 :          0 :         Py_DECREF(source);
        1089                 :          0 :         return NULL;
        1090                 :            :     }
        1091                 :            :
        1092                 :            :     /* Split the source into lines. */
        1093                 :          0 :     source_list = PyUnicode_Splitlines(source, 0);
        1094                 :          0 :     Py_DECREF(source);
        1095         [ #  # ]:          0 :     if (!source_list) {
        1096                 :          0 :         return NULL;
        1097                 :            :     }
        1098                 :            :
        1099                 :            :     /* Get the source line. */
        1100                 :          0 :     source_line = PyList_GetItem(source_list, lineno-1);
        1101                 :          0 :     Py_XINCREF(source_line);
        1102                 :          0 :     Py_DECREF(source_list);
        1103                 :          0 :     return source_line;
        1104                 :            : }
        1105                 :            :
        1106                 :            : /*[clinic input]
        1107                 :            : warn_explicit as warnings_warn_explicit
        1108                 :            :
        1109                 :            :     message: object
        1110                 :            :     category: object
        1111                 :            :     filename: unicode
        1112                 :            :     lineno: int
        1113                 :            :     module as mod: object = NULL
        1114                 :            :     registry: object = None
        1115                 :            :     module_globals: object = None
        1116                 :            :     source as sourceobj: object = None
        1117                 :            :
        1118                 :            : Issue a warning, or maybe ignore it or raise an exception.
        1119                 :            : [clinic start generated code]*/
        1120                 :            :
        1121                 :            : static PyObject *
        1122                 :          0 : warnings_warn_explicit_impl(PyObject *module, PyObject *message,
        1123                 :            :                             PyObject *category, PyObject *filename,
        1124                 :            :                             int lineno, PyObject *mod, PyObject *registry,
        1125                 :            :                             PyObject *module_globals, PyObject *sourceobj)
        1126                 :            : /*[clinic end generated code: output=c49c62b15a49a186 input=df6eeb8b45e712f1]*/
        1127                 :            : {
        1128                 :          0 :     PyObject *source_line = NULL;
        1129                 :            :     PyObject *returned;
        1130                 :            :
        1131                 :          0 :     PyThreadState *tstate = get_current_tstate();
        1132         [ #  # ]:          0 :     if (tstate == NULL) {
        1133                 :          0 :         return NULL;
        1134                 :            :     }
        1135                 :            :
        1136   [ #  #  #  # ]:          0 :     if (module_globals && module_globals != Py_None) {
        1137         [ #  # ]:          0 :         if (!PyDict_Check(module_globals)) {
        1138                 :          0 :             PyErr_Format(PyExc_TypeError,
        1139                 :            :                          "module_globals must be a dict, not '%.200s'",
        1140                 :          0 :                          Py_TYPE(module_globals)->tp_name);
        1141                 :          0 :             return NULL;
        1142                 :            :         }
        1143                 :            :
        1144                 :          0 :         source_line = get_source_line(tstate->interp, module_globals, lineno);
        1145   [ #  #  #  # ]:          0 :         if (source_line == NULL && PyErr_Occurred()) {
        1146                 :          0 :             return NULL;
        1147                 :            :         }
        1148                 :            :     }
        1149                 :          0 :     returned = warn_explicit(tstate, category, message, filename, lineno,
        1150                 :            :                              mod, registry, source_line, sourceobj);
        1151                 :          0 :     Py_XDECREF(source_line);
        1152                 :          0 :     return returned;
        1153                 :            : }
        1154                 :            :
        1155                 :            : /*[clinic input]
        1156                 :            : _filters_mutated as warnings_filters_mutated
        1157                 :            :
        1158                 :            : [clinic start generated code]*/
        1159                 :            :
        1160                 :            : static PyObject *
        1161                 :        330 : warnings_filters_mutated_impl(PyObject *module)
        1162                 :            : /*[clinic end generated code: output=8ce517abd12b88f4 input=35ecbf08ee2491b2]*/
        1163                 :            : {
        1164                 :        330 :     PyInterpreterState *interp = get_current_interp();
        1165         [ -  + ]:        330 :     if (interp == NULL) {
        1166                 :          0 :         return NULL;
        1167                 :            :     }
        1168                 :        330 :     WarningsState *st = warnings_get_state(interp);
        1169         [ -  + ]:        330 :     if (st == NULL) {
        1170                 :          0 :         return NULL;
        1171                 :            :     }
        1172                 :        330 :     st->filters_version++;
        1173                 :        330 :     Py_RETURN_NONE;
        1174                 :            : }
        1175                 :            :
        1176                 :            :
        1177                 :            : /* Function to issue a warning message; may raise an exception. */
        1178                 :            :
        1179                 :            : static int
        1180                 :          4 : warn_unicode(PyObject *category, PyObject *message,
        1181                 :            :              Py_ssize_t stack_level, PyObject *source)
        1182                 :            : {
        1183                 :            :     PyObject *res;
        1184                 :            :
        1185         [ -  + ]:          4 :     if (category == NULL)
        1186                 :          0 :         category = PyExc_RuntimeWarning;
        1187                 :            :
        1188                 :          4 :     res = do_warn(message, category, stack_level, source, NULL);
        1189         [ -  + ]:          4 :     if (res == NULL)
        1190                 :          0 :         return -1;
        1191                 :          4 :     Py_DECREF(res);
        1192                 :            :
        1193                 :          4 :     return 0;
        1194                 :            : }
        1195                 :            :
        1196                 :            : static int
        1197                 :          0 : _PyErr_WarnFormatV(PyObject *source,
        1198                 :            :                    PyObject *category, Py_ssize_t stack_level,
        1199                 :            :                    const char *format, va_list vargs)
        1200                 :            : {
        1201                 :            :     PyObject *message;
        1202                 :            :     int res;
        1203                 :            :
        1204                 :          0 :     message = PyUnicode_FromFormatV(format, vargs);
        1205         [ #  # ]:          0 :     if (message == NULL)
        1206                 :          0 :         return -1;
        1207                 :            :
        1208                 :          0 :     res = warn_unicode(category, message, stack_level, source);
        1209                 :          0 :     Py_DECREF(message);
        1210                 :          0 :     return res;
        1211                 :            : }
        1212                 :            :
        1213                 :            : int
        1214                 :          0 : PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
        1215                 :            :                  const char *format, ...)
        1216                 :            : {
        1217                 :            :     int res;
        1218                 :            :     va_list vargs;
        1219                 :            :
        1220                 :          0 :     va_start(vargs, format);
        1221                 :          0 :     res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
        1222                 :          0 :     va_end(vargs);
        1223                 :          0 :     return res;
        1224                 :            : }
        1225                 :            :
        1226                 :            : static int
        1227                 :          0 : _PyErr_WarnFormat(PyObject *source, PyObject *category, Py_ssize_t stack_level,
        1228                 :            :                   const char *format, ...)
        1229                 :            : {
        1230                 :            :     int res;
        1231                 :            :     va_list vargs;
        1232                 :            :
        1233                 :          0 :     va_start(vargs, format);
        1234                 :          0 :     res = _PyErr_WarnFormatV(source, category, stack_level, format, vargs);
        1235                 :          0 :     va_end(vargs);
        1236                 :          0 :     return res;
        1237                 :            : }
        1238                 :            :
        1239                 :            : int
        1240                 :          0 : PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
        1241                 :            :                       const char *format, ...)
        1242                 :            : {
        1243                 :            :     int res;
        1244                 :            :     va_list vargs;
        1245                 :            :
        1246                 :          0 :     va_start(vargs, format);
        1247                 :          0 :     res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
        1248                 :            :                              stack_level, format, vargs);
        1249                 :          0 :     va_end(vargs);
        1250                 :          0 :     return res;
        1251                 :            : }
        1252                 :            :
        1253                 :            :
        1254                 :            : int
        1255                 :          4 : PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
        1256                 :            : {
        1257                 :            :     int ret;
        1258                 :          4 :     PyObject *message = PyUnicode_FromString(text);
        1259         [ -  + ]:          4 :     if (message == NULL)
        1260                 :          0 :         return -1;
        1261                 :          4 :     ret = warn_unicode(category, message, stack_level, NULL);
        1262                 :          4 :     Py_DECREF(message);
        1263                 :          4 :     return ret;
        1264                 :            : }
        1265                 :            :
        1266                 :            : /* PyErr_Warn is only for backwards compatibility and will be removed.
        1267                 :            :    Use PyErr_WarnEx instead. */
        1268                 :            :
        1269                 :            : #undef PyErr_Warn
        1270                 :            :
        1271                 :            : int
        1272                 :          0 : PyErr_Warn(PyObject *category, const char *text)
        1273                 :            : {
        1274                 :          0 :     return PyErr_WarnEx(category, text, 1);
        1275                 :            : }
        1276                 :            :
        1277                 :            : /* Warning with explicit origin */
        1278                 :            : int
        1279                 :          0 : PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
        1280                 :            :                          PyObject *filename, int lineno,
        1281                 :            :                          PyObject *module, PyObject *registry)
        1282                 :            : {
        1283                 :            :     PyObject *res;
        1284         [ #  # ]:          0 :     if (category == NULL)
        1285                 :          0 :         category = PyExc_RuntimeWarning;
        1286                 :          0 :     PyThreadState *tstate = get_current_tstate();
        1287         [ #  # ]:          0 :     if (tstate == NULL) {
        1288                 :          0 :         return -1;
        1289                 :            :     }
        1290                 :          0 :     res = warn_explicit(tstate, category, message, filename, lineno,
        1291                 :            :                         module, registry, NULL, NULL);
        1292         [ #  # ]:          0 :     if (res == NULL)
        1293                 :          0 :         return -1;
        1294                 :          0 :     Py_DECREF(res);
        1295                 :          0 :     return 0;
        1296                 :            : }
        1297                 :            :
        1298                 :            : int
        1299                 :          0 : PyErr_WarnExplicit(PyObject *category, const char *text,
        1300                 :            :                    const char *filename_str, int lineno,
        1301                 :            :                    const char *module_str, PyObject *registry)
        1302                 :            : {
        1303                 :          0 :     PyObject *message = PyUnicode_FromString(text);
        1304                 :          0 :     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
        1305                 :          0 :     PyObject *module = NULL;
        1306                 :          0 :     int ret = -1;
        1307                 :            :
        1308   [ #  #  #  # ]:          0 :     if (message == NULL || filename == NULL)
        1309                 :          0 :         goto exit;
        1310         [ #  # ]:          0 :     if (module_str != NULL) {
        1311                 :          0 :         module = PyUnicode_FromString(module_str);
        1312         [ #  # ]:          0 :         if (module == NULL)
        1313                 :          0 :             goto exit;
        1314                 :            :     }
        1315                 :            :
        1316                 :          0 :     ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
        1317                 :            :                                    module, registry);
        1318                 :            :
        1319                 :          0 :  exit:
        1320                 :          0 :     Py_XDECREF(message);
        1321                 :          0 :     Py_XDECREF(module);
        1322                 :          0 :     Py_XDECREF(filename);
        1323                 :          0 :     return ret;
        1324                 :            : }
        1325                 :            :
        1326                 :            : int
        1327                 :          0 : PyErr_WarnExplicitFormat(PyObject *category,
        1328                 :            :                          const char *filename_str, int lineno,
        1329                 :            :                          const char *module_str, PyObject *registry,
        1330                 :            :                          const char *format, ...)
        1331                 :            : {
        1332                 :            :     PyObject *message;
        1333                 :          0 :     PyObject *module = NULL;
        1334                 :          0 :     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
        1335                 :          0 :     int ret = -1;
        1336                 :            :     va_list vargs;
        1337                 :            :
        1338         [ #  # ]:          0 :     if (filename == NULL)
        1339                 :          0 :         goto exit;
        1340         [ #  # ]:          0 :     if (module_str != NULL) {
        1341                 :          0 :         module = PyUnicode_FromString(module_str);
        1342         [ #  # ]:          0 :         if (module == NULL)
        1343                 :          0 :             goto exit;
        1344                 :            :     }
        1345                 :            :
        1346                 :          0 :     va_start(vargs, format);
        1347                 :          0 :     message = PyUnicode_FromFormatV(format, vargs);
        1348         [ #  # ]:          0 :     if (message != NULL) {
        1349                 :            :         PyObject *res;
        1350                 :          0 :         PyThreadState *tstate = get_current_tstate();
        1351         [ #  # ]:          0 :         if (tstate != NULL) {
        1352                 :          0 :             res = warn_explicit(tstate, category, message, filename, lineno,
        1353                 :            :                                 module, registry, NULL, NULL);
        1354                 :          0 :             Py_DECREF(message);
        1355         [ #  # ]:          0 :             if (res != NULL) {
        1356                 :          0 :                 Py_DECREF(res);
        1357                 :          0 :                 ret = 0;
        1358                 :            :             }
        1359                 :            :         }
        1360                 :            :     }
        1361                 :          0 :     va_end(vargs);
        1362                 :          0 : exit:
        1363                 :          0 :     Py_XDECREF(module);
        1364                 :          0 :     Py_XDECREF(filename);
        1365                 :          0 :     return ret;
        1366                 :            : }
        1367                 :            :
        1368                 :            : void
        1369                 :          0 : _PyErr_WarnUnawaitedCoroutine(PyObject *coro)
        1370                 :            : {
        1371                 :            :     /* First, we attempt to funnel the warning through
        1372                 :            :        warnings._warn_unawaited_coroutine.
        1373                 :            :
        1374                 :            :        This could raise an exception, due to:
        1375                 :            :        - a bug
        1376                 :            :        - some kind of shutdown-related brokenness
        1377                 :            :        - succeeding, but with an "error" warning filter installed, so the
        1378                 :            :          warning is converted into a RuntimeWarning exception
        1379                 :            :
        1380                 :            :        In the first two cases, we want to print the error (so we know what it
        1381                 :            :        is!), and then print a warning directly as a fallback. In the last
        1382                 :            :        case, we want to print the error (since it's the warning!), but *not*
        1383                 :            :        do a fallback. And after we print the error we can't check for what
        1384                 :            :        type of error it was (because PyErr_WriteUnraisable clears it), so we
        1385                 :            :        need a flag to keep track.
        1386                 :            :
        1387                 :            :        Since this is called from __del__ context, it's careful to never raise
        1388                 :            :        an exception.
        1389                 :            :     */
        1390                 :          0 :     int warned = 0;
        1391                 :          0 :     PyInterpreterState *interp = _PyInterpreterState_GET();
        1392                 :            :     assert(interp != NULL);
        1393                 :          0 :     PyObject *fn = GET_WARNINGS_ATTR(interp, _warn_unawaited_coroutine, 1);
        1394         [ #  # ]:          0 :     if (fn) {
        1395                 :          0 :         PyObject *res = PyObject_CallOneArg(fn, coro);
        1396                 :          0 :         Py_DECREF(fn);
        1397   [ #  #  #  # ]:          0 :         if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
        1398                 :          0 :             warned = 1;
        1399                 :            :         }
        1400                 :          0 :         Py_XDECREF(res);
        1401                 :            :     }
        1402                 :            :
        1403         [ #  # ]:          0 :     if (PyErr_Occurred()) {
        1404                 :          0 :         PyErr_WriteUnraisable(coro);
        1405                 :            :     }
        1406         [ #  # ]:          0 :     if (!warned) {
        1407         [ #  # ]:          0 :         if (_PyErr_WarnFormat(coro, PyExc_RuntimeWarning, 1,
        1408                 :            :                               "coroutine '%S' was never awaited",
        1409                 :            :                               ((PyCoroObject *)coro)->cr_qualname) < 0)
        1410                 :            :         {
        1411                 :          0 :             PyErr_WriteUnraisable(coro);
        1412                 :            :         }
        1413                 :            :     }
        1414                 :          0 : }
        1415                 :            :
        1416                 :            : static PyMethodDef warnings_functions[] = {
        1417                 :            :     WARNINGS_WARN_METHODDEF
        1418                 :            :     WARNINGS_WARN_EXPLICIT_METHODDEF
        1419                 :            :     WARNINGS_FILTERS_MUTATED_METHODDEF
        1420                 :            :     /* XXX(brett.cannon): add showwarning? */
        1421                 :            :     /* XXX(brett.cannon): Reasonable to add formatwarning? */
        1422                 :            :     {NULL, NULL}                /* sentinel */
        1423                 :            : };
        1424                 :            :
        1425                 :            :
        1426                 :            : static int
        1427                 :         26 : warnings_module_exec(PyObject *module)
        1428                 :            : {
        1429                 :         26 :     PyInterpreterState *interp = get_current_interp();
        1430         [ -  + ]:         26 :     if (interp == NULL) {
        1431                 :          0 :         return -1;
        1432                 :            :     }
        1433                 :         26 :     WarningsState *st = warnings_get_state(interp);
        1434         [ -  + ]:         26 :     if (st == NULL) {
        1435                 :          0 :         return -1;
        1436                 :            :     }
        1437         [ -  + ]:         26 :     if (PyModule_AddObjectRef(module, "filters", st->filters) < 0) {
        1438                 :          0 :         return -1;
        1439                 :            :     }
        1440         [ -  + ]:         26 :     if (PyModule_AddObjectRef(module, "_onceregistry", st->once_registry) < 0) {
        1441                 :          0 :         return -1;
        1442                 :            :     }
        1443         [ -  + ]:         26 :     if (PyModule_AddObjectRef(module, "_defaultaction", st->default_action) < 0) {
        1444                 :          0 :         return -1;
        1445                 :            :     }
        1446                 :         26 :     return 0;
        1447                 :            : }
        1448                 :            :
        1449                 :            :
        1450                 :            : static PyModuleDef_Slot warnings_slots[] = {
        1451                 :            :     {Py_mod_exec, warnings_module_exec},
        1452                 :            :     {0, NULL}
        1453                 :            : };
        1454                 :            :
        1455                 :            : static struct PyModuleDef warnings_module = {
        1456                 :            :     PyModuleDef_HEAD_INIT,
        1457                 :            :     .m_name = MODULE_NAME,
        1458                 :            :     .m_doc = warnings__doc__,
        1459                 :            :     .m_size = 0,
        1460                 :            :     .m_methods = warnings_functions,
        1461                 :            :     .m_slots = warnings_slots,
        1462                 :            : };
        1463                 :            :
        1464                 :            :
        1465                 :            : PyMODINIT_FUNC
        1466                 :         26 : _PyWarnings_Init(void)
        1467                 :            : {
        1468                 :         26 :     return PyModuleDef_Init(&warnings_module);
        1469                 :            : }
        1470                 :            :
        1471                 :            : // We need this to ensure that warnings still work until late in finalization.
        1472                 :            : void
        1473                 :         25 : _PyWarnings_Fini(PyInterpreterState *interp)
        1474                 :            : {
        1475                 :         25 :     warnings_clear_state(&interp->warnings);
        1476                 :         25 : }

Generated by: LCOV version 1.14