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