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