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