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