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 goto handle_error;
860 }
861 *registry = PyDict_New();
862 if (*registry == NULL)
863 goto handle_error;
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 Py_XDECREF(*registry);
890 Py_XDECREF(*module);
891 Py_DECREF(*filename);
892 return 0;
893 }
894
895 static PyObject *
get_category(PyObject * message,PyObject * category)896 get_category(PyObject *message, PyObject *category)
897 {
898 int rc;
899
900 /* Get category. */
901 rc = PyObject_IsInstance(message, PyExc_Warning);
902 if (rc == -1)
903 return NULL;
904
905 if (rc == 1)
906 category = (PyObject*)message->ob_type;
907 else if (category == NULL || category == Py_None)
908 category = PyExc_UserWarning;
909
910 /* Validate category. */
911 rc = PyObject_IsSubclass(category, PyExc_Warning);
912 /* category is not a subclass of PyExc_Warning or
913 PyObject_IsSubclass raised an error */
914 if (rc == -1 || rc == 0) {
915 PyErr_Format(PyExc_TypeError,
916 "category must be a Warning subclass, not '%s'",
917 Py_TYPE(category)->tp_name);
918 return NULL;
919 }
920
921 return category;
922 }
923
924 static PyObject *
do_warn(PyObject * message,PyObject * category,Py_ssize_t stack_level,PyObject * source)925 do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
926 PyObject *source)
927 {
928 PyObject *filename, *module, *registry, *res;
929 int lineno;
930
931 if (!setup_context(stack_level, &filename, &lineno, &module, ®istry))
932 return NULL;
933
934 res = warn_explicit(category, message, filename, lineno, module, registry,
935 NULL, source);
936 Py_DECREF(filename);
937 Py_DECREF(registry);
938 Py_DECREF(module);
939 return res;
940 }
941
942 /*[clinic input]
943 warn as warnings_warn
944
945 message: object
946 category: object = None
947 stacklevel: Py_ssize_t = 1
948 source: object = None
949
950 Issue a warning, or maybe ignore it or raise an exception.
951 [clinic start generated code]*/
952
953 static PyObject *
warnings_warn_impl(PyObject * module,PyObject * message,PyObject * category,Py_ssize_t stacklevel,PyObject * source)954 warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
955 Py_ssize_t stacklevel, PyObject *source)
956 /*[clinic end generated code: output=31ed5ab7d8d760b2 input=bfdf5cf99f6c4edd]*/
957 {
958 category = get_category(message, category);
959 if (category == NULL)
960 return NULL;
961 return do_warn(message, category, stacklevel, source);
962 }
963
964 static PyObject *
get_source_line(PyObject * module_globals,int lineno)965 get_source_line(PyObject *module_globals, int lineno)
966 {
967 _Py_IDENTIFIER(get_source);
968 _Py_IDENTIFIER(__loader__);
969 _Py_IDENTIFIER(__name__);
970 PyObject *loader;
971 PyObject *module_name;
972 PyObject *get_source;
973 PyObject *source;
974 PyObject *source_list;
975 PyObject *source_line;
976
977 /* Check/get the requisite pieces needed for the loader. */
978 loader = _PyDict_GetItemIdWithError(module_globals, &PyId___loader__);
979 if (loader == NULL) {
980 return NULL;
981 }
982 Py_INCREF(loader);
983 module_name = _PyDict_GetItemIdWithError(module_globals, &PyId___name__);
984 if (!module_name) {
985 Py_DECREF(loader);
986 return NULL;
987 }
988 Py_INCREF(module_name);
989
990 /* Make sure the loader implements the optional get_source() method. */
991 (void)_PyObject_LookupAttrId(loader, &PyId_get_source, &get_source);
992 Py_DECREF(loader);
993 if (!get_source) {
994 Py_DECREF(module_name);
995 return NULL;
996 }
997 /* Call get_source() to get the source code. */
998 source = PyObject_CallFunctionObjArgs(get_source, module_name, NULL);
999 Py_DECREF(get_source);
1000 Py_DECREF(module_name);
1001 if (!source) {
1002 return NULL;
1003 }
1004 if (source == Py_None) {
1005 Py_DECREF(source);
1006 return NULL;
1007 }
1008
1009 /* Split the source into lines. */
1010 source_list = PyUnicode_Splitlines(source, 0);
1011 Py_DECREF(source);
1012 if (!source_list) {
1013 return NULL;
1014 }
1015
1016 /* Get the source line. */
1017 source_line = PyList_GetItem(source_list, lineno-1);
1018 Py_XINCREF(source_line);
1019 Py_DECREF(source_list);
1020 return source_line;
1021 }
1022
1023 static PyObject *
warnings_warn_explicit(PyObject * self,PyObject * args,PyObject * kwds)1024 warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
1025 {
1026 static char *kwd_list[] = {"message", "category", "filename", "lineno",
1027 "module", "registry", "module_globals",
1028 "source", 0};
1029 PyObject *message;
1030 PyObject *category;
1031 PyObject *filename;
1032 int lineno;
1033 PyObject *module = NULL;
1034 PyObject *registry = NULL;
1035 PyObject *module_globals = NULL;
1036 PyObject *sourceobj = NULL;
1037 PyObject *source_line = NULL;
1038 PyObject *returned;
1039
1040 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit",
1041 kwd_list, &message, &category, &filename, &lineno, &module,
1042 ®istry, &module_globals, &sourceobj))
1043 return NULL;
1044
1045 if (module_globals && module_globals != Py_None) {
1046 if (!PyDict_Check(module_globals)) {
1047 PyErr_Format(PyExc_TypeError,
1048 "module_globals must be a dict, not '%.200s'",
1049 Py_TYPE(module_globals)->tp_name);
1050 return NULL;
1051 }
1052
1053 source_line = get_source_line(module_globals, lineno);
1054 if (source_line == NULL && PyErr_Occurred()) {
1055 return NULL;
1056 }
1057 }
1058 returned = warn_explicit(category, message, filename, lineno, module,
1059 registry, source_line, sourceobj);
1060 Py_XDECREF(source_line);
1061 return returned;
1062 }
1063
1064 static PyObject *
warnings_filters_mutated(PyObject * self,PyObject * args)1065 warnings_filters_mutated(PyObject *self, PyObject *args)
1066 {
1067 WarningsState *st = _Warnings_GetState();
1068 if (st == NULL) {
1069 return NULL;
1070 }
1071 st->filters_version++;
1072 Py_RETURN_NONE;
1073 }
1074
1075
1076 /* Function to issue a warning message; may raise an exception. */
1077
1078 static int
warn_unicode(PyObject * category,PyObject * message,Py_ssize_t stack_level,PyObject * source)1079 warn_unicode(PyObject *category, PyObject *message,
1080 Py_ssize_t stack_level, PyObject *source)
1081 {
1082 PyObject *res;
1083
1084 if (category == NULL)
1085 category = PyExc_RuntimeWarning;
1086
1087 res = do_warn(message, category, stack_level, source);
1088 if (res == NULL)
1089 return -1;
1090 Py_DECREF(res);
1091
1092 return 0;
1093 }
1094
1095 static int
_PyErr_WarnFormatV(PyObject * source,PyObject * category,Py_ssize_t stack_level,const char * format,va_list vargs)1096 _PyErr_WarnFormatV(PyObject *source,
1097 PyObject *category, Py_ssize_t stack_level,
1098 const char *format, va_list vargs)
1099 {
1100 PyObject *message;
1101 int res;
1102
1103 message = PyUnicode_FromFormatV(format, vargs);
1104 if (message == NULL)
1105 return -1;
1106
1107 res = warn_unicode(category, message, stack_level, source);
1108 Py_DECREF(message);
1109 return res;
1110 }
1111
1112 int
PyErr_WarnFormat(PyObject * category,Py_ssize_t stack_level,const char * format,...)1113 PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
1114 const char *format, ...)
1115 {
1116 int res;
1117 va_list vargs;
1118
1119 #ifdef HAVE_STDARG_PROTOTYPES
1120 va_start(vargs, format);
1121 #else
1122 va_start(vargs);
1123 #endif
1124 res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
1125 va_end(vargs);
1126 return res;
1127 }
1128
1129 int
PyErr_ResourceWarning(PyObject * source,Py_ssize_t stack_level,const char * format,...)1130 PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
1131 const char *format, ...)
1132 {
1133 int res;
1134 va_list vargs;
1135
1136 #ifdef HAVE_STDARG_PROTOTYPES
1137 va_start(vargs, format);
1138 #else
1139 va_start(vargs);
1140 #endif
1141 res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
1142 stack_level, format, vargs);
1143 va_end(vargs);
1144 return res;
1145 }
1146
1147
1148 int
PyErr_WarnEx(PyObject * category,const char * text,Py_ssize_t stack_level)1149 PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
1150 {
1151 int ret;
1152 PyObject *message = PyUnicode_FromString(text);
1153 if (message == NULL)
1154 return -1;
1155 ret = warn_unicode(category, message, stack_level, NULL);
1156 Py_DECREF(message);
1157 return ret;
1158 }
1159
1160 /* PyErr_Warn is only for backwards compatibility and will be removed.
1161 Use PyErr_WarnEx instead. */
1162
1163 #undef PyErr_Warn
1164
1165 int
PyErr_Warn(PyObject * category,const char * text)1166 PyErr_Warn(PyObject *category, const char *text)
1167 {
1168 return PyErr_WarnEx(category, text, 1);
1169 }
1170
1171 /* Warning with explicit origin */
1172 int
PyErr_WarnExplicitObject(PyObject * category,PyObject * message,PyObject * filename,int lineno,PyObject * module,PyObject * registry)1173 PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
1174 PyObject *filename, int lineno,
1175 PyObject *module, PyObject *registry)
1176 {
1177 PyObject *res;
1178 if (category == NULL)
1179 category = PyExc_RuntimeWarning;
1180 res = warn_explicit(category, message, filename, lineno,
1181 module, registry, NULL, NULL);
1182 if (res == NULL)
1183 return -1;
1184 Py_DECREF(res);
1185 return 0;
1186 }
1187
1188 int
PyErr_WarnExplicit(PyObject * category,const char * text,const char * filename_str,int lineno,const char * module_str,PyObject * registry)1189 PyErr_WarnExplicit(PyObject *category, const char *text,
1190 const char *filename_str, int lineno,
1191 const char *module_str, PyObject *registry)
1192 {
1193 PyObject *message = PyUnicode_FromString(text);
1194 PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1195 PyObject *module = NULL;
1196 int ret = -1;
1197
1198 if (message == NULL || filename == NULL)
1199 goto exit;
1200 if (module_str != NULL) {
1201 module = PyUnicode_FromString(module_str);
1202 if (module == NULL)
1203 goto exit;
1204 }
1205
1206 ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
1207 module, registry);
1208
1209 exit:
1210 Py_XDECREF(message);
1211 Py_XDECREF(module);
1212 Py_XDECREF(filename);
1213 return ret;
1214 }
1215
1216 int
PyErr_WarnExplicitFormat(PyObject * category,const char * filename_str,int lineno,const char * module_str,PyObject * registry,const char * format,...)1217 PyErr_WarnExplicitFormat(PyObject *category,
1218 const char *filename_str, int lineno,
1219 const char *module_str, PyObject *registry,
1220 const char *format, ...)
1221 {
1222 PyObject *message;
1223 PyObject *module = NULL;
1224 PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1225 int ret = -1;
1226 va_list vargs;
1227
1228 if (filename == NULL)
1229 goto exit;
1230 if (module_str != NULL) {
1231 module = PyUnicode_FromString(module_str);
1232 if (module == NULL)
1233 goto exit;
1234 }
1235
1236 #ifdef HAVE_STDARG_PROTOTYPES
1237 va_start(vargs, format);
1238 #else
1239 va_start(vargs);
1240 #endif
1241 message = PyUnicode_FromFormatV(format, vargs);
1242 if (message != NULL) {
1243 PyObject *res;
1244 res = warn_explicit(category, message, filename, lineno,
1245 module, registry, NULL, NULL);
1246 Py_DECREF(message);
1247 if (res != NULL) {
1248 Py_DECREF(res);
1249 ret = 0;
1250 }
1251 }
1252 va_end(vargs);
1253 exit:
1254 Py_XDECREF(module);
1255 Py_XDECREF(filename);
1256 return ret;
1257 }
1258
1259 void
_PyErr_WarnUnawaitedCoroutine(PyObject * coro)1260 _PyErr_WarnUnawaitedCoroutine(PyObject *coro)
1261 {
1262 /* First, we attempt to funnel the warning through
1263 warnings._warn_unawaited_coroutine.
1264
1265 This could raise an exception, due to:
1266 - a bug
1267 - some kind of shutdown-related brokenness
1268 - succeeding, but with an "error" warning filter installed, so the
1269 warning is converted into a RuntimeWarning exception
1270
1271 In the first two cases, we want to print the error (so we know what it
1272 is!), and then print a warning directly as a fallback. In the last
1273 case, we want to print the error (since it's the warning!), but *not*
1274 do a fallback. And after we print the error we can't check for what
1275 type of error it was (because PyErr_WriteUnraisable clears it), so we
1276 need a flag to keep track.
1277
1278 Since this is called from __del__ context, it's careful to never raise
1279 an exception.
1280 */
1281 _Py_IDENTIFIER(_warn_unawaited_coroutine);
1282 int warned = 0;
1283 PyObject *fn = get_warnings_attr(&PyId__warn_unawaited_coroutine, 1);
1284 if (fn) {
1285 PyObject *res = PyObject_CallFunctionObjArgs(fn, coro, NULL);
1286 Py_DECREF(fn);
1287 if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
1288 warned = 1;
1289 }
1290 Py_XDECREF(res);
1291 }
1292
1293 if (PyErr_Occurred()) {
1294 PyErr_WriteUnraisable(coro);
1295 }
1296 if (!warned) {
1297 if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
1298 "coroutine '%.50S' was never awaited",
1299 ((PyCoroObject *)coro)->cr_qualname) < 0)
1300 {
1301 PyErr_WriteUnraisable(coro);
1302 }
1303 }
1304 }
1305
1306 PyDoc_STRVAR(warn_explicit_doc,
1307 "Low-level interface to warnings functionality.");
1308
1309 static PyMethodDef warnings_functions[] = {
1310 WARNINGS_WARN_METHODDEF
1311 {"warn_explicit", (PyCFunction)(void(*)(void))warnings_warn_explicit,
1312 METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
1313 {"_filters_mutated", (PyCFunction)warnings_filters_mutated, METH_NOARGS,
1314 NULL},
1315 /* XXX(brett.cannon): add showwarning? */
1316 /* XXX(brett.cannon): Reasonable to add formatwarning? */
1317 {NULL, NULL} /* sentinel */
1318 };
1319
1320
1321 static struct PyModuleDef warningsmodule = {
1322 PyModuleDef_HEAD_INIT,
1323 MODULE_NAME, /* m_name */
1324 warnings__doc__, /* m_doc */
1325 0, /* m_size */
1326 warnings_functions, /* m_methods */
1327 NULL, /* m_reload */
1328 NULL, /* m_traverse */
1329 NULL, /* m_clear */
1330 NULL /* m_free */
1331 };
1332
1333
1334 PyMODINIT_FUNC
_PyWarnings_Init(void)1335 _PyWarnings_Init(void)
1336 {
1337 PyObject *m;
1338
1339 m = PyModule_Create(&warningsmodule);
1340 if (m == NULL) {
1341 return NULL;
1342 }
1343
1344 WarningsState *st = _Warnings_GetState();
1345 if (st == NULL) {
1346 goto error;
1347 }
1348 if (_Warnings_InitState(st) < 0) {
1349 goto error;
1350 }
1351
1352 Py_INCREF(st->filters);
1353 if (PyModule_AddObject(m, "filters", st->filters) < 0) {
1354 goto error;
1355 }
1356
1357 Py_INCREF(st->once_registry);
1358 if (PyModule_AddObject(m, "_onceregistry", st->once_registry) < 0) {
1359 goto error;
1360 }
1361
1362 Py_INCREF(st->default_action);
1363 if (PyModule_AddObject(m, "_defaultaction", st->default_action) < 0) {
1364 goto error;
1365 }
1366
1367 return m;
1368
1369 error:
1370 if (st != NULL) {
1371 _Warnings_ClearState(st);
1372 }
1373 Py_DECREF(m);
1374 return NULL;
1375 }
1376
1377 // We need this to ensure that warnings still work until late in finalization.
1378 void
_PyWarnings_Fini(PyInterpreterState * interp)1379 _PyWarnings_Fini(PyInterpreterState *interp)
1380 {
1381 _Warnings_ClearState(&interp->warnings);
1382 }
1383