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