LCOV - code coverage report
Current view: top level - Python - _warnings.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 42 471 8.9 %
Date: 2017-04-19 Functions: 3 21 14.3 %

          Line data    Source code
       1             : #include "Python.h"
       2             : #include "frameobject.h"
       3             : 
       4             : #define MODULE_NAME "_warnings"
       5             : 
       6             : PyDoc_STRVAR(warnings__doc__,
       7             : MODULE_NAME " provides basic warning filtering support.\n"
       8             : "It is a helper module to speed up interpreter start-up.");
       9             : 
      10             : /* Both 'filters' and 'onceregistry' can be set in warnings.py;
      11             :    get_warnings_attr() will reset these variables accordingly. */
      12             : static PyObject *_filters;  /* List */
      13             : static PyObject *_once_registry;  /* Dict */
      14             : static PyObject *_default_action; /* String */
      15             : 
      16             : 
      17             : static int
      18           0 : check_matched(PyObject *obj, PyObject *arg)
      19             : {
      20             :     PyObject *result;
      21             :     int rc;
      22             : 
      23           0 :     if (obj == Py_None)
      24           0 :         return 1;
      25           0 :     result = PyObject_CallMethod(obj, "match", "O", arg);
      26           0 :     if (result == NULL)
      27           0 :         return -1;
      28             : 
      29           0 :     rc = PyObject_IsTrue(result);
      30           0 :     Py_DECREF(result);
      31           0 :     return rc;
      32             : }
      33             : 
      34             : /*
      35             :    Returns a new reference.
      36             :    A NULL return value can mean false or an error.
      37             : */
      38             : static PyObject *
      39           0 : get_warnings_attr(const char *attr)
      40             : {
      41             :     static PyObject *warnings_str = NULL;
      42             :     PyObject *all_modules;
      43             :     PyObject *warnings_module;
      44             :     int result;
      45             : 
      46           0 :     if (warnings_str == NULL) {
      47           0 :         warnings_str = PyString_InternFromString("warnings");
      48           0 :         if (warnings_str == NULL)
      49           0 :             return NULL;
      50             :     }
      51             : 
      52           0 :     all_modules = PyImport_GetModuleDict();
      53           0 :     result = PyDict_Contains(all_modules, warnings_str);
      54           0 :     if (result == -1 || result == 0)
      55           0 :         return NULL;
      56             : 
      57           0 :     warnings_module = PyDict_GetItem(all_modules, warnings_str);
      58           0 :     if (!PyObject_HasAttrString(warnings_module, attr))
      59           0 :             return NULL;
      60           0 :     return PyObject_GetAttrString(warnings_module, attr);
      61             : }
      62             : 
      63             : 
      64             : static PyObject *
      65           0 : get_once_registry(void)
      66             : {
      67             :     PyObject *registry;
      68             : 
      69           0 :     registry = get_warnings_attr("onceregistry");
      70           0 :     if (registry == NULL) {
      71           0 :         if (PyErr_Occurred())
      72           0 :             return NULL;
      73           0 :         return _once_registry;
      74             :     }
      75           0 :     Py_DECREF(_once_registry);
      76           0 :     _once_registry = registry;
      77           0 :     return registry;
      78             : }
      79             : 
      80             : 
      81             : static PyObject *
      82           0 : get_default_action(void)
      83             : {
      84             :     PyObject *default_action;
      85             : 
      86           0 :     default_action = get_warnings_attr("defaultaction");
      87           0 :     if (default_action == NULL) {
      88           0 :         if (PyErr_Occurred()) {
      89           0 :             return NULL;
      90             :         }
      91           0 :         return _default_action;
      92             :     }
      93             : 
      94           0 :     Py_DECREF(_default_action);
      95           0 :     _default_action = default_action;
      96           0 :     return default_action;
      97             : }
      98             : 
      99             : 
     100             : /* The item is a borrowed reference. */
     101             : static const char *
     102           0 : get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
     103             :            PyObject *module, PyObject **item)
     104             : {
     105             :     PyObject *action;
     106             :     Py_ssize_t i;
     107             :     PyObject *warnings_filters;
     108             : 
     109           0 :     warnings_filters = get_warnings_attr("filters");
     110           0 :     if (warnings_filters == NULL) {
     111           0 :         if (PyErr_Occurred())
     112           0 :             return NULL;
     113             :     }
     114             :     else {
     115           0 :         Py_DECREF(_filters);
     116           0 :         _filters = warnings_filters;
     117             :     }
     118             : 
     119           0 :     if (!PyList_Check(_filters)) {
     120           0 :         PyErr_SetString(PyExc_ValueError,
     121             :                         MODULE_NAME ".filters must be a list");
     122           0 :         return NULL;
     123             :     }
     124             : 
     125             :     /* _filters could change while we are iterating over it. */
     126           0 :     for (i = 0; i < PyList_GET_SIZE(_filters); i++) {
     127             :         PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
     128             :         Py_ssize_t ln;
     129             :         int is_subclass, good_msg, good_mod;
     130             : 
     131           0 :         tmp_item = *item = PyList_GET_ITEM(_filters, i);
     132           0 :         if (PyTuple_Size(tmp_item) != 5) {
     133           0 :             PyErr_Format(PyExc_ValueError,
     134             :                          MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
     135           0 :             return NULL;
     136             :         }
     137             : 
     138             :         /* Python code: action, msg, cat, mod, ln = item */
     139           0 :         action = PyTuple_GET_ITEM(tmp_item, 0);
     140           0 :         msg = PyTuple_GET_ITEM(tmp_item, 1);
     141           0 :         cat = PyTuple_GET_ITEM(tmp_item, 2);
     142           0 :         mod = PyTuple_GET_ITEM(tmp_item, 3);
     143           0 :         ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
     144             : 
     145           0 :         good_msg = check_matched(msg, text);
     146           0 :         good_mod = check_matched(mod, module);
     147           0 :         is_subclass = PyObject_IsSubclass(category, cat);
     148           0 :         ln = PyInt_AsSsize_t(ln_obj);
     149           0 :         if (good_msg == -1 || good_mod == -1 || is_subclass == -1 ||
     150           0 :             (ln == -1 && PyErr_Occurred()))
     151           0 :             return NULL;
     152             : 
     153           0 :         if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))
     154           0 :             return PyString_AsString(action);
     155             :     }
     156             : 
     157           0 :     action = get_default_action();
     158           0 :     if (action != NULL) {
     159           0 :         return PyString_AsString(action);
     160             :     }
     161             : 
     162           0 :     PyErr_SetString(PyExc_ValueError,
     163             :                     MODULE_NAME ".defaultaction not found");
     164           0 :     return NULL;
     165             : }
     166             : 
     167             : 
     168             : static int
     169           0 : already_warned(PyObject *registry, PyObject *key, int should_set)
     170             : {
     171             :     PyObject *already_warned;
     172             : 
     173           0 :     if (key == NULL)
     174           0 :         return -1;
     175             : 
     176           0 :     already_warned = PyDict_GetItem(registry, key);
     177           0 :     if (already_warned != NULL) {
     178           0 :         int rc = PyObject_IsTrue(already_warned);
     179           0 :         if (rc != 0)
     180           0 :             return rc;
     181             :     }
     182             : 
     183             :     /* This warning wasn't found in the registry, set it. */
     184           0 :     if (should_set)
     185           0 :         return PyDict_SetItem(registry, key, Py_True);
     186           0 :     return 0;
     187             : }
     188             : 
     189             : /* New reference. */
     190             : static PyObject *
     191           0 : normalize_module(PyObject *filename)
     192             : {
     193             :     PyObject *module;
     194             :     const char *mod_str;
     195             :     Py_ssize_t len;
     196             : 
     197           0 :     int rc = PyObject_IsTrue(filename);
     198           0 :     if (rc == -1)
     199           0 :         return NULL;
     200           0 :     else if (rc == 0)
     201           0 :         return PyString_FromString("<unknown>");
     202             : 
     203           0 :     mod_str = PyString_AsString(filename);
     204           0 :     if (mod_str == NULL)
     205           0 :         return NULL;
     206           0 :     len = PyString_Size(filename);
     207           0 :     if (len < 0)
     208           0 :         return NULL;
     209           0 :     if (len >= 3 &&
     210           0 :             strncmp(mod_str + (len - 3), ".py", 3) == 0) {
     211           0 :         module = PyString_FromStringAndSize(mod_str, len-3);
     212             :     }
     213             :     else {
     214           0 :         module = filename;
     215           0 :         Py_INCREF(module);
     216             :     }
     217           0 :     return module;
     218             : }
     219             : 
     220             : static int
     221           0 : update_registry(PyObject *registry, PyObject *text, PyObject *category,
     222             :                 int add_zero)
     223             : {
     224           0 :     PyObject *altkey, *zero = NULL;
     225             :     int rc;
     226             : 
     227           0 :     if (add_zero) {
     228           0 :         zero = PyInt_FromLong(0);
     229           0 :         if (zero == NULL)
     230           0 :             return -1;
     231           0 :         altkey = PyTuple_Pack(3, text, category, zero);
     232             :     }
     233             :     else
     234           0 :         altkey = PyTuple_Pack(2, text, category);
     235             : 
     236           0 :     rc = already_warned(registry, altkey, 1);
     237           0 :     Py_XDECREF(zero);
     238           0 :     Py_XDECREF(altkey);
     239           0 :     return rc;
     240             : }
     241             : 
     242             : static void
     243           0 : show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
     244             :                 *category, PyObject *sourceline)
     245             : {
     246             :     PyObject *f_stderr;
     247             :     PyObject *name;
     248             :     char lineno_str[128];
     249             : 
     250           0 :     PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
     251             : 
     252           0 :     name = PyObject_GetAttrString(category, "__name__");
     253           0 :     if (name == NULL)  /* XXX Can an object lack a '__name__' attribute? */
     254           0 :         return;
     255             : 
     256           0 :     f_stderr = PySys_GetObject("stderr");
     257           0 :     if (f_stderr == NULL) {
     258           0 :         fprintf(stderr, "lost sys.stderr\n");
     259           0 :         Py_DECREF(name);
     260           0 :         return;
     261             :     }
     262             : 
     263             :     /* Print "filename:lineno: category: text\n" */
     264           0 :     PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW);
     265           0 :     PyFile_WriteString(lineno_str, f_stderr);
     266           0 :     PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW);
     267           0 :     PyFile_WriteString(": ", f_stderr);
     268           0 :     PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW);
     269           0 :     PyFile_WriteString("\n", f_stderr);
     270           0 :     Py_XDECREF(name);
     271             : 
     272             :     /* Print "  source_line\n" */
     273           0 :     if (sourceline) {
     274           0 :         char *source_line_str = PyString_AS_STRING(sourceline);
     275           0 :         while (*source_line_str == ' ' || *source_line_str == '\t' ||
     276           0 :                 *source_line_str == '\014')
     277           0 :             source_line_str++;
     278             : 
     279           0 :         PyFile_WriteString(source_line_str, f_stderr);
     280           0 :         PyFile_WriteString("\n", f_stderr);
     281             :     }
     282             :     else
     283           0 :         _Py_DisplaySourceLine(f_stderr, PyString_AS_STRING(filename),
     284             :                               lineno, 2);
     285           0 :     PyErr_Clear();
     286             : }
     287             : 
     288             : static PyObject *
     289           0 : warn_explicit(PyObject *category, PyObject *message,
     290             :               PyObject *filename, int lineno,
     291             :               PyObject *module, PyObject *registry, PyObject *sourceline)
     292             : {
     293           0 :     PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
     294           0 :     PyObject *item = Py_None;
     295             :     const char *action;
     296             :     int rc;
     297             : 
     298           0 :     if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
     299           0 :         PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
     300           0 :         return NULL;
     301             :     }
     302             : 
     303             :     /* Normalize module. */
     304           0 :     if (module == NULL) {
     305           0 :         module = normalize_module(filename);
     306           0 :         if (module == NULL)
     307           0 :             return NULL;
     308             :     }
     309             :     else
     310           0 :         Py_INCREF(module);
     311             : 
     312             :     /* Normalize message. */
     313           0 :     Py_INCREF(message);  /* DECREF'ed in cleanup. */
     314           0 :     rc = PyObject_IsInstance(message, PyExc_Warning);
     315           0 :     if (rc == -1) {
     316           0 :         goto cleanup;
     317             :     }
     318           0 :     if (rc == 1) {
     319           0 :         text = PyObject_Str(message);
     320           0 :         if (text == NULL)
     321           0 :             goto cleanup;
     322           0 :         category = (PyObject*)message->ob_type;
     323             :     }
     324             :     else {
     325           0 :         text = message;
     326           0 :         message = PyObject_CallFunction(category, "O", message);
     327           0 :         if (message == NULL)
     328           0 :             goto cleanup;
     329             :     }
     330             : 
     331           0 :     lineno_obj = PyInt_FromLong(lineno);
     332           0 :     if (lineno_obj == NULL)
     333           0 :         goto cleanup;
     334             : 
     335             :     /* Create key. */
     336           0 :     key = PyTuple_Pack(3, text, category, lineno_obj);
     337           0 :     if (key == NULL)
     338           0 :         goto cleanup;
     339             : 
     340           0 :     if ((registry != NULL) && (registry != Py_None)) {
     341           0 :         rc = already_warned(registry, key, 0);
     342           0 :         if (rc == -1)
     343           0 :             goto cleanup;
     344           0 :         else if (rc == 1)
     345           0 :             goto return_none;
     346             :         /* Else this warning hasn't been generated before. */
     347             :     }
     348             : 
     349           0 :     action = get_filter(category, text, lineno, module, &item);
     350           0 :     if (action == NULL)
     351           0 :         goto cleanup;
     352             : 
     353           0 :     if (strcmp(action, "error") == 0) {
     354           0 :         PyErr_SetObject(category, message);
     355           0 :         goto cleanup;
     356             :     }
     357             : 
     358             :     /* Store in the registry that we've been here, *except* when the action
     359             :        is "always". */
     360           0 :     rc = 0;
     361           0 :     if (strcmp(action, "always") != 0) {
     362           0 :         if (registry != NULL && registry != Py_None &&
     363           0 :                 PyDict_SetItem(registry, key, Py_True) < 0)
     364             :             goto cleanup;
     365           0 :         else if (strcmp(action, "ignore") == 0)
     366           0 :             goto return_none;
     367           0 :         else if (strcmp(action, "once") == 0) {
     368           0 :             if (registry == NULL || registry == Py_None) {
     369           0 :                 registry = get_once_registry();
     370           0 :                 if (registry == NULL)
     371           0 :                     goto cleanup;
     372             :             }
     373             :             /* _once_registry[(text, category)] = 1 */
     374           0 :             rc = update_registry(registry, text, category, 0);
     375             :         }
     376           0 :         else if (strcmp(action, "module") == 0) {
     377             :             /* registry[(text, category, 0)] = 1 */
     378           0 :             if (registry != NULL && registry != Py_None)
     379           0 :                 rc = update_registry(registry, text, category, 0);
     380             :         }
     381           0 :         else if (strcmp(action, "default") != 0) {
     382           0 :             PyObject *to_str = PyObject_Str(item);
     383           0 :             const char *err_str = "???";
     384             : 
     385           0 :             if (to_str != NULL)
     386           0 :                 err_str = PyString_AS_STRING(to_str);
     387           0 :             PyErr_Format(PyExc_RuntimeError,
     388             :                         "Unrecognized action (%s) in warnings.filters:\n %s",
     389             :                         action, err_str);
     390           0 :             Py_XDECREF(to_str);
     391           0 :             goto cleanup;
     392             :         }
     393             :     }
     394             : 
     395           0 :     if (rc == 1)  /* Already warned for this module. */
     396           0 :         goto return_none;
     397           0 :     if (rc == 0) {
     398           0 :         PyObject *show_fxn = get_warnings_attr("showwarning");
     399           0 :         if (show_fxn == NULL) {
     400           0 :             if (PyErr_Occurred())
     401           0 :                 goto cleanup;
     402           0 :             show_warning(filename, lineno, text, category, sourceline);
     403             :         }
     404             :         else {
     405             :               PyObject *res;
     406             : 
     407           0 :               if (!PyMethod_Check(show_fxn) && !PyFunction_Check(show_fxn)) {
     408           0 :                   PyErr_SetString(PyExc_TypeError,
     409             :                                   "warnings.showwarning() must be set to a "
     410             :                                   "function or method");
     411           0 :                   Py_DECREF(show_fxn);
     412           0 :                   goto cleanup;
     413             :               }
     414             : 
     415           0 :               res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
     416             :                                                   filename, lineno_obj,
     417             :                                                   NULL);
     418           0 :               Py_DECREF(show_fxn);
     419           0 :               Py_XDECREF(res);
     420           0 :               if (res == NULL)
     421           0 :                   goto cleanup;
     422             :         }
     423             :     }
     424             :     else /* if (rc == -1) */
     425           0 :         goto cleanup;
     426             : 
     427             :  return_none:
     428           0 :     result = Py_None;
     429           0 :     Py_INCREF(result);
     430             : 
     431             :  cleanup:
     432           0 :     Py_XDECREF(key);
     433           0 :     Py_XDECREF(text);
     434           0 :     Py_XDECREF(lineno_obj);
     435           0 :     Py_DECREF(module);
     436           0 :     Py_XDECREF(message);
     437           0 :     return result;  /* Py_None or NULL. */
     438             : }
     439             : 
     440             : /* filename, module, and registry are new refs, globals is borrowed */
     441             : /* Returns 0 on error (no new refs), 1 on success */
     442             : static int
     443           0 : setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
     444             :               PyObject **module, PyObject **registry)
     445             : {
     446             :     PyObject *globals;
     447             : 
     448             :     /* Setup globals and lineno. */
     449           0 :     PyFrameObject *f = PyThreadState_GET()->frame;
     450           0 :     while (--stack_level > 0 && f != NULL)
     451           0 :         f = f->f_back;
     452             : 
     453           0 :     if (f == NULL) {
     454           0 :         globals = PyThreadState_Get()->interp->sysdict;
     455           0 :         *lineno = 1;
     456             :     }
     457             :     else {
     458           0 :         globals = f->f_globals;
     459           0 :         *lineno = PyFrame_GetLineNumber(f);
     460             :     }
     461             : 
     462           0 :     *module = NULL;
     463             : 
     464             :     /* Setup registry. */
     465             :     assert(globals != NULL);
     466             :     assert(PyDict_Check(globals));
     467           0 :     *registry = PyDict_GetItemString(globals, "__warningregistry__");
     468           0 :     if (*registry == NULL) {
     469             :         int rc;
     470             : 
     471           0 :         *registry = PyDict_New();
     472           0 :         if (*registry == NULL)
     473           0 :             return 0;
     474             : 
     475           0 :          rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
     476           0 :          if (rc < 0)
     477           0 :             goto handle_error;
     478             :     }
     479             :     else
     480           0 :         Py_INCREF(*registry);
     481             : 
     482             :     /* Setup module. */
     483           0 :     *module = PyDict_GetItemString(globals, "__name__");
     484           0 :     if (*module == NULL) {
     485           0 :         *module = PyString_FromString("<string>");
     486           0 :         if (*module == NULL)
     487           0 :             goto handle_error;
     488             :     }
     489             :     else
     490           0 :         Py_INCREF(*module);
     491             : 
     492             :     /* Setup filename. */
     493           0 :     *filename = PyDict_GetItemString(globals, "__file__");
     494           0 :     if (*filename != NULL && PyString_Check(*filename)) {
     495           0 :             Py_ssize_t len = PyString_Size(*filename);
     496           0 :         const char *file_str = PyString_AsString(*filename);
     497           0 :             if (file_str == NULL || (len < 0 && PyErr_Occurred()))
     498             :             goto handle_error;
     499             : 
     500             :         /* if filename.lower().endswith((".pyc", ".pyo")): */
     501           0 :         if (len >= 4 &&
     502           0 :             file_str[len-4] == '.' &&
     503           0 :             tolower(file_str[len-3]) == 'p' &&
     504           0 :             tolower(file_str[len-2]) == 'y' &&
     505           0 :             (tolower(file_str[len-1]) == 'c' ||
     506           0 :                 tolower(file_str[len-1]) == 'o'))
     507             :         {
     508           0 :             *filename = PyString_FromStringAndSize(file_str, len-1);
     509           0 :             if (*filename == NULL)
     510           0 :                 goto handle_error;
     511             :         }
     512             :         else
     513           0 :             Py_INCREF(*filename);
     514             :     }
     515             :     else {
     516           0 :         const char *module_str = PyString_AsString(*module);
     517           0 :         *filename = NULL;
     518           0 :         if (module_str && strcmp(module_str, "__main__") == 0) {
     519           0 :             PyObject *argv = PySys_GetObject("argv");
     520           0 :             if (argv != NULL && PyList_Size(argv) > 0) {
     521             :                 int is_true;
     522           0 :                 *filename = PyList_GetItem(argv, 0);
     523           0 :                 Py_INCREF(*filename);
     524             :                 /* If sys.argv[0] is false, then use '__main__'. */
     525           0 :                 is_true = PyObject_IsTrue(*filename);
     526           0 :                 if (is_true < 0) {
     527           0 :                     Py_DECREF(*filename);
     528           0 :                     goto handle_error;
     529             :                 }
     530           0 :                 else if (!is_true) {
     531           0 :                     Py_SETREF(*filename, PyString_FromString("__main__"));
     532           0 :                     if (*filename == NULL)
     533           0 :                         goto handle_error;
     534             :                 }
     535             :             }
     536             :             else {
     537             :                 /* embedded interpreters don't have sys.argv, see bug #839151 */
     538           0 :                 *filename = PyString_FromString("__main__");
     539           0 :                 if (*filename == NULL)
     540           0 :                     goto handle_error;
     541             :             }
     542             :         }
     543           0 :         if (*filename == NULL) {
     544           0 :             *filename = *module;
     545           0 :             Py_INCREF(*filename);
     546             :         }
     547             :     }
     548             : 
     549           0 :     return 1;
     550             : 
     551             :  handle_error:
     552             :     /* filename not XDECREF'ed here as there is no way to jump here with a
     553             :        dangling reference. */
     554           0 :     Py_XDECREF(*registry);
     555           0 :     Py_XDECREF(*module);
     556           0 :     return 0;
     557             : }
     558             : 
     559             : static PyObject *
     560           0 : get_category(PyObject *message, PyObject *category)
     561             : {
     562             :     int rc;
     563             : 
     564             :     /* Get category. */
     565           0 :     rc = PyObject_IsInstance(message, PyExc_Warning);
     566           0 :     if (rc == -1)
     567           0 :         return NULL;
     568             : 
     569           0 :     if (rc == 1)
     570           0 :         category = (PyObject*)message->ob_type;
     571           0 :     else if (category == NULL)
     572           0 :         category = PyExc_UserWarning;
     573             : 
     574             :     /* Validate category. */
     575           0 :     rc = PyObject_IsSubclass(category, PyExc_Warning);
     576           0 :     if (rc == -1)
     577           0 :         return NULL;
     578           0 :     if (rc == 0) {
     579           0 :         PyErr_SetString(PyExc_ValueError,
     580             :                         "category is not a subclass of Warning");
     581           0 :         return NULL;
     582             :     }
     583             : 
     584           0 :     return category;
     585             : }
     586             : 
     587             : static PyObject *
     588           0 : do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
     589             : {
     590             :     PyObject *filename, *module, *registry, *res;
     591             :     int lineno;
     592             : 
     593           0 :     if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
     594           0 :         return NULL;
     595             : 
     596           0 :     res = warn_explicit(category, message, filename, lineno, module, registry,
     597             :                         NULL);
     598           0 :     Py_DECREF(filename);
     599           0 :     Py_DECREF(registry);
     600           0 :     Py_DECREF(module);
     601           0 :     return res;
     602             : }
     603             : 
     604             : static PyObject *
     605           0 : warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
     606             : {
     607             :     static char *kw_list[] = { "message", "category", "stacklevel", 0 };
     608           0 :     PyObject *message, *category = NULL;
     609           0 :     Py_ssize_t stack_level = 1;
     610             : 
     611           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
     612             :                                      &message, &category, &stack_level))
     613           0 :         return NULL;
     614             : 
     615           0 :     category = get_category(message, category);
     616           0 :     if (category == NULL)
     617           0 :         return NULL;
     618           0 :     return do_warn(message, category, stack_level);
     619             : }
     620             : 
     621             : static PyObject *
     622           0 : warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
     623             : {
     624             :     static char *kwd_list[] = {"message", "category", "filename", "lineno",
     625             :                                 "module", "registry", "module_globals", 0};
     626             :     PyObject *message;
     627             :     PyObject *category;
     628             :     PyObject *filename;
     629             :     int lineno;
     630           0 :     PyObject *module = NULL;
     631           0 :     PyObject *registry = NULL;
     632           0 :     PyObject *module_globals = NULL;
     633             : 
     634           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
     635             :                 kwd_list, &message, &category, &filename, &lineno, &module,
     636             :                 &registry, &module_globals))
     637           0 :         return NULL;
     638             : 
     639           0 :     if (module_globals) {
     640             :         static PyObject *get_source_name = NULL;
     641             :         static PyObject *splitlines_name = NULL;
     642             :         PyObject *loader;
     643             :         PyObject *module_name;
     644             :         PyObject *source;
     645             :         PyObject *source_list;
     646             :         PyObject *source_line;
     647             :         PyObject *returned;
     648             : 
     649           0 :         if (get_source_name == NULL) {
     650           0 :             get_source_name = PyString_InternFromString("get_source");
     651           0 :             if (!get_source_name)
     652           0 :                 return NULL;
     653             :         }
     654           0 :         if (splitlines_name == NULL) {
     655           0 :             splitlines_name = PyString_InternFromString("splitlines");
     656           0 :             if (!splitlines_name)
     657           0 :                 return NULL;
     658             :         }
     659             : 
     660             :         /* Check/get the requisite pieces needed for the loader. */
     661           0 :         loader = PyDict_GetItemString(module_globals, "__loader__");
     662           0 :         module_name = PyDict_GetItemString(module_globals, "__name__");
     663             : 
     664           0 :         if (loader == NULL || module_name == NULL)
     665             :             goto standard_call;
     666             : 
     667             :         /* Make sure the loader implements the optional get_source() method. */
     668           0 :         if (!PyObject_HasAttrString(loader, "get_source"))
     669           0 :                 goto standard_call;
     670             :         /* Call get_source() to get the source code. */
     671           0 :         source = PyObject_CallMethodObjArgs(loader, get_source_name,
     672             :                                                 module_name, NULL);
     673           0 :         if (!source)
     674           0 :             return NULL;
     675           0 :         else if (source == Py_None) {
     676           0 :             Py_DECREF(Py_None);
     677           0 :             goto standard_call;
     678             :         }
     679             : 
     680             :         /* Split the source into lines. */
     681           0 :         source_list = PyObject_CallMethodObjArgs(source, splitlines_name,
     682             :                                                     NULL);
     683           0 :         Py_DECREF(source);
     684           0 :         if (!source_list)
     685           0 :             return NULL;
     686             : 
     687             :         /* Get the source line. */
     688           0 :         source_line = PyList_GetItem(source_list, lineno-1);
     689           0 :         if (!source_line) {
     690           0 :             Py_DECREF(source_list);
     691           0 :             return NULL;
     692             :         }
     693             : 
     694             :         /* Handle the warning. */
     695           0 :         returned = warn_explicit(category, message, filename, lineno, module,
     696             :                             registry, source_line);
     697           0 :         Py_DECREF(source_list);
     698           0 :         return returned;
     699             :     }
     700             : 
     701             :  standard_call:
     702           0 :     return warn_explicit(category, message, filename, lineno, module,
     703             :                                 registry, NULL);
     704             : }
     705             : 
     706             : 
     707             : /* Function to issue a warning message; may raise an exception. */
     708             : int
     709           0 : PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
     710             : {
     711             :     PyObject *res;
     712           0 :     PyObject *message = PyString_FromString(text);
     713           0 :     if (message == NULL)
     714           0 :         return -1;
     715             : 
     716           0 :     if (category == NULL)
     717           0 :         category = PyExc_RuntimeWarning;
     718             : 
     719           0 :     res = do_warn(message, category, stack_level);
     720           0 :     Py_DECREF(message);
     721           0 :     if (res == NULL)
     722           0 :         return -1;
     723           0 :     Py_DECREF(res);
     724             : 
     725           0 :     return 0;
     726             : }
     727             : 
     728             : /* PyErr_Warn is only for backwards compatibility and will be removed.
     729             :    Use PyErr_WarnEx instead. */
     730             : 
     731             : #undef PyErr_Warn
     732             : 
     733             : PyAPI_FUNC(int)
     734           0 : PyErr_Warn(PyObject *category, char *text)
     735             : {
     736           0 :     return PyErr_WarnEx(category, text, 1);
     737             : }
     738             : 
     739             : /* Warning with explicit origin */
     740             : int
     741           0 : PyErr_WarnExplicit(PyObject *category, const char *text,
     742             :                    const char *filename_str, int lineno,
     743             :                    const char *module_str, PyObject *registry)
     744             : {
     745             :     PyObject *res;
     746           0 :     PyObject *message = PyString_FromString(text);
     747           0 :     PyObject *filename = PyString_FromString(filename_str);
     748           0 :     PyObject *module = NULL;
     749           0 :     int ret = -1;
     750             : 
     751           0 :     if (message == NULL || filename == NULL)
     752             :         goto exit;
     753           0 :     if (module_str != NULL) {
     754           0 :         module = PyString_FromString(module_str);
     755           0 :             if (module == NULL)
     756           0 :                 goto exit;
     757             :     }
     758             : 
     759           0 :     if (category == NULL)
     760           0 :         category = PyExc_RuntimeWarning;
     761           0 :     res = warn_explicit(category, message, filename, lineno, module, registry,
     762             :                         NULL);
     763           0 :     if (res == NULL)
     764           0 :         goto exit;
     765           0 :     Py_DECREF(res);
     766           0 :     ret = 0;
     767             : 
     768             :  exit:
     769           0 :     Py_XDECREF(message);
     770           0 :     Py_XDECREF(module);
     771           0 :     Py_XDECREF(filename);
     772           0 :     return ret;
     773             : }
     774             : 
     775             : 
     776             : PyDoc_STRVAR(warn_doc,
     777             : "Issue a warning, or maybe ignore it or raise an exception.");
     778             : 
     779             : PyDoc_STRVAR(warn_explicit_doc,
     780             : "Low-level inferface to warnings functionality.");
     781             : 
     782             : static PyMethodDef warnings_functions[] = {
     783             :     {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
     784             :         warn_doc},
     785             :     {"warn_explicit", (PyCFunction)warnings_warn_explicit,
     786             :         METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
     787             :     /* XXX(brett.cannon): add showwarning? */
     788             :     /* XXX(brett.cannon): Reasonable to add formatwarning? */
     789             :     {NULL, NULL}                /* sentinel */
     790             : };
     791             : 
     792             : 
     793             : static PyObject *
     794          12 : create_filter(PyObject *category, const char *action)
     795             : {
     796             :     static PyObject *ignore_str = NULL;
     797             :     static PyObject *error_str = NULL;
     798             :     static PyObject *default_str = NULL;
     799          12 :     PyObject *action_obj = NULL;
     800             :     PyObject *lineno, *result;
     801             : 
     802          12 :     if (!strcmp(action, "ignore")) {
     803          12 :         if (ignore_str == NULL) {
     804           3 :             ignore_str = PyString_InternFromString("ignore");
     805           3 :             if (ignore_str == NULL)
     806           0 :                 return NULL;
     807             :         }
     808          12 :         action_obj = ignore_str;
     809             :     }
     810           0 :     else if (!strcmp(action, "error")) {
     811           0 :         if (error_str == NULL) {
     812           0 :             error_str = PyString_InternFromString("error");
     813           0 :             if (error_str == NULL)
     814           0 :                 return NULL;
     815             :         }
     816           0 :         action_obj = error_str;
     817             :     }
     818           0 :     else if (!strcmp(action, "default")) {
     819           0 :         if (default_str == NULL) {
     820           0 :             default_str = PyString_InternFromString("default");
     821           0 :             if (default_str == NULL)
     822           0 :                 return NULL;
     823             :         }
     824           0 :         action_obj = default_str;
     825             :     }
     826             :     else {
     827           0 :         Py_FatalError("unknown action");
     828             :     }
     829             : 
     830             :     /* This assumes the line number is zero for now. */
     831          12 :     lineno = PyInt_FromLong(0);
     832          12 :     if (lineno == NULL)
     833           0 :         return NULL;
     834          12 :     result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
     835          12 :     Py_DECREF(lineno);
     836          12 :     return result;
     837             : }
     838             : 
     839             : static PyObject *
     840           3 : init_filters(void)
     841             : {
     842             :     /* Don't silence DeprecationWarning if -3 or -Q were used. */
     843           3 :     PyObject *filters = PyList_New(Py_Py3kWarningFlag ||
     844             :                                     Py_DivisionWarningFlag ? 3 : 4);
     845           3 :     unsigned int pos = 0;  /* Post-incremented in each use. */
     846             :     unsigned int x;
     847             :     const char *bytes_action;
     848             : 
     849           3 :     if (filters == NULL)
     850           0 :         return NULL;
     851             : 
     852             :     /* If guard changes, make sure to update 'filters' initialization above. */
     853           3 :     if (!Py_Py3kWarningFlag && !Py_DivisionWarningFlag) {
     854           3 :         PyList_SET_ITEM(filters, pos++,
     855             :                         create_filter(PyExc_DeprecationWarning, "ignore"));
     856             :     }
     857           3 :     PyList_SET_ITEM(filters, pos++,
     858             :                     create_filter(PyExc_PendingDeprecationWarning, "ignore"));
     859           3 :     PyList_SET_ITEM(filters, pos++,
     860             :                     create_filter(PyExc_ImportWarning, "ignore"));
     861           3 :     if (Py_BytesWarningFlag > 1)
     862           0 :         bytes_action = "error";
     863           3 :     else if (Py_BytesWarningFlag)
     864           0 :         bytes_action = "default";
     865             :     else
     866           3 :         bytes_action = "ignore";
     867           3 :     PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning,
     868             :                     bytes_action));
     869             : 
     870          15 :     for (x = 0; x < pos; x += 1) {
     871          12 :         if (PyList_GET_ITEM(filters, x) == NULL) {
     872           0 :             Py_DECREF(filters);
     873           0 :             return NULL;
     874             :         }
     875             :     }
     876             : 
     877           3 :     return filters;
     878             : }
     879             : 
     880             : 
     881             : PyMODINIT_FUNC
     882           3 : _PyWarnings_Init(void)
     883             : {
     884             :     PyObject *m;
     885             : 
     886           3 :     m = Py_InitModule3(MODULE_NAME, warnings_functions, warnings__doc__);
     887           3 :     if (m == NULL)
     888           0 :         return;
     889             : 
     890           3 :     _filters = init_filters();
     891           3 :     if (_filters == NULL)
     892           0 :         return;
     893           3 :     Py_INCREF(_filters);
     894           3 :     if (PyModule_AddObject(m, "filters", _filters) < 0)
     895           0 :         return;
     896             : 
     897           3 :     _once_registry = PyDict_New();
     898           3 :     if (_once_registry == NULL)
     899           0 :         return;
     900           3 :     Py_INCREF(_once_registry);
     901           3 :     if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
     902           0 :         return;
     903             : 
     904           3 :     _default_action = PyString_FromString("default");
     905           3 :     if (_default_action == NULL)
     906           0 :         return;
     907           3 :     Py_INCREF(_default_action);
     908           3 :     if (PyModule_AddObject(m, "default_action", _default_action) < 0)
     909           0 :         return;
     910             : }

Generated by: LCOV version 1.10