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