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