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