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 */
15static long _filters_version;
16
17_Py_IDENTIFIER(argv);
18_Py_IDENTIFIER(stderr);
19
20static int
21check_matched(PyObject *obj, PyObject *arg)
22{
23    PyObject *result;
24    _Py_IDENTIFIER(match);
25    int rc;
26
27    if (obj == Py_None)
28        return 1;
29    result = _PyObject_CallMethodId(obj, &PyId_match, "O", arg);
30    if (result == NULL)
31        return -1;
32
33    rc = PyObject_IsTrue(result);
34    Py_DECREF(result);
35    return rc;
36}
37
38/*
39   Returns a new reference.
40   A NULL return value can mean false or an error.
41*/
42static PyObject *
43get_warnings_attr(const char *attr, int try_import)
44{
45    static PyObject *warnings_str = NULL;
46    PyObject *all_modules;
47    PyObject *warnings_module, *obj;
48
49    if (warnings_str == NULL) {
50        warnings_str = PyUnicode_InternFromString("warnings");
51        if (warnings_str == NULL)
52            return NULL;
53    }
54
55    /* don't try to import after the start of the Python finallization */
56    if (try_import && _Py_Finalizing == NULL) {
57        warnings_module = PyImport_Import(warnings_str);
58        if (warnings_module == NULL) {
59            /* Fallback to the C implementation if we cannot get
60               the Python implementation */
61            PyErr_Clear();
62            return NULL;
63        }
64    }
65    else {
66        all_modules = PyImport_GetModuleDict();
67
68        warnings_module = PyDict_GetItem(all_modules, warnings_str);
69        if (warnings_module == NULL)
70            return NULL;
71
72        Py_INCREF(warnings_module);
73    }
74
75    if (!PyObject_HasAttrString(warnings_module, attr)) {
76        Py_DECREF(warnings_module);
77        return NULL;
78    }
79
80    obj = PyObject_GetAttrString(warnings_module, attr);
81    Py_DECREF(warnings_module);
82    return obj;
83}
84
85
86static PyObject *
87get_once_registry(void)
88{
89    PyObject *registry;
90
91    registry = get_warnings_attr("onceregistry", 0);
92    if (registry == NULL) {
93        if (PyErr_Occurred())
94            return NULL;
95        return _once_registry;
96    }
97    Py_DECREF(_once_registry);
98    _once_registry = registry;
99    return registry;
100}
101
102
103static PyObject *
104get_default_action(void)
105{
106    PyObject *default_action;
107
108    default_action = get_warnings_attr("defaultaction", 0);
109    if (default_action == NULL) {
110        if (PyErr_Occurred()) {
111            return NULL;
112        }
113        return _default_action;
114    }
115
116    Py_DECREF(_default_action);
117    _default_action = default_action;
118    return default_action;
119}
120
121
122/* The item is a new reference. */
123static PyObject*
124get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
125           PyObject *module, PyObject **item)
126{
127    PyObject *action;
128    Py_ssize_t i;
129    PyObject *warnings_filters;
130
131    warnings_filters = get_warnings_attr("filters", 0);
132    if (warnings_filters == NULL) {
133        if (PyErr_Occurred())
134            return NULL;
135    }
136    else {
137        Py_DECREF(_filters);
138        _filters = warnings_filters;
139    }
140
141    if (_filters == NULL || !PyList_Check(_filters)) {
142        PyErr_SetString(PyExc_ValueError,
143                        MODULE_NAME ".filters must be a list");
144        return NULL;
145    }
146
147    /* _filters could change while we are iterating over it. */
148    for (i = 0; i < PyList_GET_SIZE(_filters); i++) {
149        PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
150        Py_ssize_t ln;
151        int is_subclass, good_msg, good_mod;
152
153        tmp_item = PyList_GET_ITEM(_filters, i);
154        if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {
155            PyErr_Format(PyExc_ValueError,
156                         MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
157            return NULL;
158        }
159
160        /* Python code: action, msg, cat, mod, ln = item */
161        Py_INCREF(tmp_item);
162        action = PyTuple_GET_ITEM(tmp_item, 0);
163        msg = PyTuple_GET_ITEM(tmp_item, 1);
164        cat = PyTuple_GET_ITEM(tmp_item, 2);
165        mod = PyTuple_GET_ITEM(tmp_item, 3);
166        ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
167
168        good_msg = check_matched(msg, text);
169        if (good_msg == -1) {
170            Py_DECREF(tmp_item);
171            return NULL;
172        }
173
174        good_mod = check_matched(mod, module);
175        if (good_mod == -1) {
176            Py_DECREF(tmp_item);
177            return NULL;
178        }
179
180        is_subclass = PyObject_IsSubclass(category, cat);
181        if (is_subclass == -1) {
182            Py_DECREF(tmp_item);
183            return NULL;
184        }
185
186        ln = PyLong_AsSsize_t(ln_obj);
187        if (ln == -1 && PyErr_Occurred()) {
188            Py_DECREF(tmp_item);
189            return NULL;
190        }
191
192        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
193            *item = tmp_item;
194            return action;
195        }
196
197        Py_DECREF(tmp_item);
198    }
199
200    action = get_default_action();
201    if (action != NULL) {
202        Py_INCREF(Py_None);
203        *item = Py_None;
204        return action;
205    }
206
207    PyErr_SetString(PyExc_ValueError,
208                    MODULE_NAME ".defaultaction not found");
209    return NULL;
210}
211
212
213static int
214already_warned(PyObject *registry, PyObject *key, int should_set)
215{
216    PyObject *version_obj, *already_warned;
217    _Py_IDENTIFIER(version);
218
219    if (key == NULL)
220        return -1;
221
222    version_obj = _PyDict_GetItemId(registry, &PyId_version);
223    if (version_obj == NULL
224        || !PyLong_CheckExact(version_obj)
225        || PyLong_AsLong(version_obj) != _filters_version) {
226        PyDict_Clear(registry);
227        version_obj = PyLong_FromLong(_filters_version);
228        if (version_obj == NULL)
229            return -1;
230        if (_PyDict_SetItemId(registry, &PyId_version, version_obj) < 0) {
231            Py_DECREF(version_obj);
232            return -1;
233        }
234        Py_DECREF(version_obj);
235    }
236    else {
237        already_warned = PyDict_GetItem(registry, key);
238        if (already_warned != NULL) {
239            int rc = PyObject_IsTrue(already_warned);
240            if (rc != 0)
241                return rc;
242        }
243    }
244
245    /* This warning wasn't found in the registry, set it. */
246    if (should_set)
247        return PyDict_SetItem(registry, key, Py_True);
248    return 0;
249}
250
251/* New reference. */
252static PyObject *
253normalize_module(PyObject *filename)
254{
255    PyObject *module;
256    int kind;
257    void *data;
258    Py_ssize_t len;
259
260    len = PyUnicode_GetLength(filename);
261    if (len < 0)
262        return NULL;
263
264    if (len == 0)
265        return PyUnicode_FromString("<unknown>");
266
267    kind = PyUnicode_KIND(filename);
268    data = PyUnicode_DATA(filename);
269
270    /* if filename.endswith(".py"): */
271    if (len >= 3 &&
272        PyUnicode_READ(kind, data, len-3) == '.' &&
273        PyUnicode_READ(kind, data, len-2) == 'p' &&
274        PyUnicode_READ(kind, data, len-1) == 'y')
275    {
276        module = PyUnicode_Substring(filename, 0, len-3);
277    }
278    else {
279        module = filename;
280        Py_INCREF(module);
281    }
282    return module;
283}
284
285static int
286update_registry(PyObject *registry, PyObject *text, PyObject *category,
287                int add_zero)
288{
289    PyObject *altkey, *zero = NULL;
290    int rc;
291
292    if (add_zero) {
293        zero = PyLong_FromLong(0);
294        if (zero == NULL)
295            return -1;
296        altkey = PyTuple_Pack(3, text, category, zero);
297    }
298    else
299        altkey = PyTuple_Pack(2, text, category);
300
301    rc = already_warned(registry, altkey, 1);
302    Py_XDECREF(zero);
303    Py_XDECREF(altkey);
304    return rc;
305}
306
307static void
308show_warning(PyObject *filename, int lineno, PyObject *text,
309             PyObject *category, PyObject *sourceline)
310{
311    PyObject *f_stderr;
312    PyObject *name;
313    char lineno_str[128];
314    _Py_IDENTIFIER(__name__);
315
316    PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
317
318    name = _PyObject_GetAttrId(category, &PyId___name__);
319    if (name == NULL)  /* XXX Can an object lack a '__name__' attribute? */
320        goto error;
321
322    f_stderr = _PySys_GetObjectId(&PyId_stderr);
323    if (f_stderr == NULL) {
324        fprintf(stderr, "lost sys.stderr\n");
325        goto error;
326    }
327
328    /* Print "filename:lineno: category: text\n" */
329    if (PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW) < 0)
330        goto error;
331    if (PyFile_WriteString(lineno_str, f_stderr) < 0)
332        goto error;
333    if (PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW) < 0)
334        goto error;
335    if (PyFile_WriteString(": ", f_stderr) < 0)
336        goto error;
337    if (PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW) < 0)
338        goto error;
339    if (PyFile_WriteString("\n", f_stderr) < 0)
340        goto error;
341    Py_CLEAR(name);
342
343    /* Print "  source_line\n" */
344    if (sourceline) {
345        int kind;
346        void *data;
347        Py_ssize_t i, len;
348        Py_UCS4 ch;
349        PyObject *truncated;
350
351        if (PyUnicode_READY(sourceline) < 1)
352            goto error;
353
354        kind = PyUnicode_KIND(sourceline);
355        data = PyUnicode_DATA(sourceline);
356        len = PyUnicode_GET_LENGTH(sourceline);
357        for (i=0; i<len; i++) {
358            ch = PyUnicode_READ(kind, data, i);
359            if (ch != ' ' && ch != '\t' && ch != '\014')
360                break;
361        }
362
363        truncated = PyUnicode_Substring(sourceline, i, len);
364        if (truncated == NULL)
365            goto error;
366
367        PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW);
368        Py_DECREF(truncated);
369        PyFile_WriteString("\n", f_stderr);
370    }
371    else {
372        _Py_DisplaySourceLine(f_stderr, filename, lineno, 2);
373    }
374
375error:
376    Py_XDECREF(name);
377    PyErr_Clear();
378}
379
380static int
381call_show_warning(PyObject *category, PyObject *text, PyObject *message,
382                  PyObject *filename, int lineno, PyObject *lineno_obj,
383                  PyObject *sourceline, PyObject *source)
384{
385    PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;
386
387    /* If the source parameter is set, try to get the Python implementation.
388       The Python implementation is able to log the traceback where the source
389       was allocated, whereas the C implementation doesnt. */
390    show_fn = get_warnings_attr("_showwarnmsg", source != NULL);
391    if (show_fn == NULL) {
392        if (PyErr_Occurred())
393            return -1;
394        show_warning(filename, lineno, text, category, sourceline);
395        return 0;
396    }
397
398    if (!PyCallable_Check(show_fn)) {
399        PyErr_SetString(PyExc_TypeError,
400                "warnings._showwarnmsg() must be set to a callable");
401        goto error;
402    }
403
404    warnmsg_cls = get_warnings_attr("WarningMessage", 0);
405    if (warnmsg_cls == NULL) {
406        PyErr_SetString(PyExc_RuntimeError,
407                "unable to get warnings.WarningMessage");
408        goto error;
409    }
410
411    msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category,
412            filename, lineno_obj, Py_None, Py_None, source,
413            NULL);
414    Py_DECREF(warnmsg_cls);
415    if (msg == NULL)
416        goto error;
417
418    res = PyObject_CallFunctionObjArgs(show_fn, msg, NULL);
419    Py_DECREF(show_fn);
420    Py_DECREF(msg);
421
422    if (res == NULL)
423        return -1;
424
425    Py_DECREF(res);
426    return 0;
427
428error:
429    Py_XDECREF(show_fn);
430    return -1;
431}
432
433static PyObject *
434warn_explicit(PyObject *category, PyObject *message,
435              PyObject *filename, int lineno,
436              PyObject *module, PyObject *registry, PyObject *sourceline,
437              PyObject *source)
438{
439    PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
440    PyObject *item = NULL;
441    PyObject *action;
442    int rc;
443
444    /* module can be None if a warning is emitted late during Python shutdown.
445       In this case, the Python warnings module was probably unloaded, filters
446       are no more available to choose as action. It is safer to ignore the
447       warning and do nothing. */
448    if (module == Py_None)
449        Py_RETURN_NONE;
450
451    if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
452        PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
453        return NULL;
454    }
455
456    /* Normalize module. */
457    if (module == NULL) {
458        module = normalize_module(filename);
459        if (module == NULL)
460            return NULL;
461    }
462    else
463        Py_INCREF(module);
464
465    /* Normalize message. */
466    Py_INCREF(message);  /* DECREF'ed in cleanup. */
467    rc = PyObject_IsInstance(message, PyExc_Warning);
468    if (rc == -1) {
469        goto cleanup;
470    }
471    if (rc == 1) {
472        text = PyObject_Str(message);
473        if (text == NULL)
474            goto cleanup;
475        category = (PyObject*)message->ob_type;
476    }
477    else {
478        text = message;
479        message = PyObject_CallFunction(category, "O", message);
480        if (message == NULL)
481            goto cleanup;
482    }
483
484    lineno_obj = PyLong_FromLong(lineno);
485    if (lineno_obj == NULL)
486        goto cleanup;
487
488    /* Create key. */
489    key = PyTuple_Pack(3, text, category, lineno_obj);
490    if (key == NULL)
491        goto cleanup;
492
493    if ((registry != NULL) && (registry != Py_None)) {
494        rc = already_warned(registry, key, 0);
495        if (rc == -1)
496            goto cleanup;
497        else if (rc == 1)
498            goto return_none;
499        /* Else this warning hasn't been generated before. */
500    }
501
502    action = get_filter(category, text, lineno, module, &item);
503    if (action == NULL)
504        goto cleanup;
505
506    if (_PyUnicode_EqualToASCIIString(action, "error")) {
507        PyErr_SetObject(category, message);
508        goto cleanup;
509    }
510
511    /* Store in the registry that we've been here, *except* when the action
512       is "always". */
513    rc = 0;
514    if (!_PyUnicode_EqualToASCIIString(action, "always")) {
515        if (registry != NULL && registry != Py_None &&
516                PyDict_SetItem(registry, key, Py_True) < 0)
517            goto cleanup;
518        else if (_PyUnicode_EqualToASCIIString(action, "ignore"))
519            goto return_none;
520        else if (_PyUnicode_EqualToASCIIString(action, "once")) {
521            if (registry == NULL || registry == Py_None) {
522                registry = get_once_registry();
523                if (registry == NULL)
524                    goto cleanup;
525            }
526            /* _once_registry[(text, category)] = 1 */
527            rc = update_registry(registry, text, category, 0);
528        }
529        else if (_PyUnicode_EqualToASCIIString(action, "module")) {
530            /* registry[(text, category, 0)] = 1 */
531            if (registry != NULL && registry != Py_None)
532                rc = update_registry(registry, text, category, 0);
533        }
534        else if (!_PyUnicode_EqualToASCIIString(action, "default")) {
535            PyErr_Format(PyExc_RuntimeError,
536                        "Unrecognized action (%R) in warnings.filters:\n %R",
537                        action, item);
538            goto cleanup;
539        }
540    }
541
542    if (rc == 1)  /* Already warned for this module. */
543        goto return_none;
544    if (rc == 0) {
545        if (call_show_warning(category, text, message, filename, lineno,
546                              lineno_obj, sourceline, source) < 0)
547            goto cleanup;
548    }
549    else /* if (rc == -1) */
550        goto cleanup;
551
552 return_none:
553    result = Py_None;
554    Py_INCREF(result);
555
556 cleanup:
557    Py_XDECREF(item);
558    Py_XDECREF(key);
559    Py_XDECREF(text);
560    Py_XDECREF(lineno_obj);
561    Py_DECREF(module);
562    Py_XDECREF(message);
563    return result;  /* Py_None or NULL. */
564}
565
566static int
567is_internal_frame(PyFrameObject *frame)
568{
569    static PyObject *importlib_string = NULL;
570    static PyObject *bootstrap_string = NULL;
571    PyObject *filename;
572    int contains;
573
574    if (importlib_string == NULL) {
575        importlib_string = PyUnicode_FromString("importlib");
576        if (importlib_string == NULL) {
577            return 0;
578        }
579
580        bootstrap_string = PyUnicode_FromString("_bootstrap");
581        if (bootstrap_string == NULL) {
582            Py_DECREF(importlib_string);
583            return 0;
584        }
585        Py_INCREF(importlib_string);
586        Py_INCREF(bootstrap_string);
587    }
588
589    if (frame == NULL || frame->f_code == NULL ||
590            frame->f_code->co_filename == NULL) {
591        return 0;
592    }
593    filename = frame->f_code->co_filename;
594    if (!PyUnicode_Check(filename)) {
595        return 0;
596    }
597    contains = PyUnicode_Contains(filename, importlib_string);
598    if (contains < 0) {
599        return 0;
600    }
601    else if (contains > 0) {
602        contains = PyUnicode_Contains(filename, bootstrap_string);
603        if (contains < 0) {
604            return 0;
605        }
606        else if (contains > 0) {
607            return 1;
608        }
609    }
610
611    return 0;
612}
613
614static PyFrameObject *
615next_external_frame(PyFrameObject *frame)
616{
617    do {
618        frame = frame->f_back;
619    } while (frame != NULL && is_internal_frame(frame));
620
621    return frame;
622}
623
624/* filename, module, and registry are new refs, globals is borrowed */
625/* Returns 0 on error (no new refs), 1 on success */
626static int
627setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
628              PyObject **module, PyObject **registry)
629{
630    PyObject *globals;
631
632    /* Setup globals and lineno. */
633    PyFrameObject *f = PyThreadState_GET()->frame;
634    // Stack level comparisons to Python code is off by one as there is no
635    // warnings-related stack level to avoid.
636    if (stack_level <= 0 || is_internal_frame(f)) {
637        while (--stack_level > 0 && f != NULL) {
638            f = f->f_back;
639        }
640    }
641    else {
642        while (--stack_level > 0 && f != NULL) {
643            f = next_external_frame(f);
644        }
645    }
646
647    if (f == NULL) {
648        globals = PyThreadState_Get()->interp->sysdict;
649        *lineno = 1;
650    }
651    else {
652        globals = f->f_globals;
653        *lineno = PyFrame_GetLineNumber(f);
654    }
655
656    *module = NULL;
657
658    /* Setup registry. */
659    assert(globals != NULL);
660    assert(PyDict_Check(globals));
661    *registry = PyDict_GetItemString(globals, "__warningregistry__");
662    if (*registry == NULL) {
663        int rc;
664
665        *registry = PyDict_New();
666        if (*registry == NULL)
667            return 0;
668
669         rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
670         if (rc < 0)
671            goto handle_error;
672    }
673    else
674        Py_INCREF(*registry);
675
676    /* Setup module. */
677    *module = PyDict_GetItemString(globals, "__name__");
678    if (*module == NULL) {
679        *module = PyUnicode_FromString("<string>");
680        if (*module == NULL)
681            goto handle_error;
682    }
683    else
684        Py_INCREF(*module);
685
686    /* Setup filename. */
687    *filename = PyDict_GetItemString(globals, "__file__");
688    if (*filename != NULL && PyUnicode_Check(*filename)) {
689        Py_ssize_t len;
690        int kind;
691        void *data;
692
693        if (PyUnicode_READY(*filename))
694            goto handle_error;
695
696        len = PyUnicode_GetLength(*filename);
697        kind = PyUnicode_KIND(*filename);
698        data = PyUnicode_DATA(*filename);
699
700#define ascii_lower(c) ((c <= 127) ? Py_TOLOWER(c) : 0)
701        /* if filename.lower().endswith(".pyc"): */
702        if (len >= 4 &&
703            PyUnicode_READ(kind, data, len-4) == '.' &&
704            ascii_lower(PyUnicode_READ(kind, data, len-3)) == 'p' &&
705            ascii_lower(PyUnicode_READ(kind, data, len-2)) == 'y' &&
706            ascii_lower(PyUnicode_READ(kind, data, len-1)) == 'c')
707        {
708            *filename = PyUnicode_Substring(*filename, 0,
709                                            PyUnicode_GET_LENGTH(*filename)-1);
710            if (*filename == NULL)
711                goto handle_error;
712        }
713        else
714            Py_INCREF(*filename);
715    }
716    else {
717        *filename = NULL;
718        if (*module != Py_None && _PyUnicode_EqualToASCIIString(*module, "__main__")) {
719            PyObject *argv = _PySys_GetObjectId(&PyId_argv);
720            /* PyList_Check() is needed because sys.argv is set to None during
721               Python finalization */
722            if (argv != NULL && PyList_Check(argv) && PyList_Size(argv) > 0) {
723                int is_true;
724                *filename = PyList_GetItem(argv, 0);
725                Py_INCREF(*filename);
726                /* If sys.argv[0] is false, then use '__main__'. */
727                is_true = PyObject_IsTrue(*filename);
728                if (is_true < 0) {
729                    Py_DECREF(*filename);
730                    goto handle_error;
731                }
732                else if (!is_true) {
733                    Py_SETREF(*filename, PyUnicode_FromString("__main__"));
734                    if (*filename == NULL)
735                        goto handle_error;
736                }
737            }
738            else {
739                /* embedded interpreters don't have sys.argv, see bug #839151 */
740                *filename = PyUnicode_FromString("__main__");
741                if (*filename == NULL)
742                    goto handle_error;
743            }
744        }
745        if (*filename == NULL) {
746            *filename = *module;
747            Py_INCREF(*filename);
748        }
749    }
750
751    return 1;
752
753 handle_error:
754    /* filename not XDECREF'ed here as there is no way to jump here with a
755       dangling reference. */
756    Py_XDECREF(*registry);
757    Py_XDECREF(*module);
758    return 0;
759}
760
761static PyObject *
762get_category(PyObject *message, PyObject *category)
763{
764    int rc;
765
766    /* Get category. */
767    rc = PyObject_IsInstance(message, PyExc_Warning);
768    if (rc == -1)
769        return NULL;
770
771    if (rc == 1)
772        category = (PyObject*)message->ob_type;
773    else if (category == NULL || category == Py_None)
774        category = PyExc_UserWarning;
775
776    /* Validate category. */
777    rc = PyObject_IsSubclass(category, PyExc_Warning);
778    /* category is not a subclass of PyExc_Warning or
779       PyObject_IsSubclass raised an error */
780    if (rc == -1 || rc == 0) {
781        PyErr_Format(PyExc_TypeError,
782                     "category must be a Warning subclass, not '%s'",
783                     Py_TYPE(category)->tp_name);
784        return NULL;
785    }
786
787    return category;
788}
789
790static PyObject *
791do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
792        PyObject *source)
793{
794    PyObject *filename, *module, *registry, *res;
795    int lineno;
796
797    if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
798        return NULL;
799
800    res = warn_explicit(category, message, filename, lineno, module, registry,
801                        NULL, source);
802    Py_DECREF(filename);
803    Py_DECREF(registry);
804    Py_DECREF(module);
805    return res;
806}
807
808static PyObject *
809warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
810{
811    static char *kw_list[] = {"message", "category", "stacklevel",
812                              "source", NULL};
813    PyObject *message, *category = NULL, *source = NULL;
814    Py_ssize_t stack_level = 1;
815
816    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OnO:warn", kw_list,
817                                     &message, &category, &stack_level, &source))
818        return NULL;
819
820    category = get_category(message, category);
821    if (category == NULL)
822        return NULL;
823    return do_warn(message, category, stack_level, source);
824}
825
826static PyObject *
827warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
828{
829    static char *kwd_list[] = {"message", "category", "filename", "lineno",
830                                "module", "registry", "module_globals",
831                                "source", 0};
832    PyObject *message;
833    PyObject *category;
834    PyObject *filename;
835    int lineno;
836    PyObject *module = NULL;
837    PyObject *registry = NULL;
838    PyObject *module_globals = NULL;
839    PyObject *sourceobj = NULL;
840
841    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit",
842                kwd_list, &message, &category, &filename, &lineno, &module,
843                &registry, &module_globals, &sourceobj))
844        return NULL;
845
846    if (module_globals) {
847        _Py_IDENTIFIER(get_source);
848        _Py_IDENTIFIER(splitlines);
849        PyObject *tmp;
850        PyObject *loader;
851        PyObject *module_name;
852        PyObject *source;
853        PyObject *source_list;
854        PyObject *source_line;
855        PyObject *returned;
856
857        if ((tmp = _PyUnicode_FromId(&PyId_get_source)) == NULL)
858            return NULL;
859        if ((tmp = _PyUnicode_FromId(&PyId_splitlines)) == NULL)
860            return NULL;
861
862        /* Check/get the requisite pieces needed for the loader. */
863        loader = PyDict_GetItemString(module_globals, "__loader__");
864        module_name = PyDict_GetItemString(module_globals, "__name__");
865
866        if (loader == NULL || module_name == NULL)
867            goto standard_call;
868
869        /* Make sure the loader implements the optional get_source() method. */
870        if (!_PyObject_HasAttrId(loader, &PyId_get_source))
871                goto standard_call;
872        /* Call get_source() to get the source code. */
873        source = PyObject_CallMethodObjArgs(loader, PyId_get_source.object,
874                                            module_name, NULL);
875        if (!source)
876            return NULL;
877        else if (source == Py_None) {
878            Py_DECREF(Py_None);
879            goto standard_call;
880        }
881
882        /* Split the source into lines. */
883        source_list = PyObject_CallMethodObjArgs(source,
884                                                 PyId_splitlines.object,
885                                                 NULL);
886        Py_DECREF(source);
887        if (!source_list)
888            return NULL;
889
890        /* Get the source line. */
891        source_line = PyList_GetItem(source_list, lineno-1);
892        if (!source_line) {
893            Py_DECREF(source_list);
894            return NULL;
895        }
896
897        /* Handle the warning. */
898        returned = warn_explicit(category, message, filename, lineno, module,
899                                 registry, source_line, sourceobj);
900        Py_DECREF(source_list);
901        return returned;
902    }
903
904 standard_call:
905    return warn_explicit(category, message, filename, lineno, module,
906                         registry, NULL, sourceobj);
907}
908
909static PyObject *
910warnings_filters_mutated(PyObject *self, PyObject *args)
911{
912    _filters_version++;
913    Py_RETURN_NONE;
914}
915
916
917/* Function to issue a warning message; may raise an exception. */
918
919static int
920warn_unicode(PyObject *category, PyObject *message,
921             Py_ssize_t stack_level, PyObject *source)
922{
923    PyObject *res;
924
925    if (category == NULL)
926        category = PyExc_RuntimeWarning;
927
928    res = do_warn(message, category, stack_level, source);
929    if (res == NULL)
930        return -1;
931    Py_DECREF(res);
932
933    return 0;
934}
935
936static int
937_PyErr_WarnFormatV(PyObject *source,
938                   PyObject *category, Py_ssize_t stack_level,
939                   const char *format, va_list vargs)
940{
941    PyObject *message;
942    int res;
943
944    message = PyUnicode_FromFormatV(format, vargs);
945    if (message == NULL)
946        return -1;
947
948    res = warn_unicode(category, message, stack_level, source);
949    Py_DECREF(message);
950    return res;
951}
952
953int
954PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
955                 const char *format, ...)
956{
957    int res;
958    va_list vargs;
959
960#ifdef HAVE_STDARG_PROTOTYPES
961    va_start(vargs, format);
962#else
963    va_start(vargs);
964#endif
965    res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
966    va_end(vargs);
967    return res;
968}
969
970int
971PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
972                      const char *format, ...)
973{
974    int res;
975    va_list vargs;
976
977#ifdef HAVE_STDARG_PROTOTYPES
978    va_start(vargs, format);
979#else
980    va_start(vargs);
981#endif
982    res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
983                             stack_level, format, vargs);
984    va_end(vargs);
985    return res;
986}
987
988
989int
990PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
991{
992    int ret;
993    PyObject *message = PyUnicode_FromString(text);
994    if (message == NULL)
995        return -1;
996    ret = warn_unicode(category, message, stack_level, NULL);
997    Py_DECREF(message);
998    return ret;
999}
1000
1001/* PyErr_Warn is only for backwards compatibility and will be removed.
1002   Use PyErr_WarnEx instead. */
1003
1004#undef PyErr_Warn
1005
1006PyAPI_FUNC(int)
1007PyErr_Warn(PyObject *category, const char *text)
1008{
1009    return PyErr_WarnEx(category, text, 1);
1010}
1011
1012/* Warning with explicit origin */
1013int
1014PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
1015                         PyObject *filename, int lineno,
1016                         PyObject *module, PyObject *registry)
1017{
1018    PyObject *res;
1019    if (category == NULL)
1020        category = PyExc_RuntimeWarning;
1021    res = warn_explicit(category, message, filename, lineno,
1022                        module, registry, NULL, NULL);
1023    if (res == NULL)
1024        return -1;
1025    Py_DECREF(res);
1026    return 0;
1027}
1028
1029int
1030PyErr_WarnExplicit(PyObject *category, const char *text,
1031                   const char *filename_str, int lineno,
1032                   const char *module_str, PyObject *registry)
1033{
1034    PyObject *message = PyUnicode_FromString(text);
1035    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1036    PyObject *module = NULL;
1037    int ret = -1;
1038
1039    if (message == NULL || filename == NULL)
1040        goto exit;
1041    if (module_str != NULL) {
1042        module = PyUnicode_FromString(module_str);
1043        if (module == NULL)
1044            goto exit;
1045    }
1046
1047    ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
1048                                   module, registry);
1049
1050 exit:
1051    Py_XDECREF(message);
1052    Py_XDECREF(module);
1053    Py_XDECREF(filename);
1054    return ret;
1055}
1056
1057int
1058PyErr_WarnExplicitFormat(PyObject *category,
1059                         const char *filename_str, int lineno,
1060                         const char *module_str, PyObject *registry,
1061                         const char *format, ...)
1062{
1063    PyObject *message;
1064    PyObject *module = NULL;
1065    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1066    int ret = -1;
1067    va_list vargs;
1068
1069    if (filename == NULL)
1070        goto exit;
1071    if (module_str != NULL) {
1072        module = PyUnicode_FromString(module_str);
1073        if (module == NULL)
1074            goto exit;
1075    }
1076
1077#ifdef HAVE_STDARG_PROTOTYPES
1078    va_start(vargs, format);
1079#else
1080    va_start(vargs);
1081#endif
1082    message = PyUnicode_FromFormatV(format, vargs);
1083    if (message != NULL) {
1084        PyObject *res;
1085        res = warn_explicit(category, message, filename, lineno,
1086                            module, registry, NULL, NULL);
1087        Py_DECREF(message);
1088        if (res != NULL) {
1089            Py_DECREF(res);
1090            ret = 0;
1091        }
1092    }
1093    va_end(vargs);
1094exit:
1095    Py_XDECREF(module);
1096    Py_XDECREF(filename);
1097    return ret;
1098}
1099
1100
1101PyDoc_STRVAR(warn_doc,
1102"Issue a warning, or maybe ignore it or raise an exception.");
1103
1104PyDoc_STRVAR(warn_explicit_doc,
1105"Low-level inferface to warnings functionality.");
1106
1107static PyMethodDef warnings_functions[] = {
1108    {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
1109        warn_doc},
1110    {"warn_explicit", (PyCFunction)warnings_warn_explicit,
1111        METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
1112    {"_filters_mutated", (PyCFunction)warnings_filters_mutated, METH_NOARGS,
1113        NULL},
1114    /* XXX(brett.cannon): add showwarning? */
1115    /* XXX(brett.cannon): Reasonable to add formatwarning? */
1116    {NULL, NULL}                /* sentinel */
1117};
1118
1119
1120static PyObject *
1121create_filter(PyObject *category, const char *action)
1122{
1123    static PyObject *ignore_str = NULL;
1124    static PyObject *error_str = NULL;
1125    static PyObject *default_str = NULL;
1126    static PyObject *always_str = NULL;
1127    PyObject *action_obj = NULL;
1128    PyObject *lineno, *result;
1129
1130    if (!strcmp(action, "ignore")) {
1131        if (ignore_str == NULL) {
1132            ignore_str = PyUnicode_InternFromString("ignore");
1133            if (ignore_str == NULL)
1134                return NULL;
1135        }
1136        action_obj = ignore_str;
1137    }
1138    else if (!strcmp(action, "error")) {
1139        if (error_str == NULL) {
1140            error_str = PyUnicode_InternFromString("error");
1141            if (error_str == NULL)
1142                return NULL;
1143        }
1144        action_obj = error_str;
1145    }
1146    else if (!strcmp(action, "default")) {
1147        if (default_str == NULL) {
1148            default_str = PyUnicode_InternFromString("default");
1149            if (default_str == NULL)
1150                return NULL;
1151        }
1152        action_obj = default_str;
1153    }
1154    else if (!strcmp(action, "always")) {
1155        if (always_str == NULL) {
1156            always_str = PyUnicode_InternFromString("always");
1157            if (always_str == NULL)
1158                return NULL;
1159        }
1160        action_obj = always_str;
1161    }
1162    else {
1163        Py_FatalError("unknown action");
1164    }
1165
1166    /* This assumes the line number is zero for now. */
1167    lineno = PyLong_FromLong(0);
1168    if (lineno == NULL)
1169        return NULL;
1170    result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
1171    Py_DECREF(lineno);
1172    return result;
1173}
1174
1175static PyObject *
1176init_filters(void)
1177{
1178    PyObject *filters = PyList_New(5);
1179    unsigned int pos = 0;  /* Post-incremented in each use. */
1180    unsigned int x;
1181    const char *bytes_action, *resource_action;
1182
1183    if (filters == NULL)
1184        return NULL;
1185
1186    PyList_SET_ITEM(filters, pos++,
1187                    create_filter(PyExc_DeprecationWarning, "ignore"));
1188    PyList_SET_ITEM(filters, pos++,
1189                    create_filter(PyExc_PendingDeprecationWarning, "ignore"));
1190    PyList_SET_ITEM(filters, pos++,
1191                    create_filter(PyExc_ImportWarning, "ignore"));
1192    if (Py_BytesWarningFlag > 1)
1193        bytes_action = "error";
1194    else if (Py_BytesWarningFlag)
1195        bytes_action = "default";
1196    else
1197        bytes_action = "ignore";
1198    PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning,
1199                    bytes_action));
1200    /* resource usage warnings are enabled by default in pydebug mode */
1201#ifdef Py_DEBUG
1202    resource_action = "always";
1203#else
1204    resource_action = "ignore";
1205#endif
1206    PyList_SET_ITEM(filters, pos++, create_filter(PyExc_ResourceWarning,
1207                    resource_action));
1208    for (x = 0; x < pos; x += 1) {
1209        if (PyList_GET_ITEM(filters, x) == NULL) {
1210            Py_DECREF(filters);
1211            return NULL;
1212        }
1213    }
1214
1215    return filters;
1216}
1217
1218static struct PyModuleDef warningsmodule = {
1219        PyModuleDef_HEAD_INIT,
1220        MODULE_NAME,
1221        warnings__doc__,
1222        0,
1223        warnings_functions,
1224        NULL,
1225        NULL,
1226        NULL,
1227        NULL
1228};
1229
1230
1231PyMODINIT_FUNC
1232_PyWarnings_Init(void)
1233{
1234    PyObject *m;
1235
1236    m = PyModule_Create(&warningsmodule);
1237    if (m == NULL)
1238        return NULL;
1239
1240    if (_filters == NULL) {
1241        _filters = init_filters();
1242        if (_filters == NULL)
1243            return NULL;
1244    }
1245    Py_INCREF(_filters);
1246    if (PyModule_AddObject(m, "filters", _filters) < 0)
1247        return NULL;
1248
1249    if (_once_registry == NULL) {
1250        _once_registry = PyDict_New();
1251        if (_once_registry == NULL)
1252            return NULL;
1253    }
1254    Py_INCREF(_once_registry);
1255    if (PyModule_AddObject(m, "_onceregistry", _once_registry) < 0)
1256        return NULL;
1257
1258    if (_default_action == NULL) {
1259        _default_action = PyUnicode_FromString("default");
1260        if (_default_action == NULL)
1261            return NULL;
1262    }
1263    Py_INCREF(_default_action);
1264    if (PyModule_AddObject(m, "_defaultaction", _default_action) < 0)
1265        return NULL;
1266
1267    _filters_version = 0;
1268    return m;
1269}
1270