• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "Python.h"
2 #include "pycore_critical_section.h"  // Py_BEGIN_CRITICAL_SECTION_MUT()
3 #include "pycore_interp.h"        // PyInterpreterState.warnings
4 #include "pycore_long.h"          // _PyLong_GetZero()
5 #include "pycore_pyerrors.h"      // _PyErr_Occurred()
6 #include "pycore_pylifecycle.h"   // _Py_IsInterpreterFinalizing()
7 #include "pycore_pystate.h"       // _PyThreadState_GET()
8 #include "pycore_sysmodule.h"     // _PySys_GetAttr()
9 #include "pycore_traceback.h"     // _Py_DisplaySourceLine()
10 
11 #include <stdbool.h>
12 
13 #include "clinic/_warnings.c.h"
14 
15 #define MODULE_NAME "_warnings"
16 
17 PyDoc_STRVAR(warnings__doc__,
18 MODULE_NAME " provides basic warning filtering support.\n"
19 "It is a helper module to speed up interpreter start-up.");
20 
21 
22 /*************************************************************************/
23 
24 typedef struct _warnings_runtime_state WarningsState;
25 
26 static inline int
check_interp(PyInterpreterState * interp)27 check_interp(PyInterpreterState *interp)
28 {
29     if (interp == NULL) {
30         PyErr_SetString(PyExc_RuntimeError,
31                         "warnings_get_state: could not identify "
32                         "current interpreter");
33         return 0;
34     }
35     return 1;
36 }
37 
38 static inline PyInterpreterState *
get_current_interp(void)39 get_current_interp(void)
40 {
41     PyInterpreterState *interp = _PyInterpreterState_GET();
42     return check_interp(interp) ? interp : NULL;
43 }
44 
45 static inline PyThreadState *
get_current_tstate(void)46 get_current_tstate(void)
47 {
48     PyThreadState *tstate = _PyThreadState_GET();
49     if (tstate == NULL) {
50         (void)check_interp(NULL);
51         return NULL;
52     }
53     return check_interp(tstate->interp) ? tstate : NULL;
54 }
55 
56 /* Given a module object, get its per-module state. */
57 static WarningsState *
warnings_get_state(PyInterpreterState * interp)58 warnings_get_state(PyInterpreterState *interp)
59 {
60     return &interp->warnings;
61 }
62 
63 /* Clear the given warnings module state. */
64 static void
warnings_clear_state(WarningsState * st)65 warnings_clear_state(WarningsState *st)
66 {
67     Py_CLEAR(st->filters);
68     Py_CLEAR(st->once_registry);
69     Py_CLEAR(st->default_action);
70 }
71 
72 #ifndef Py_DEBUG
73 static PyObject *
create_filter(PyObject * category,PyObject * action_str,const char * modname)74 create_filter(PyObject *category, PyObject *action_str, const char *modname)
75 {
76     PyObject *modname_obj = NULL;
77 
78     /* Default to "no module name" for initial filter set */
79     if (modname != NULL) {
80         modname_obj = PyUnicode_InternFromString(modname);
81         if (modname_obj == NULL) {
82             return NULL;
83         }
84     } else {
85         modname_obj = Py_NewRef(Py_None);
86     }
87 
88     /* This assumes the line number is zero for now. */
89     PyObject *filter = PyTuple_Pack(5, action_str, Py_None,
90                                     category, modname_obj, _PyLong_GetZero());
91     Py_DECREF(modname_obj);
92     return filter;
93 }
94 #endif
95 
96 static PyObject *
init_filters(PyInterpreterState * interp)97 init_filters(PyInterpreterState *interp)
98 {
99 #ifdef Py_DEBUG
100     /* Py_DEBUG builds show all warnings by default */
101     return PyList_New(0);
102 #else
103     /* Other builds ignore a number of warning categories by default */
104     PyObject *filters = PyList_New(5);
105     if (filters == NULL) {
106         return NULL;
107     }
108 
109     size_t pos = 0;  /* Post-incremented in each use. */
110 #define ADD(TYPE, ACTION, MODNAME) \
111     PyList_SET_ITEM(filters, pos++, \
112                     create_filter(TYPE, &_Py_ID(ACTION), MODNAME));
113     ADD(PyExc_DeprecationWarning, default, "__main__");
114     ADD(PyExc_DeprecationWarning, ignore, NULL);
115     ADD(PyExc_PendingDeprecationWarning, ignore, NULL);
116     ADD(PyExc_ImportWarning, ignore, NULL);
117     ADD(PyExc_ResourceWarning, ignore, NULL);
118 #undef ADD
119 
120     for (size_t x = 0; x < pos; x++) {
121         if (PyList_GET_ITEM(filters, x) == NULL) {
122             Py_DECREF(filters);
123             return NULL;
124         }
125     }
126     return filters;
127 #endif
128 }
129 
130 /* Initialize the given warnings module state. */
131 int
_PyWarnings_InitState(PyInterpreterState * interp)132 _PyWarnings_InitState(PyInterpreterState *interp)
133 {
134     WarningsState *st = &interp->warnings;
135 
136     if (st->filters == NULL) {
137         st->filters = init_filters(interp);
138         if (st->filters == NULL) {
139             return -1;
140         }
141     }
142 
143     if (st->once_registry == NULL) {
144         st->once_registry = PyDict_New();
145         if (st->once_registry == NULL) {
146             return -1;
147         }
148     }
149 
150     if (st->default_action == NULL) {
151         st->default_action = PyUnicode_FromString("default");
152         if (st->default_action == NULL) {
153             return -1;
154         }
155     }
156 
157     st->filters_version = 0;
158     return 0;
159 }
160 
161 
162 /*************************************************************************/
163 
164 static int
check_matched(PyInterpreterState * interp,PyObject * obj,PyObject * arg)165 check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg)
166 {
167     PyObject *result;
168     int rc;
169 
170     /* A 'None' filter always matches */
171     if (obj == Py_None)
172         return 1;
173 
174     /* An internal plain text default filter must match exactly */
175     if (PyUnicode_CheckExact(obj)) {
176         int cmp_result = PyUnicode_Compare(obj, arg);
177         if (cmp_result == -1 && PyErr_Occurred()) {
178             return -1;
179         }
180         return !cmp_result;
181     }
182 
183     /* Otherwise assume a regex filter and call its match() method */
184     result = PyObject_CallMethodOneArg(obj, &_Py_ID(match), arg);
185     if (result == NULL)
186         return -1;
187 
188     rc = PyObject_IsTrue(result);
189     Py_DECREF(result);
190     return rc;
191 }
192 
193 #define GET_WARNINGS_ATTR(interp, ATTR, try_import) \
194     get_warnings_attr(interp, &_Py_ID(ATTR), try_import)
195 
196 /*
197    Returns a new reference.
198    A NULL return value can mean false or an error.
199 */
200 static PyObject *
get_warnings_attr(PyInterpreterState * interp,PyObject * attr,int try_import)201 get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import)
202 {
203     PyObject *warnings_module, *obj;
204 
205     /* don't try to import after the start of the Python finallization */
206     if (try_import && !_Py_IsInterpreterFinalizing(interp)) {
207         warnings_module = PyImport_Import(&_Py_ID(warnings));
208         if (warnings_module == NULL) {
209             /* Fallback to the C implementation if we cannot get
210                the Python implementation */
211             if (PyErr_ExceptionMatches(PyExc_ImportError)) {
212                 PyErr_Clear();
213             }
214             return NULL;
215         }
216     }
217     else {
218         /* if we're so late into Python finalization that the module dict is
219            gone, then we can't even use PyImport_GetModule without triggering
220            an interpreter abort.
221         */
222         if (!_PyImport_GetModules(interp)) {
223             return NULL;
224         }
225         warnings_module = PyImport_GetModule(&_Py_ID(warnings));
226         if (warnings_module == NULL)
227             return NULL;
228     }
229 
230     (void)PyObject_GetOptionalAttr(warnings_module, attr, &obj);
231     Py_DECREF(warnings_module);
232     return obj;
233 }
234 
235 
236 static PyObject *
get_once_registry(PyInterpreterState * interp)237 get_once_registry(PyInterpreterState *interp)
238 {
239     WarningsState *st = warnings_get_state(interp);
240     assert(st != NULL);
241 
242     _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&st->mutex);
243 
244     PyObject *registry = GET_WARNINGS_ATTR(interp, onceregistry, 0);
245     if (registry == NULL) {
246         if (PyErr_Occurred())
247             return NULL;
248         assert(st->once_registry);
249         return st->once_registry;
250     }
251     if (!PyDict_Check(registry)) {
252         PyErr_Format(PyExc_TypeError,
253                      MODULE_NAME ".onceregistry must be a dict, "
254                      "not '%.200s'",
255                      Py_TYPE(registry)->tp_name);
256         Py_DECREF(registry);
257         return NULL;
258     }
259     Py_SETREF(st->once_registry, registry);
260     return registry;
261 }
262 
263 
264 static PyObject *
get_default_action(PyInterpreterState * interp)265 get_default_action(PyInterpreterState *interp)
266 {
267     WarningsState *st = warnings_get_state(interp);
268     assert(st != NULL);
269 
270     _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&st->mutex);
271 
272     PyObject *default_action = GET_WARNINGS_ATTR(interp, defaultaction, 0);
273     if (default_action == NULL) {
274         if (PyErr_Occurred()) {
275             return NULL;
276         }
277         assert(st->default_action);
278         return st->default_action;
279     }
280     if (!PyUnicode_Check(default_action)) {
281         PyErr_Format(PyExc_TypeError,
282                      MODULE_NAME ".defaultaction must be a string, "
283                      "not '%.200s'",
284                      Py_TYPE(default_action)->tp_name);
285         Py_DECREF(default_action);
286         return NULL;
287     }
288     Py_SETREF(st->default_action, default_action);
289     return default_action;
290 }
291 
292 
293 /* The item is a new reference. */
294 static PyObject*
get_filter(PyInterpreterState * interp,PyObject * category,PyObject * text,Py_ssize_t lineno,PyObject * module,PyObject ** item)295 get_filter(PyInterpreterState *interp, PyObject *category,
296            PyObject *text, Py_ssize_t lineno,
297            PyObject *module, PyObject **item)
298 {
299     WarningsState *st = warnings_get_state(interp);
300     assert(st != NULL);
301 
302     _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&st->mutex);
303 
304     PyObject *warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
305     if (warnings_filters == NULL) {
306         if (PyErr_Occurred())
307             return NULL;
308     }
309     else {
310         Py_SETREF(st->filters, warnings_filters);
311     }
312 
313     PyObject *filters = st->filters;
314     if (filters == NULL || !PyList_Check(filters)) {
315         PyErr_SetString(PyExc_ValueError,
316                         MODULE_NAME ".filters must be a list");
317         return NULL;
318     }
319 
320     /* WarningsState.filters could change while we are iterating over it. */
321     for (Py_ssize_t i = 0; i < PyList_GET_SIZE(filters); i++) {
322         PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
323         Py_ssize_t ln;
324         int is_subclass, good_msg, good_mod;
325 
326         tmp_item = PyList_GET_ITEM(filters, i);
327         if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {
328             PyErr_Format(PyExc_ValueError,
329                          MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
330             return NULL;
331         }
332 
333         /* Python code: action, msg, cat, mod, ln = item */
334         Py_INCREF(tmp_item);
335         action = PyTuple_GET_ITEM(tmp_item, 0);
336         msg = PyTuple_GET_ITEM(tmp_item, 1);
337         cat = PyTuple_GET_ITEM(tmp_item, 2);
338         mod = PyTuple_GET_ITEM(tmp_item, 3);
339         ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
340 
341         if (!PyUnicode_Check(action)) {
342             PyErr_Format(PyExc_TypeError,
343                          "action must be a string, not '%.200s'",
344                          Py_TYPE(action)->tp_name);
345             Py_DECREF(tmp_item);
346             return NULL;
347         }
348 
349         good_msg = check_matched(interp, msg, text);
350         if (good_msg == -1) {
351             Py_DECREF(tmp_item);
352             return NULL;
353         }
354 
355         good_mod = check_matched(interp, mod, module);
356         if (good_mod == -1) {
357             Py_DECREF(tmp_item);
358             return NULL;
359         }
360 
361         is_subclass = PyObject_IsSubclass(category, cat);
362         if (is_subclass == -1) {
363             Py_DECREF(tmp_item);
364             return NULL;
365         }
366 
367         ln = PyLong_AsSsize_t(ln_obj);
368         if (ln == -1 && PyErr_Occurred()) {
369             Py_DECREF(tmp_item);
370             return NULL;
371         }
372 
373         if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
374             *item = tmp_item;
375             return action;
376         }
377 
378         Py_DECREF(tmp_item);
379     }
380 
381     PyObject *action = get_default_action(interp);
382     if (action != NULL) {
383         *item = Py_NewRef(Py_None);
384         return action;
385     }
386 
387     return NULL;
388 }
389 
390 
391 static int
already_warned(PyInterpreterState * interp,PyObject * registry,PyObject * key,int should_set)392 already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,
393                int should_set)
394 {
395     PyObject *already_warned;
396 
397     if (key == NULL)
398         return -1;
399 
400     WarningsState *st = warnings_get_state(interp);
401     assert(st != NULL);
402     _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(&st->mutex);
403 
404     PyObject *version_obj;
405     if (PyDict_GetItemRef(registry, &_Py_ID(version), &version_obj) < 0) {
406         return -1;
407     }
408     bool should_update_version = (
409         version_obj == NULL
410         || !PyLong_CheckExact(version_obj)
411         || PyLong_AsLong(version_obj) != st->filters_version
412     );
413     Py_XDECREF(version_obj);
414     if (should_update_version) {
415         PyDict_Clear(registry);
416         version_obj = PyLong_FromLong(st->filters_version);
417         if (version_obj == NULL)
418             return -1;
419         if (PyDict_SetItem(registry, &_Py_ID(version), version_obj) < 0) {
420             Py_DECREF(version_obj);
421             return -1;
422         }
423         Py_DECREF(version_obj);
424     }
425     else {
426         if (PyDict_GetItemRef(registry, key, &already_warned) < 0) {
427             return -1;
428         }
429         if (already_warned != NULL) {
430             int rc = PyObject_IsTrue(already_warned);
431             Py_DECREF(already_warned);
432             if (rc != 0)
433                 return rc;
434         }
435     }
436 
437     /* This warning wasn't found in the registry, set it. */
438     if (should_set)
439         return PyDict_SetItem(registry, key, Py_True);
440     return 0;
441 }
442 
443 /* New reference. */
444 static PyObject *
normalize_module(PyObject * filename)445 normalize_module(PyObject *filename)
446 {
447     PyObject *module;
448     int kind;
449     const void *data;
450     Py_ssize_t len;
451 
452     len = PyUnicode_GetLength(filename);
453     if (len < 0)
454         return NULL;
455 
456     if (len == 0)
457         return PyUnicode_FromString("<unknown>");
458 
459     kind = PyUnicode_KIND(filename);
460     data = PyUnicode_DATA(filename);
461 
462     /* if filename.endswith(".py"): */
463     if (len >= 3 &&
464         PyUnicode_READ(kind, data, len-3) == '.' &&
465         PyUnicode_READ(kind, data, len-2) == 'p' &&
466         PyUnicode_READ(kind, data, len-1) == 'y')
467     {
468         module = PyUnicode_Substring(filename, 0, len-3);
469     }
470     else {
471         module = Py_NewRef(filename);
472     }
473     return module;
474 }
475 
476 static int
update_registry(PyInterpreterState * interp,PyObject * registry,PyObject * text,PyObject * category,int add_zero)477 update_registry(PyInterpreterState *interp, PyObject *registry, PyObject *text,
478                 PyObject *category, int add_zero)
479 {
480     PyObject *altkey;
481     int rc;
482 
483     if (add_zero)
484         altkey = PyTuple_Pack(3, text, category, _PyLong_GetZero());
485     else
486         altkey = PyTuple_Pack(2, text, category);
487 
488     rc = already_warned(interp, registry, altkey, 1);
489     Py_XDECREF(altkey);
490     return rc;
491 }
492 
493 static void
show_warning(PyThreadState * tstate,PyObject * filename,int lineno,PyObject * text,PyObject * category,PyObject * sourceline)494 show_warning(PyThreadState *tstate, PyObject *filename, int lineno,
495              PyObject *text, PyObject *category, PyObject *sourceline)
496 {
497     PyObject *f_stderr;
498     PyObject *name;
499     char lineno_str[128];
500 
501     PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
502 
503     name = PyObject_GetAttr(category, &_Py_ID(__name__));
504     if (name == NULL) {
505         goto error;
506     }
507 
508     f_stderr = _PySys_GetAttr(tstate, &_Py_ID(stderr));
509     if (f_stderr == NULL) {
510         fprintf(stderr, "lost sys.stderr\n");
511         goto error;
512     }
513 
514     /* Print "filename:lineno: category: text\n" */
515     if (PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW) < 0)
516         goto error;
517     if (PyFile_WriteString(lineno_str, f_stderr) < 0)
518         goto error;
519     if (PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW) < 0)
520         goto error;
521     if (PyFile_WriteString(": ", f_stderr) < 0)
522         goto error;
523     if (PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW) < 0)
524         goto error;
525     if (PyFile_WriteString("\n", f_stderr) < 0)
526         goto error;
527     Py_CLEAR(name);
528 
529     /* Print "  source_line\n" */
530     if (sourceline) {
531         int kind;
532         const void *data;
533         Py_ssize_t i, len;
534         Py_UCS4 ch;
535         PyObject *truncated;
536 
537         kind = PyUnicode_KIND(sourceline);
538         data = PyUnicode_DATA(sourceline);
539         len = PyUnicode_GET_LENGTH(sourceline);
540         for (i=0; i<len; i++) {
541             ch = PyUnicode_READ(kind, data, i);
542             if (ch != ' ' && ch != '\t' && ch != '\014')
543                 break;
544         }
545 
546         truncated = PyUnicode_Substring(sourceline, i, len);
547         if (truncated == NULL)
548             goto error;
549 
550         PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW);
551         Py_DECREF(truncated);
552         PyFile_WriteString("\n", f_stderr);
553     }
554     else {
555         _Py_DisplaySourceLine(f_stderr, filename, lineno, 2, NULL, NULL);
556     }
557 
558 error:
559     Py_XDECREF(name);
560     PyErr_Clear();
561 }
562 
563 static int
call_show_warning(PyThreadState * tstate,PyObject * category,PyObject * text,PyObject * message,PyObject * filename,int lineno,PyObject * lineno_obj,PyObject * sourceline,PyObject * source)564 call_show_warning(PyThreadState *tstate, PyObject *category,
565                   PyObject *text, PyObject *message,
566                   PyObject *filename, int lineno, PyObject *lineno_obj,
567                   PyObject *sourceline, PyObject *source)
568 {
569     PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;
570     PyInterpreterState *interp = tstate->interp;
571 
572     /* The Python implementation is able to log the traceback where the source
573        was allocated, whereas the C implementation doesn't. */
574     show_fn = GET_WARNINGS_ATTR(interp, _showwarnmsg, 1);
575     if (show_fn == NULL) {
576         if (PyErr_Occurred())
577             return -1;
578         show_warning(tstate, filename, lineno, text, category, sourceline);
579         return 0;
580     }
581 
582     if (!PyCallable_Check(show_fn)) {
583         PyErr_SetString(PyExc_TypeError,
584                 "warnings._showwarnmsg() must be set to a callable");
585         goto error;
586     }
587 
588     warnmsg_cls = GET_WARNINGS_ATTR(interp, WarningMessage, 0);
589     if (warnmsg_cls == NULL) {
590         if (!PyErr_Occurred()) {
591             PyErr_SetString(PyExc_RuntimeError,
592                     "unable to get warnings.WarningMessage");
593         }
594         goto error;
595     }
596 
597     msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category,
598             filename, lineno_obj, Py_None, Py_None, source,
599             NULL);
600     Py_DECREF(warnmsg_cls);
601     if (msg == NULL)
602         goto error;
603 
604     res = PyObject_CallOneArg(show_fn, msg);
605     Py_DECREF(show_fn);
606     Py_DECREF(msg);
607 
608     if (res == NULL)
609         return -1;
610 
611     Py_DECREF(res);
612     return 0;
613 
614 error:
615     Py_XDECREF(show_fn);
616     return -1;
617 }
618 
619 static PyObject *
warn_explicit(PyThreadState * tstate,PyObject * category,PyObject * message,PyObject * filename,int lineno,PyObject * module,PyObject * registry,PyObject * sourceline,PyObject * source)620 warn_explicit(PyThreadState *tstate, PyObject *category, PyObject *message,
621               PyObject *filename, int lineno,
622               PyObject *module, PyObject *registry, PyObject *sourceline,
623               PyObject *source)
624 {
625     PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
626     PyObject *item = NULL;
627     PyObject *action;
628     int rc;
629     PyInterpreterState *interp = tstate->interp;
630 
631     /* module can be None if a warning is emitted late during Python shutdown.
632        In this case, the Python warnings module was probably unloaded, filters
633        are no more available to choose as action. It is safer to ignore the
634        warning and do nothing. */
635     if (module == Py_None)
636         Py_RETURN_NONE;
637 
638     if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
639         PyErr_SetString(PyExc_TypeError, "'registry' must be a dict or None");
640         return NULL;
641     }
642 
643     /* Normalize module. */
644     if (module == NULL) {
645         module = normalize_module(filename);
646         if (module == NULL)
647             return NULL;
648     }
649     else
650         Py_INCREF(module);
651 
652     /* Normalize message. */
653     Py_INCREF(message);  /* DECREF'ed in cleanup. */
654     rc = PyObject_IsInstance(message, PyExc_Warning);
655     if (rc == -1) {
656         goto cleanup;
657     }
658     if (rc == 1) {
659         text = PyObject_Str(message);
660         if (text == NULL)
661             goto cleanup;
662         category = (PyObject*)Py_TYPE(message);
663     }
664     else {
665         text = message;
666         message = PyObject_CallOneArg(category, message);
667         if (message == NULL)
668             goto cleanup;
669     }
670 
671     lineno_obj = PyLong_FromLong(lineno);
672     if (lineno_obj == NULL)
673         goto cleanup;
674 
675     if (source == Py_None) {
676         source = NULL;
677     }
678 
679     /* Create key. */
680     key = PyTuple_Pack(3, text, category, lineno_obj);
681     if (key == NULL)
682         goto cleanup;
683 
684     if ((registry != NULL) && (registry != Py_None)) {
685         rc = already_warned(interp, registry, key, 0);
686         if (rc == -1)
687             goto cleanup;
688         else if (rc == 1)
689             goto return_none;
690         /* Else this warning hasn't been generated before. */
691     }
692 
693     action = get_filter(interp, category, text, lineno, module, &item);
694     if (action == NULL)
695         goto cleanup;
696 
697     if (_PyUnicode_EqualToASCIIString(action, "error")) {
698         PyErr_SetObject(category, message);
699         goto cleanup;
700     }
701 
702     if (_PyUnicode_EqualToASCIIString(action, "ignore")) {
703         goto return_none;
704     }
705 
706     /* Store in the registry that we've been here, *except* when the action
707        is "always". */
708     rc = 0;
709     if (!_PyUnicode_EqualToASCIIString(action, "always")) {
710         if (registry != NULL && registry != Py_None &&
711             PyDict_SetItem(registry, key, Py_True) < 0)
712         {
713             goto cleanup;
714         }
715 
716         if (_PyUnicode_EqualToASCIIString(action, "once")) {
717             if (registry == NULL || registry == Py_None) {
718                 registry = get_once_registry(interp);
719                 if (registry == NULL)
720                     goto cleanup;
721             }
722             /* WarningsState.once_registry[(text, category)] = 1 */
723             rc = update_registry(interp, registry, text, category, 0);
724         }
725         else if (_PyUnicode_EqualToASCIIString(action, "module")) {
726             /* registry[(text, category, 0)] = 1 */
727             if (registry != NULL && registry != Py_None)
728                 rc = update_registry(interp, registry, text, category, 0);
729         }
730         else if (!_PyUnicode_EqualToASCIIString(action, "default")) {
731             PyErr_Format(PyExc_RuntimeError,
732                         "Unrecognized action (%R) in warnings.filters:\n %R",
733                         action, item);
734             goto cleanup;
735         }
736     }
737 
738     if (rc == 1)  /* Already warned for this module. */
739         goto return_none;
740     if (rc == 0) {
741         if (call_show_warning(tstate, category, text, message, filename,
742                               lineno, lineno_obj, sourceline, source) < 0)
743             goto cleanup;
744     }
745     else /* if (rc == -1) */
746         goto cleanup;
747 
748  return_none:
749     result = Py_NewRef(Py_None);
750 
751  cleanup:
752     Py_XDECREF(item);
753     Py_XDECREF(key);
754     Py_XDECREF(text);
755     Py_XDECREF(lineno_obj);
756     Py_DECREF(module);
757     Py_XDECREF(message);
758     return result;  /* Py_None or NULL. */
759 }
760 
761 static PyObject *
get_frame_filename(PyFrameObject * frame)762 get_frame_filename(PyFrameObject *frame)
763 {
764     PyCodeObject *code = PyFrame_GetCode(frame);
765     PyObject *filename = code->co_filename;
766     Py_DECREF(code);
767     return filename;
768 }
769 
770 static bool
is_internal_filename(PyObject * filename)771 is_internal_filename(PyObject *filename)
772 {
773     if (!PyUnicode_Check(filename)) {
774         return false;
775     }
776 
777     int contains = PyUnicode_Contains(filename, &_Py_ID(importlib));
778     if (contains < 0) {
779         return false;
780     }
781     else if (contains > 0) {
782         contains = PyUnicode_Contains(filename, &_Py_ID(_bootstrap));
783         if (contains < 0) {
784             return false;
785         }
786         else if (contains > 0) {
787             return true;
788         }
789     }
790 
791     return false;
792 }
793 
794 static bool
is_filename_to_skip(PyObject * filename,PyTupleObject * skip_file_prefixes)795 is_filename_to_skip(PyObject *filename, PyTupleObject *skip_file_prefixes)
796 {
797     if (skip_file_prefixes) {
798         if (!PyUnicode_Check(filename)) {
799             return false;
800         }
801 
802         Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
803         for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
804         {
805             PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
806             Py_ssize_t found = PyUnicode_Tailmatch(filename, prefix, 0, -1, -1);
807             if (found == 1) {
808                 return true;
809             }
810             if (found < 0) {
811                 return false;
812             }
813         }
814     }
815     return false;
816 }
817 
818 static bool
is_internal_frame(PyFrameObject * frame)819 is_internal_frame(PyFrameObject *frame)
820 {
821     if (frame == NULL) {
822         return false;
823     }
824 
825     PyObject *filename = get_frame_filename(frame);
826     if (filename == NULL) {
827         return false;
828     }
829 
830     return is_internal_filename(filename);
831 }
832 
833 static PyFrameObject *
next_external_frame(PyFrameObject * frame,PyTupleObject * skip_file_prefixes)834 next_external_frame(PyFrameObject *frame, PyTupleObject *skip_file_prefixes)
835 {
836     PyObject *frame_filename;
837     do {
838         PyFrameObject *back = PyFrame_GetBack(frame);
839         Py_SETREF(frame, back);
840     } while (frame != NULL && (frame_filename = get_frame_filename(frame)) &&
841              (is_internal_filename(frame_filename) ||
842               is_filename_to_skip(frame_filename, skip_file_prefixes)));
843 
844     return frame;
845 }
846 
847 /* filename, module, and registry are new refs, globals is borrowed */
848 /* skip_file_prefixes is either NULL or a tuple of strs. */
849 /* Returns 0 on error (no new refs), 1 on success */
850 static int
setup_context(Py_ssize_t stack_level,PyTupleObject * skip_file_prefixes,PyObject ** filename,int * lineno,PyObject ** module,PyObject ** registry)851 setup_context(Py_ssize_t stack_level,
852               PyTupleObject *skip_file_prefixes,
853               PyObject **filename, int *lineno,
854               PyObject **module, PyObject **registry)
855 {
856     PyObject *globals;
857 
858     /* Setup globals, filename and lineno. */
859     PyThreadState *tstate = get_current_tstate();
860     if (tstate == NULL) {
861         return 0;
862     }
863     if (skip_file_prefixes) {
864         /* Type check our data structure up front. Later code that uses it
865          * isn't structured to report errors. */
866         Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
867         for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
868         {
869             PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
870             if (!PyUnicode_Check(prefix)) {
871                 PyErr_Format(PyExc_TypeError,
872                              "Found non-str '%s' in skip_file_prefixes.",
873                              Py_TYPE(prefix)->tp_name);
874                 return 0;
875             }
876         }
877     }
878     PyInterpreterState *interp = tstate->interp;
879     PyFrameObject *f = PyThreadState_GetFrame(tstate);
880     // Stack level comparisons to Python code is off by one as there is no
881     // warnings-related stack level to avoid.
882     if (stack_level <= 0 || is_internal_frame(f)) {
883         while (--stack_level > 0 && f != NULL) {
884             PyFrameObject *back = PyFrame_GetBack(f);
885             Py_SETREF(f, back);
886         }
887     }
888     else {
889         while (--stack_level > 0 && f != NULL) {
890             f = next_external_frame(f, skip_file_prefixes);
891         }
892     }
893 
894     if (f == NULL) {
895         globals = interp->sysdict;
896         *filename = PyUnicode_FromString("<sys>");
897         *lineno = 0;
898     }
899     else {
900         globals = f->f_frame->f_globals;
901         *filename = Py_NewRef(_PyFrame_GetCode(f->f_frame)->co_filename);
902         *lineno = PyFrame_GetLineNumber(f);
903         Py_DECREF(f);
904     }
905 
906     *module = NULL;
907 
908     /* Setup registry. */
909     assert(globals != NULL);
910     assert(PyDict_Check(globals));
911     int rc = PyDict_GetItemRef(globals, &_Py_ID(__warningregistry__),
912                                registry);
913     if (rc < 0) {
914         goto handle_error;
915     }
916     if (*registry == NULL) {
917         *registry = PyDict_New();
918         if (*registry == NULL)
919             goto handle_error;
920 
921          rc = PyDict_SetItem(globals, &_Py_ID(__warningregistry__), *registry);
922          if (rc < 0)
923             goto handle_error;
924     }
925 
926     /* Setup module. */
927     rc = PyDict_GetItemRef(globals, &_Py_ID(__name__), module);
928     if (rc < 0) {
929         goto handle_error;
930     }
931     if (rc > 0) {
932         if (Py_IsNone(*module) || PyUnicode_Check(*module)) {
933             return 1;
934         }
935         Py_DECREF(*module);
936     }
937     *module = PyUnicode_FromString("<string>");
938     if (*module == NULL) {
939         goto handle_error;
940     }
941 
942     return 1;
943 
944  handle_error:
945     Py_XDECREF(*registry);
946     Py_XDECREF(*module);
947     Py_DECREF(*filename);
948     return 0;
949 }
950 
951 static PyObject *
get_category(PyObject * message,PyObject * category)952 get_category(PyObject *message, PyObject *category)
953 {
954     int rc;
955 
956     /* Get category. */
957     rc = PyObject_IsInstance(message, PyExc_Warning);
958     if (rc == -1)
959         return NULL;
960 
961     if (rc == 1)
962         category = (PyObject*)Py_TYPE(message);
963     else if (category == NULL || category == Py_None)
964         category = PyExc_UserWarning;
965 
966     /* Validate category. */
967     rc = PyObject_IsSubclass(category, PyExc_Warning);
968     /* category is not a subclass of PyExc_Warning or
969        PyObject_IsSubclass raised an error */
970     if (rc == -1 || rc == 0) {
971         PyErr_Format(PyExc_TypeError,
972                      "category must be a Warning subclass, not '%s'",
973                      Py_TYPE(category)->tp_name);
974         return NULL;
975     }
976 
977     return category;
978 }
979 
980 static PyObject *
do_warn(PyObject * message,PyObject * category,Py_ssize_t stack_level,PyObject * source,PyTupleObject * skip_file_prefixes)981 do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
982         PyObject *source, PyTupleObject *skip_file_prefixes)
983 {
984     PyObject *filename, *module, *registry, *res;
985     int lineno;
986 
987     PyThreadState *tstate = get_current_tstate();
988     if (tstate == NULL) {
989         return NULL;
990     }
991 
992     if (!setup_context(stack_level, skip_file_prefixes,
993                        &filename, &lineno, &module, &registry))
994         return NULL;
995 
996 #ifdef Py_GIL_DISABLED
997     WarningsState *st = warnings_get_state(tstate->interp);
998     assert(st != NULL);
999 #endif
1000 
1001     Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
1002     res = warn_explicit(tstate, category, message, filename, lineno, module, registry,
1003                         NULL, source);
1004     Py_END_CRITICAL_SECTION();
1005     Py_DECREF(filename);
1006     Py_DECREF(registry);
1007     Py_DECREF(module);
1008     return res;
1009 }
1010 
1011 /*[clinic input]
1012 warn as warnings_warn
1013 
1014     message: object
1015       Text of the warning message.
1016     category: object = None
1017       The Warning category subclass. Defaults to UserWarning.
1018     stacklevel: Py_ssize_t = 1
1019       How far up the call stack to make this warning appear. A value of 2 for
1020       example attributes the warning to the caller of the code calling warn().
1021     source: object = None
1022       If supplied, the destroyed object which emitted a ResourceWarning
1023     *
1024     skip_file_prefixes: object(type='PyTupleObject *', subclass_of='&PyTuple_Type') = NULL
1025       An optional tuple of module filename prefixes indicating frames to skip
1026       during stacklevel computations for stack frame attribution.
1027 
1028 Issue a warning, or maybe ignore it or raise an exception.
1029 [clinic start generated code]*/
1030 
1031 static PyObject *
warnings_warn_impl(PyObject * module,PyObject * message,PyObject * category,Py_ssize_t stacklevel,PyObject * source,PyTupleObject * skip_file_prefixes)1032 warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
1033                    Py_ssize_t stacklevel, PyObject *source,
1034                    PyTupleObject *skip_file_prefixes)
1035 /*[clinic end generated code: output=a68e0f6906c65f80 input=eb37c6a18bec4ea1]*/
1036 {
1037     category = get_category(message, category);
1038     if (category == NULL)
1039         return NULL;
1040     if (skip_file_prefixes) {
1041         if (PyTuple_GET_SIZE(skip_file_prefixes) > 0) {
1042             if (stacklevel < 2) {
1043                 stacklevel = 2;
1044             }
1045         } else {
1046             Py_DECREF((PyObject *)skip_file_prefixes);
1047             skip_file_prefixes = NULL;
1048         }
1049     }
1050     return do_warn(message, category, stacklevel, source, skip_file_prefixes);
1051 }
1052 
1053 static PyObject *
get_source_line(PyInterpreterState * interp,PyObject * module_globals,int lineno)1054 get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno)
1055 {
1056     PyObject *loader;
1057     PyObject *module_name;
1058     PyObject *get_source;
1059     PyObject *source;
1060     PyObject *source_list;
1061     PyObject *source_line;
1062 
1063     /* stolen from import.c */
1064     loader = _PyImport_BlessMyLoader(interp, module_globals);
1065     if (loader == NULL) {
1066         return NULL;
1067     }
1068 
1069     int rc = PyDict_GetItemRef(module_globals, &_Py_ID(__name__),
1070                                &module_name);
1071     if (rc < 0 || rc == 0) {
1072         Py_DECREF(loader);
1073         return NULL;
1074     }
1075 
1076     /* Make sure the loader implements the optional get_source() method. */
1077     (void)PyObject_GetOptionalAttr(loader, &_Py_ID(get_source), &get_source);
1078     Py_DECREF(loader);
1079     if (!get_source) {
1080         Py_DECREF(module_name);
1081         return NULL;
1082     }
1083     /* Call get_source() to get the source code. */
1084     source = PyObject_CallOneArg(get_source, module_name);
1085     Py_DECREF(get_source);
1086     Py_DECREF(module_name);
1087     if (!source) {
1088         return NULL;
1089     }
1090     if (source == Py_None) {
1091         Py_DECREF(source);
1092         return NULL;
1093     }
1094 
1095     /* Split the source into lines. */
1096     source_list = PyUnicode_Splitlines(source, 0);
1097     Py_DECREF(source);
1098     if (!source_list) {
1099         return NULL;
1100     }
1101 
1102     /* Get the source line. */
1103     source_line = PyList_GetItem(source_list, lineno-1);
1104     Py_XINCREF(source_line);
1105     Py_DECREF(source_list);
1106     return source_line;
1107 }
1108 
1109 /*[clinic input]
1110 warn_explicit as warnings_warn_explicit
1111 
1112     message: object
1113     category: object
1114     filename: unicode
1115     lineno: int
1116     module as mod: object = NULL
1117     registry: object = None
1118     module_globals: object = None
1119     source as sourceobj: object = None
1120 
1121 Issue a warning, or maybe ignore it or raise an exception.
1122 [clinic start generated code]*/
1123 
1124 static PyObject *
warnings_warn_explicit_impl(PyObject * module,PyObject * message,PyObject * category,PyObject * filename,int lineno,PyObject * mod,PyObject * registry,PyObject * module_globals,PyObject * sourceobj)1125 warnings_warn_explicit_impl(PyObject *module, PyObject *message,
1126                             PyObject *category, PyObject *filename,
1127                             int lineno, PyObject *mod, PyObject *registry,
1128                             PyObject *module_globals, PyObject *sourceobj)
1129 /*[clinic end generated code: output=c49c62b15a49a186 input=df6eeb8b45e712f1]*/
1130 {
1131     PyObject *source_line = NULL;
1132     PyObject *returned;
1133 
1134     PyThreadState *tstate = get_current_tstate();
1135     if (tstate == NULL) {
1136         return NULL;
1137     }
1138 
1139     if (module_globals && module_globals != Py_None) {
1140         if (!PyDict_Check(module_globals)) {
1141             PyErr_Format(PyExc_TypeError,
1142                          "module_globals must be a dict, not '%.200s'",
1143                          Py_TYPE(module_globals)->tp_name);
1144             return NULL;
1145         }
1146 
1147         source_line = get_source_line(tstate->interp, module_globals, lineno);
1148         if (source_line == NULL && PyErr_Occurred()) {
1149             return NULL;
1150         }
1151     }
1152 
1153 #ifdef Py_GIL_DISABLED
1154     WarningsState *st = warnings_get_state(tstate->interp);
1155     assert(st != NULL);
1156 #endif
1157 
1158     Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
1159     returned = warn_explicit(tstate, category, message, filename, lineno,
1160                              mod, registry, source_line, sourceobj);
1161     Py_END_CRITICAL_SECTION();
1162     Py_XDECREF(source_line);
1163     return returned;
1164 }
1165 
1166 /*[clinic input]
1167 _filters_mutated as warnings_filters_mutated
1168 
1169 [clinic start generated code]*/
1170 
1171 static PyObject *
warnings_filters_mutated_impl(PyObject * module)1172 warnings_filters_mutated_impl(PyObject *module)
1173 /*[clinic end generated code: output=8ce517abd12b88f4 input=35ecbf08ee2491b2]*/
1174 {
1175     PyInterpreterState *interp = get_current_interp();
1176     if (interp == NULL) {
1177         return NULL;
1178     }
1179 
1180     WarningsState *st = warnings_get_state(interp);
1181     assert(st != NULL);
1182 
1183     Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
1184     st->filters_version++;
1185     Py_END_CRITICAL_SECTION();
1186 
1187     Py_RETURN_NONE;
1188 }
1189 
1190 
1191 /* Function to issue a warning message; may raise an exception. */
1192 
1193 static int
warn_unicode(PyObject * category,PyObject * message,Py_ssize_t stack_level,PyObject * source)1194 warn_unicode(PyObject *category, PyObject *message,
1195              Py_ssize_t stack_level, PyObject *source)
1196 {
1197     PyObject *res;
1198 
1199     if (category == NULL)
1200         category = PyExc_RuntimeWarning;
1201 
1202     res = do_warn(message, category, stack_level, source, NULL);
1203     if (res == NULL)
1204         return -1;
1205     Py_DECREF(res);
1206 
1207     return 0;
1208 }
1209 
1210 static int
_PyErr_WarnFormatV(PyObject * source,PyObject * category,Py_ssize_t stack_level,const char * format,va_list vargs)1211 _PyErr_WarnFormatV(PyObject *source,
1212                    PyObject *category, Py_ssize_t stack_level,
1213                    const char *format, va_list vargs)
1214 {
1215     PyObject *message;
1216     int res;
1217 
1218     message = PyUnicode_FromFormatV(format, vargs);
1219     if (message == NULL)
1220         return -1;
1221 
1222     res = warn_unicode(category, message, stack_level, source);
1223     Py_DECREF(message);
1224     return res;
1225 }
1226 
1227 int
PyErr_WarnFormat(PyObject * category,Py_ssize_t stack_level,const char * format,...)1228 PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
1229                  const char *format, ...)
1230 {
1231     int res;
1232     va_list vargs;
1233 
1234     va_start(vargs, format);
1235     res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
1236     va_end(vargs);
1237     return res;
1238 }
1239 
1240 static int
_PyErr_WarnFormat(PyObject * source,PyObject * category,Py_ssize_t stack_level,const char * format,...)1241 _PyErr_WarnFormat(PyObject *source, PyObject *category, Py_ssize_t stack_level,
1242                   const char *format, ...)
1243 {
1244     int res;
1245     va_list vargs;
1246 
1247     va_start(vargs, format);
1248     res = _PyErr_WarnFormatV(source, category, stack_level, format, vargs);
1249     va_end(vargs);
1250     return res;
1251 }
1252 
1253 int
PyErr_ResourceWarning(PyObject * source,Py_ssize_t stack_level,const char * format,...)1254 PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
1255                       const char *format, ...)
1256 {
1257     int res;
1258     va_list vargs;
1259 
1260     va_start(vargs, format);
1261     res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
1262                              stack_level, format, vargs);
1263     va_end(vargs);
1264     return res;
1265 }
1266 
1267 
1268 int
PyErr_WarnEx(PyObject * category,const char * text,Py_ssize_t stack_level)1269 PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
1270 {
1271     int ret;
1272     PyObject *message = PyUnicode_FromString(text);
1273     if (message == NULL)
1274         return -1;
1275     ret = warn_unicode(category, message, stack_level, NULL);
1276     Py_DECREF(message);
1277     return ret;
1278 }
1279 
1280 /* PyErr_Warn is only for backwards compatibility and will be removed.
1281    Use PyErr_WarnEx instead. */
1282 
1283 #undef PyErr_Warn
1284 
1285 int
PyErr_Warn(PyObject * category,const char * text)1286 PyErr_Warn(PyObject *category, const char *text)
1287 {
1288     return PyErr_WarnEx(category, text, 1);
1289 }
1290 
1291 /* Warning with explicit origin */
1292 int
PyErr_WarnExplicitObject(PyObject * category,PyObject * message,PyObject * filename,int lineno,PyObject * module,PyObject * registry)1293 PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
1294                          PyObject *filename, int lineno,
1295                          PyObject *module, PyObject *registry)
1296 {
1297     PyObject *res;
1298     if (category == NULL)
1299         category = PyExc_RuntimeWarning;
1300     PyThreadState *tstate = get_current_tstate();
1301     if (tstate == NULL) {
1302         return -1;
1303     }
1304 
1305 #ifdef Py_GIL_DISABLED
1306     WarningsState *st = warnings_get_state(tstate->interp);
1307     assert(st != NULL);
1308 #endif
1309 
1310     Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
1311     res = warn_explicit(tstate, category, message, filename, lineno,
1312                         module, registry, NULL, NULL);
1313     Py_END_CRITICAL_SECTION();
1314     if (res == NULL)
1315         return -1;
1316     Py_DECREF(res);
1317     return 0;
1318 }
1319 
1320 int
PyErr_WarnExplicit(PyObject * category,const char * text,const char * filename_str,int lineno,const char * module_str,PyObject * registry)1321 PyErr_WarnExplicit(PyObject *category, const char *text,
1322                    const char *filename_str, int lineno,
1323                    const char *module_str, PyObject *registry)
1324 {
1325     PyObject *message = PyUnicode_FromString(text);
1326     if (message == NULL) {
1327         return -1;
1328     }
1329     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1330     if (filename == NULL) {
1331         Py_DECREF(message);
1332         return -1;
1333     }
1334     PyObject *module = NULL;
1335     if (module_str != NULL) {
1336         module = PyUnicode_FromString(module_str);
1337         if (module == NULL) {
1338             Py_DECREF(filename);
1339             Py_DECREF(message);
1340             return -1;
1341         }
1342     }
1343 
1344     int ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
1345                                        module, registry);
1346     Py_XDECREF(module);
1347     Py_DECREF(filename);
1348     Py_DECREF(message);
1349     return ret;
1350 }
1351 
1352 int
PyErr_WarnExplicitFormat(PyObject * category,const char * filename_str,int lineno,const char * module_str,PyObject * registry,const char * format,...)1353 PyErr_WarnExplicitFormat(PyObject *category,
1354                          const char *filename_str, int lineno,
1355                          const char *module_str, PyObject *registry,
1356                          const char *format, ...)
1357 {
1358     PyObject *message;
1359     PyObject *module = NULL;
1360     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1361     int ret = -1;
1362     va_list vargs;
1363 
1364     if (filename == NULL)
1365         goto exit;
1366     if (module_str != NULL) {
1367         module = PyUnicode_FromString(module_str);
1368         if (module == NULL)
1369             goto exit;
1370     }
1371 
1372     va_start(vargs, format);
1373     message = PyUnicode_FromFormatV(format, vargs);
1374     if (message != NULL) {
1375         PyObject *res;
1376         PyThreadState *tstate = get_current_tstate();
1377         if (tstate != NULL) {
1378 #ifdef Py_GIL_DISABLED
1379             WarningsState *st = warnings_get_state(tstate->interp);
1380             assert(st != NULL);
1381 #endif
1382 
1383             Py_BEGIN_CRITICAL_SECTION_MUT(&st->mutex);
1384             res = warn_explicit(tstate, category, message, filename, lineno,
1385                                 module, registry, NULL, NULL);
1386             Py_END_CRITICAL_SECTION();
1387             Py_DECREF(message);
1388             if (res != NULL) {
1389                 Py_DECREF(res);
1390                 ret = 0;
1391             }
1392         }
1393     }
1394     va_end(vargs);
1395 exit:
1396     Py_XDECREF(module);
1397     Py_XDECREF(filename);
1398     return ret;
1399 }
1400 
1401 void
_PyErr_WarnUnawaitedAgenMethod(PyAsyncGenObject * agen,PyObject * method)1402 _PyErr_WarnUnawaitedAgenMethod(PyAsyncGenObject *agen, PyObject *method)
1403 {
1404     PyObject *exc = PyErr_GetRaisedException();
1405     if (_PyErr_WarnFormat((PyObject *)agen, PyExc_RuntimeWarning, 1,
1406                           "coroutine method %R of %R was never awaited",
1407                           method, agen->ag_qualname) < 0)
1408     {
1409         PyErr_WriteUnraisable((PyObject *)agen);
1410     }
1411     PyErr_SetRaisedException(exc);
1412 }
1413 
1414 
1415 void
_PyErr_WarnUnawaitedCoroutine(PyObject * coro)1416 _PyErr_WarnUnawaitedCoroutine(PyObject *coro)
1417 {
1418     /* First, we attempt to funnel the warning through
1419        warnings._warn_unawaited_coroutine.
1420 
1421        This could raise an exception, due to:
1422        - a bug
1423        - some kind of shutdown-related brokenness
1424        - succeeding, but with an "error" warning filter installed, so the
1425          warning is converted into a RuntimeWarning exception
1426 
1427        In the first two cases, we want to print the error (so we know what it
1428        is!), and then print a warning directly as a fallback. In the last
1429        case, we want to print the error (since it's the warning!), but *not*
1430        do a fallback. And after we print the error we can't check for what
1431        type of error it was (because PyErr_WriteUnraisable clears it), so we
1432        need a flag to keep track.
1433 
1434        Since this is called from __del__ context, it's careful to never raise
1435        an exception.
1436     */
1437     int warned = 0;
1438     PyInterpreterState *interp = _PyInterpreterState_GET();
1439     assert(interp != NULL);
1440     PyObject *fn = GET_WARNINGS_ATTR(interp, _warn_unawaited_coroutine, 1);
1441     if (fn) {
1442         PyObject *res = PyObject_CallOneArg(fn, coro);
1443         Py_DECREF(fn);
1444         if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
1445             warned = 1;
1446         }
1447         Py_XDECREF(res);
1448     }
1449 
1450     if (PyErr_Occurred()) {
1451         PyErr_WriteUnraisable(coro);
1452     }
1453     if (!warned) {
1454         if (_PyErr_WarnFormat(coro, PyExc_RuntimeWarning, 1,
1455                               "coroutine '%S' was never awaited",
1456                               ((PyCoroObject *)coro)->cr_qualname) < 0)
1457         {
1458             PyErr_WriteUnraisable(coro);
1459         }
1460     }
1461 }
1462 
1463 static PyMethodDef warnings_functions[] = {
1464     WARNINGS_WARN_METHODDEF
1465     WARNINGS_WARN_EXPLICIT_METHODDEF
1466     WARNINGS_FILTERS_MUTATED_METHODDEF
1467     /* XXX(brett.cannon): add showwarning? */
1468     /* XXX(brett.cannon): Reasonable to add formatwarning? */
1469     {NULL, NULL}                /* sentinel */
1470 };
1471 
1472 
1473 static int
warnings_module_exec(PyObject * module)1474 warnings_module_exec(PyObject *module)
1475 {
1476     PyInterpreterState *interp = get_current_interp();
1477     if (interp == NULL) {
1478         return -1;
1479     }
1480     WarningsState *st = warnings_get_state(interp);
1481     if (st == NULL) {
1482         return -1;
1483     }
1484     if (PyModule_AddObjectRef(module, "filters", st->filters) < 0) {
1485         return -1;
1486     }
1487     if (PyModule_AddObjectRef(module, "_onceregistry", st->once_registry) < 0) {
1488         return -1;
1489     }
1490     if (PyModule_AddObjectRef(module, "_defaultaction", st->default_action) < 0) {
1491         return -1;
1492     }
1493     return 0;
1494 }
1495 
1496 
1497 static PyModuleDef_Slot warnings_slots[] = {
1498     {Py_mod_exec, warnings_module_exec},
1499     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
1500     {Py_mod_gil, Py_MOD_GIL_NOT_USED},
1501     {0, NULL}
1502 };
1503 
1504 static struct PyModuleDef warnings_module = {
1505     PyModuleDef_HEAD_INIT,
1506     .m_name = MODULE_NAME,
1507     .m_doc = warnings__doc__,
1508     .m_size = 0,
1509     .m_methods = warnings_functions,
1510     .m_slots = warnings_slots,
1511 };
1512 
1513 
1514 PyMODINIT_FUNC
_PyWarnings_Init(void)1515 _PyWarnings_Init(void)
1516 {
1517     return PyModuleDef_Init(&warnings_module);
1518 }
1519 
1520 // We need this to ensure that warnings still work until late in finalization.
1521 void
_PyWarnings_Fini(PyInterpreterState * interp)1522 _PyWarnings_Fini(PyInterpreterState *interp)
1523 {
1524     warnings_clear_state(&interp->warnings);
1525 }
1526