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, ®istry))
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