PageRenderTime 70ms CodeModel.GetById 21ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/Python/_warnings.c

http://unladen-swallow.googlecode.com/
C | 916 lines | 742 code | 123 blank | 51 comment | 302 complexity | 633f7c446506233a4c4d8ed48ba07936 MD5 | raw file
  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
  8PyDoc_STRVAR(warnings__doc__,
  9MODULE_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. */
 14static PyObject *_filters;  /* List */
 15static PyObject *_once_registry;  /* Dict */
 16
 17
 18static int
 19check_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*/
 39static PyObject *
 40get_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
 65static PyObject *
 66get_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. */
 83static const char *
 84get_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
155static int
156already_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. */
177static PyObject *
178normalize_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
207static int
208update_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
229static void
230show_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
275static PyObject *
276warn_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        if (text == NULL)
308            goto cleanup;
309        category = (PyObject*)message->ob_type;
310    }
311    else {
312        text = message;
313        message = PyObject_CallFunction(category, "O", message);
314        if (message == NULL)
315            goto cleanup;
316    }
317
318    lineno_obj = PyInt_FromLong(lineno);
319    if (lineno_obj == NULL)
320        goto cleanup;
321
322    /* Create key. */
323    key = PyTuple_Pack(3, text, category, lineno_obj);
324    if (key == NULL)
325        goto cleanup;
326
327    if ((registry != NULL) && (registry != Py_None)) {
328        rc = already_warned(registry, key, 0);
329        if (rc == -1)
330            goto cleanup;
331	else if (rc == 1)
332            goto return_none;
333        /* Else this warning hasn't been generated before. */
334    }
335
336    action = get_filter(category, text, lineno, module, &item);
337    if (action == NULL)
338        goto cleanup;
339
340    if (strcmp(action, "error") == 0) {
341        PyErr_SetObject(category, message);
342        goto cleanup;
343    }
344
345    /* Store in the registry that we've been here, *except* when the action
346       is "always". */
347    rc = 0;
348    if (strcmp(action, "always") != 0) {
349        if (registry != NULL && registry != Py_None &&
350                PyDict_SetItem(registry, key, Py_True) < 0)
351            goto cleanup;
352        else if (strcmp(action, "ignore") == 0)
353            goto return_none;
354        else if (strcmp(action, "once") == 0) {
355            if (registry == NULL || registry == Py_None) {
356                registry = get_once_registry();
357                if (registry == NULL)
358                    goto cleanup;
359            }
360            /* _once_registry[(text, category)] = 1 */
361            rc = update_registry(registry, text, category, 0);
362        }
363        else if (strcmp(action, "module") == 0) {
364            /* registry[(text, category, 0)] = 1 */
365            if (registry != NULL && registry != Py_None)
366                rc = update_registry(registry, text, category, 0);
367        }
368        else if (strcmp(action, "default") != 0) {
369            PyObject *to_str = PyObject_Str(item);
370            const char *err_str = "???";
371
372            if (to_str != NULL)
373                err_str = PyString_AS_STRING(to_str);
374            PyErr_Format(PyExc_RuntimeError,
375                        "Unrecognized action (%s) in warnings.filters:\n %s",
376                        action, err_str);
377            Py_XDECREF(to_str);
378            goto cleanup;
379        }
380    }
381
382    if (rc == 1)  /* Already warned for this module. */
383        goto return_none;
384    if (rc == 0) {
385        PyObject *show_fxn = get_warnings_attr("showwarning");
386        if (show_fxn == NULL) {
387            if (PyErr_Occurred())
388                goto cleanup;
389            show_warning(filename, lineno, text, category, sourceline);
390        }
391        else {
392            const char *msg = "functions overriding warnings.showwarning() "
393                                "must support the 'line' argument";
394            const char *text_char = PyString_AS_STRING(text);
395
396            if (strcmp(msg, text_char) == 0) {
397                /* Prevent infinite recursion by using built-in implementation
398                   of showwarning(). */
399                show_warning(filename, lineno, text, category, sourceline);
400            }
401            else {
402                PyObject *check_fxn;
403                PyObject *defaults;
404                PyObject *res;
405
406                if (PyMethod_Check(show_fxn))
407                    check_fxn = PyMethod_Function(show_fxn);
408                else if (PyFunction_Check(show_fxn))
409                    check_fxn = show_fxn;
410                else {
411                    PyErr_SetString(PyExc_TypeError,
412                                    "warnings.showwarning() must be set to a "
413                                    "function or method");
414                    Py_DECREF(show_fxn);
415                    goto cleanup;
416                }
417
418                defaults = PyFunction_GetDefaults(check_fxn);
419                /* A proper implementation of warnings.showwarning() should
420                    have at least two default arguments. */
421                if ((defaults == NULL) || (PyTuple_Size(defaults) < 2)) {
422	            PyCodeObject *code = (PyCodeObject *)
423						PyFunction_GetCode(check_fxn);
424		    if (!(code->co_flags & CO_VARARGS)) {
425		        if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) <
426				0) {
427                            Py_DECREF(show_fxn);
428                            goto cleanup;
429                        }
430                    }
431		}
432                res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
433                                                    filename, lineno_obj,
434                                                    NULL);
435                Py_DECREF(show_fxn);
436                Py_XDECREF(res);
437                if (res == NULL)
438                    goto cleanup;
439            }
440        }
441    }
442    else /* if (rc == -1) */
443        goto cleanup;
444
445 return_none:
446    result = Py_None;
447    Py_INCREF(result);
448
449 cleanup:
450    Py_XDECREF(key);
451    Py_XDECREF(text);
452    Py_XDECREF(lineno_obj);
453    Py_DECREF(module);
454    Py_XDECREF(message);
455    return result;  /* Py_None or NULL. */
456}
457
458/* filename, module, and registry are new refs, globals is borrowed */
459/* Returns 0 on error (no new refs), 1 on success */
460static int
461setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
462              PyObject **module, PyObject **registry)
463{
464    PyObject *globals;
465
466    /* Setup globals and lineno. */
467    PyFrameObject *f = PyThreadState_GET()->frame;
468    while (--stack_level > 0 && f != NULL)
469        f = f->f_back;
470
471    if (f == NULL) {
472        globals = PyThreadState_Get()->interp->sysdict;
473        *lineno = 1;
474    }
475    else {
476        globals = f->f_globals;
477        *lineno = PyFrame_GetLineNumber(f);
478    }
479
480    *module = NULL;
481
482    /* Setup registry. */
483    assert(globals != NULL);
484    assert(PyDict_Check(globals));
485    *registry = PyDict_GetItemString(globals, "__warningregistry__");
486    if (*registry == NULL) {
487        int rc;
488
489        *registry = PyDict_New();
490        if (*registry == NULL)
491            return 0;
492
493         rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
494         if (rc < 0)
495            goto handle_error;
496    }
497    else
498        Py_INCREF(*registry);
499
500    /* Setup module. */
501    *module = PyDict_GetItemString(globals, "__name__");
502    if (*module == NULL) {
503        *module = PyString_FromString("<string>");
504        if (*module == NULL)
505            goto handle_error;
506    }
507    else
508        Py_INCREF(*module);
509
510    /* Setup filename. */
511    *filename = PyDict_GetItemString(globals, "__file__");
512    if (*filename != NULL) {
513	    Py_ssize_t len = PyString_Size(*filename);
514        const char *file_str = PyString_AsString(*filename);
515	    if (file_str == NULL || (len < 0 && PyErr_Occurred()))
516            goto handle_error;
517
518        /* if filename.lower().endswith((".pyc", ".pyo")): */
519        if (len >= 4 &&
520            file_str[len-4] == '.' &&
521            tolower(file_str[len-3]) == 'p' &&
522            tolower(file_str[len-2]) == 'y' &&
523            (tolower(file_str[len-1]) == 'c' ||
524                tolower(file_str[len-1]) == 'o'))
525        {
526            *filename = PyString_FromStringAndSize(file_str, len-1);
527	        if (*filename == NULL)
528		        goto handle_error;
529	    }
530	    else
531            Py_INCREF(*filename);
532    }
533    else {
534        const char *module_str = PyString_AsString(*module);
535        if (module_str && strcmp(module_str, "__main__") == 0) {
536            PyObject *argv = PySys_GetObject("argv");
537            if (argv != NULL && PyList_Size(argv) > 0) {
538                int is_true;
539                *filename = PyList_GetItem(argv, 0);
540                Py_INCREF(*filename);
541                /* If sys.argv[0] is false, then use '__main__'. */
542                is_true = PyObject_IsTrue(*filename);
543                if (is_true < 0) {
544                    Py_DECREF(*filename);
545                    goto handle_error;
546                }
547                else if (!is_true) {
548                    Py_DECREF(*filename);
549                    *filename = PyString_FromString("__main__");
550                    if (*filename == NULL)
551                        goto handle_error;
552                }
553            }
554            else {
555                /* embedded interpreters don't have sys.argv, see bug #839151 */
556                *filename = PyString_FromString("__main__");
557	            if (*filename == NULL)
558	                goto handle_error;
559            }
560        }
561        if (*filename == NULL) {
562            *filename = *module;
563            Py_INCREF(*filename);
564        }
565    }
566
567    return 1;
568
569 handle_error:
570    /* filename not XDECREF'ed here as there is no way to jump here with a
571       dangling reference. */
572    Py_XDECREF(*registry);
573    Py_XDECREF(*module);
574    return 0;
575}
576
577static PyObject *
578get_category(PyObject *message, PyObject *category)
579{
580    int rc;
581
582    /* Get category. */
583    rc = PyObject_IsInstance(message, PyExc_Warning);
584    if (rc == -1)
585        return NULL;
586
587    if (rc == 1)
588        category = (PyObject*)message->ob_type;
589    else if (category == NULL)
590        category = PyExc_UserWarning;
591
592    /* Validate category. */
593    rc = PyObject_IsSubclass(category, PyExc_Warning);
594    if (rc == -1)
595        return NULL;
596    if (rc == 0) {
597        PyErr_SetString(PyExc_ValueError,
598                        "category is not a subclass of Warning");
599        return NULL;
600    }
601
602    return category;
603}
604
605static PyObject *
606do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
607{
608    PyObject *filename, *module, *registry, *res;
609    int lineno;
610
611    if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
612        return NULL;
613
614    res = warn_explicit(category, message, filename, lineno, module, registry,
615                        NULL);
616    Py_DECREF(filename);
617    Py_DECREF(registry);
618    Py_DECREF(module);
619    return res;
620}
621
622static PyObject *
623warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
624{
625    static char *kw_list[] = { "message", "category", "stacklevel", 0 };
626    PyObject *message, *category = NULL;
627    Py_ssize_t stack_level = 1;
628
629    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
630                                     &message, &category, &stack_level))
631        return NULL;
632
633    category = get_category(message, category);
634    if (category == NULL)
635        return NULL;
636    return do_warn(message, category, stack_level);
637}
638
639static PyObject *
640warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
641{
642    static char *kwd_list[] = {"message", "category", "filename", "lineno",
643                                "module", "registry", "module_globals", 0};
644    PyObject *message;
645    PyObject *category;
646    PyObject *filename;
647    int lineno;
648    PyObject *module = NULL;
649    PyObject *registry = NULL;
650    PyObject *module_globals = NULL;
651
652    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
653                kwd_list, &message, &category, &filename, &lineno, &module,
654                &registry, &module_globals))
655        return NULL;
656
657    if (module_globals) {
658        static PyObject *get_source_name = NULL;
659        static PyObject *splitlines_name = NULL;
660        PyObject *loader;
661        PyObject *module_name;
662        PyObject *source;
663        PyObject *source_list;
664        PyObject *source_line;
665        PyObject *returned;
666
667        if (get_source_name == NULL) {
668            get_source_name = PyString_InternFromString("get_source");
669            if (!get_source_name)
670                return NULL;
671        }
672        if (splitlines_name == NULL) {
673            splitlines_name = PyString_InternFromString("splitlines");
674            if (!splitlines_name)
675                return NULL;
676        }
677
678        /* Check/get the requisite pieces needed for the loader. */
679        loader = PyDict_GetItemString(module_globals, "__loader__");
680        module_name = PyDict_GetItemString(module_globals, "__name__");
681
682        if (loader == NULL || module_name == NULL)
683            goto standard_call;
684
685        /* Make sure the loader implements the optional get_source() method. */
686        if (!PyObject_HasAttrString(loader, "get_source"))
687                goto standard_call;
688        /* Call get_source() to get the source code. */
689        source = PyObject_CallMethodObjArgs(loader, get_source_name,
690                                                module_name, NULL);
691        if (!source)
692            return NULL;
693        else if (source == Py_None) {
694            Py_DECREF(Py_None);
695            goto standard_call;
696        }
697
698        /* Split the source into lines. */
699        source_list = PyObject_CallMethodObjArgs(source, splitlines_name,
700                                                    NULL);
701        Py_DECREF(source);
702        if (!source_list)
703            return NULL;
704
705        /* Get the source line. */
706        source_line = PyList_GetItem(source_list, lineno-1);
707        if (!source_line) {
708            Py_DECREF(source_list);
709            return NULL;
710        }
711
712        /* Handle the warning. */
713        returned = warn_explicit(category, message, filename, lineno, module,
714                            registry, source_line);
715        Py_DECREF(source_list);
716        return returned;
717    }
718
719 standard_call:
720    return warn_explicit(category, message, filename, lineno, module,
721                                registry, NULL);
722}
723
724
725/* Function to issue a warning message; may raise an exception. */
726int
727PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
728{
729    PyObject *res;
730    PyObject *message = PyString_FromString(text);
731    if (message == NULL)
732        return -1;
733
734    if (category == NULL)
735        category = PyExc_RuntimeWarning;
736
737    res = do_warn(message, category, stack_level);
738    Py_DECREF(message);
739    if (res == NULL)
740        return -1;
741    Py_DECREF(res);
742
743    return 0;
744}
745
746/* PyErr_Warn is only for backwards compatability and will be removed.
747   Use PyErr_WarnEx instead. */
748
749#undef PyErr_Warn
750
751PyAPI_FUNC(int)
752PyErr_Warn(PyObject *category, char *text)
753{
754    return PyErr_WarnEx(category, text, 1);
755}
756
757/* Warning with explicit origin */
758int
759PyErr_WarnExplicit(PyObject *category, const char *text,
760                   const char *filename_str, int lineno,
761                   const char *module_str, PyObject *registry)
762{
763    PyObject *res;
764    PyObject *message = PyString_FromString(text);
765    PyObject *filename = PyString_FromString(filename_str);
766    PyObject *module = NULL;
767    int ret = -1;
768
769    if (message == NULL || filename == NULL)
770        goto exit;
771    if (module_str != NULL) {
772        module = PyString_FromString(module_str);
773            if (module == NULL)
774                goto exit;
775    }
776
777    if (category == NULL)
778        category = PyExc_RuntimeWarning;
779    res = warn_explicit(category, message, filename, lineno, module, registry,
780                        NULL);
781    if (res == NULL)
782        goto exit;
783    Py_DECREF(res);
784    ret = 0;
785
786 exit:
787    Py_XDECREF(message);
788    Py_XDECREF(module);
789    Py_XDECREF(filename);
790    return ret;
791}
792
793
794PyDoc_STRVAR(warn_doc,
795"Issue a warning, or maybe ignore it or raise an exception.");
796
797PyDoc_STRVAR(warn_explicit_doc,
798"Low-level inferface to warnings functionality.");
799
800static PyMethodDef warnings_functions[] = {
801    {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
802        warn_doc},
803    {"warn_explicit", (PyCFunction)warnings_warn_explicit,
804        METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
805    /* XXX(brett.cannon): add showwarning? */
806    /* XXX(brett.cannon): Reasonable to add formatwarning? */
807    {NULL, NULL}	        /* sentinel */
808};
809
810
811static PyObject *
812create_filter(PyObject *category, const char *action)
813{
814    static PyObject *ignore_str = NULL;
815    static PyObject *error_str = NULL;
816    static PyObject *default_str = NULL;
817    PyObject *action_obj = NULL;
818    PyObject *lineno, *result;
819
820    if (!strcmp(action, "ignore")) {
821        if (ignore_str == NULL) {
822            ignore_str = PyString_InternFromString("ignore");
823            if (ignore_str == NULL)
824                return NULL;
825        }
826        action_obj = ignore_str;
827    }
828    else if (!strcmp(action, "error")) {
829        if (error_str == NULL) {
830            error_str = PyString_InternFromString("error");
831            if (error_str == NULL)
832                return NULL;
833        }
834        action_obj = error_str;
835    }
836    else if (!strcmp(action, "default")) {
837        if (default_str == NULL) {
838            default_str = PyString_InternFromString("default");
839            if (default_str == NULL)
840                return NULL;
841        }
842        action_obj = default_str;
843    }
844    else {
845        Py_FatalError("unknown action");
846    }
847
848    /* This assumes the line number is zero for now. */
849    lineno = PyInt_FromLong(0);
850    if (lineno == NULL)
851        return NULL;
852    result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
853    Py_DECREF(lineno);
854    return result;
855}
856
857static PyObject *
858init_filters(void)
859{
860    PyObject *filters = PyList_New(3);
861    const char *bytes_action;
862    if (filters == NULL)
863        return NULL;
864
865    PyList_SET_ITEM(filters, 0,
866                    create_filter(PyExc_PendingDeprecationWarning, "ignore"));
867    PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore"));
868    if (Py_BytesWarningFlag > 1)
869        bytes_action = "error";
870    else if (Py_BytesWarningFlag)
871        bytes_action = "default";
872    else
873        bytes_action = "ignore";
874    PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning,
875                    bytes_action));
876
877    if (PyList_GET_ITEM(filters, 0) == NULL ||
878        PyList_GET_ITEM(filters, 1) == NULL ||
879        PyList_GET_ITEM(filters, 2) == NULL) {
880        Py_DECREF(filters);
881        return NULL;
882    }
883
884    return filters;
885}
886
887
888PyMODINIT_FUNC
889_PyWarnings_Init(void)
890{
891    PyObject *m, *default_action;
892
893    m = Py_InitModule3(MODULE_NAME, warnings_functions, warnings__doc__);
894    if (m == NULL)
895        return;
896
897    _filters = init_filters();
898    if (_filters == NULL)
899        return;
900    Py_INCREF(_filters);
901    if (PyModule_AddObject(m, "filters", _filters) < 0)
902        return;
903
904    _once_registry = PyDict_New();
905    if (_once_registry == NULL)
906        return;
907    Py_INCREF(_once_registry);
908    if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
909        return;
910
911    default_action = PyString_InternFromString("default");
912    if (default_action == NULL)
913        return;
914    if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0)
915        return;
916}