LCOV - code coverage report
Current view: top level - Python - _warnings.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 532 681 78.1 %
Date: 2022-07-20 13:12:14 Functions: 40 42 95.2 %
Branches: 283 424 66.7 %

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

Generated by: LCOV version 1.14