2
#include "frameobject.h"
4
#define MODULE_NAME "_warnings"
5
#define DEFAULT_ACTION_NAME "default_action"
7
PyDoc_STRVAR(warnings__doc__,
8
MODULE_NAME " provides basic warning filtering support.\n"
9
"It is a helper module to speed up interpreter start-up.");
11
/* Both 'filters' and 'onceregistry' can be set in warnings.py;
12
get_warnings_attr() will reset these variables accordingly. */
13
static PyObject *_filters; /* List */
14
static PyObject *_once_registry; /* Dict */
18
check_matched(PyObject *obj, PyObject *arg)
25
result = PyObject_CallMethod(obj, "match", "O", arg);
29
rc = PyObject_IsTrue(result);
35
Returns a new reference.
36
A NULL return value can mean false or an error.
39
get_warnings_attr(const char *attr)
41
static PyObject *warnings_str = NULL;
42
PyObject *all_modules;
43
PyObject *warnings_module;
46
if (warnings_str == NULL) {
47
warnings_str = PyUnicode_InternFromString("warnings");
48
if (warnings_str == NULL)
52
all_modules = PyImport_GetModuleDict();
53
result = PyDict_Contains(all_modules, warnings_str);
54
if (result == -1 || result == 0)
57
warnings_module = PyDict_GetItem(all_modules, warnings_str);
58
if (!PyObject_HasAttrString(warnings_module, attr))
60
return PyObject_GetAttrString(warnings_module, attr);
65
get_once_registry(void)
69
registry = get_warnings_attr("onceregistry");
70
if (registry == NULL) {
73
return _once_registry;
75
Py_DECREF(_once_registry);
76
_once_registry = registry;
81
/* The item is a borrowed reference. */
83
get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
84
PyObject *module, PyObject **item)
86
PyObject *action, *m, *d;
88
PyObject *warnings_filters;
90
warnings_filters = get_warnings_attr("filters");
91
if (warnings_filters == NULL) {
97
_filters = warnings_filters;
100
if (!PyList_Check(_filters)) {
101
PyErr_SetString(PyExc_ValueError,
102
MODULE_NAME ".filters must be a list");
106
/* _filters could change while we are iterating over it. */
107
for (i = 0; i < PyList_GET_SIZE(_filters); i++) {
108
PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
110
int is_subclass, good_msg, good_mod;
112
tmp_item = *item = PyList_GET_ITEM(_filters, i);
113
if (PyTuple_Size(tmp_item) != 5) {
114
PyErr_Format(PyExc_ValueError,
115
MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
119
/* Python code: action, msg, cat, mod, ln = item */
120
action = PyTuple_GET_ITEM(tmp_item, 0);
121
msg = PyTuple_GET_ITEM(tmp_item, 1);
122
cat = PyTuple_GET_ITEM(tmp_item, 2);
123
mod = PyTuple_GET_ITEM(tmp_item, 3);
124
ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
126
good_msg = check_matched(msg, text);
127
good_mod = check_matched(mod, module);
128
is_subclass = PyObject_IsSubclass(category, cat);
129
ln = PyLong_AsSsize_t(ln_obj);
130
if (good_msg == -1 || good_mod == -1 || is_subclass == -1 ||
131
(ln == -1 && PyErr_Occurred()))
134
if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))
135
return _PyUnicode_AsString(action);
138
m = PyImport_ImportModule(MODULE_NAME);
141
d = PyModule_GetDict(m);
145
action = PyDict_GetItemString(d, DEFAULT_ACTION_NAME);
147
return _PyUnicode_AsString(action);
149
PyErr_SetString(PyExc_ValueError,
150
MODULE_NAME "." DEFAULT_ACTION_NAME " not found");
155
already_warned(PyObject *registry, PyObject *key, int should_set)
157
PyObject *already_warned;
162
already_warned = PyDict_GetItem(registry, key);
163
if (already_warned != NULL) {
164
int rc = PyObject_IsTrue(already_warned);
169
/* This warning wasn't found in the registry, set it. */
171
return PyDict_SetItem(registry, key, Py_True);
177
normalize_module(PyObject *filename)
183
int rc = PyObject_IsTrue(filename);
187
return PyUnicode_FromString("<unknown>");
189
mod_str = _PyUnicode_AsString(filename);
192
len = PyUnicode_GetSize(filename);
196
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
197
module = PyUnicode_FromStringAndSize(mod_str, len-3);
207
update_registry(PyObject *registry, PyObject *text, PyObject *category,
210
PyObject *altkey, *zero = NULL;
214
zero = PyLong_FromLong(0);
217
altkey = PyTuple_Pack(3, text, category, zero);
220
altkey = PyTuple_Pack(2, text, category);
222
rc = already_warned(registry, altkey, 1);
229
show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
230
*category, PyObject *sourceline)
234
char lineno_str[128];
236
PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
238
name = PyObject_GetAttrString(category, "__name__");
239
if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */
242
f_stderr = PySys_GetObject("stderr");
243
if (f_stderr == NULL) {
244
fprintf(stderr, "lost sys.stderr\n");
249
/* Print "filename:lineno: category: text\n" */
250
PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW);
251
PyFile_WriteString(lineno_str, f_stderr);
252
PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW);
253
PyFile_WriteString(": ", f_stderr);
254
PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW);
255
PyFile_WriteString("\n", f_stderr);
258
/* Print " source_line\n" */
260
char *source_line_str = _PyUnicode_AsString(sourceline);
261
if (source_line_str == NULL)
263
while (*source_line_str == ' ' || *source_line_str == '\t' ||
264
*source_line_str == '\014')
267
PyFile_WriteString(source_line_str, f_stderr);
268
PyFile_WriteString("\n", f_stderr);
271
if (_Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename),
278
warn_explicit(PyObject *category, PyObject *message,
279
PyObject *filename, int lineno,
280
PyObject *module, PyObject *registry, PyObject *sourceline)
282
PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
283
PyObject *item = Py_None;
287
if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
288
PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
292
/* Normalize module. */
293
if (module == NULL) {
294
module = normalize_module(filename);
301
/* Normalize message. */
302
Py_INCREF(message); /* DECREF'ed in cleanup. */
303
rc = PyObject_IsInstance(message, PyExc_Warning);
308
text = PyObject_Str(message);
309
category = (PyObject*)message->ob_type;
313
message = PyObject_CallFunction(category, "O", message);
318
lineno_obj = PyLong_FromLong(lineno);
319
if (lineno_obj == NULL)
323
key = PyTuple_Pack(3, text, category, lineno_obj);
327
if ((registry != NULL) && (registry != Py_None)) {
328
rc = already_warned(registry, key, 0);
333
/* Else this warning hasn't been generated before. */
336
action = get_filter(category, text, lineno, module, &item);
340
if (strcmp(action, "error") == 0) {
341
PyErr_SetObject(category, message);
345
/* Store in the registry that we've been here, *except* when the action
348
if (strcmp(action, "always") != 0) {
349
if (registry != NULL && registry != Py_None &&
350
PyDict_SetItem(registry, key, Py_True) < 0)
352
else if (strcmp(action, "ignore") == 0)
354
else if (strcmp(action, "once") == 0) {
355
if (registry == NULL || registry == Py_None) {
356
registry = get_once_registry();
357
if (registry == NULL)
360
/* _once_registry[(text, category)] = 1 */
361
rc = update_registry(registry, text, category, 0);
363
else if (strcmp(action, "module") == 0) {
364
/* registry[(text, category, 0)] = 1 */
365
if (registry != NULL && registry != Py_None)
366
rc = update_registry(registry, text, category, 0);
368
else if (strcmp(action, "default") != 0) {
369
PyObject *to_str = PyObject_Str(item);
370
const char *err_str = "???";
372
if (to_str != NULL) {
373
err_str = _PyUnicode_AsString(to_str);
377
PyErr_Format(PyExc_RuntimeError,
378
"Unrecognized action (%s) in warnings.filters:\n %s",
385
if (rc == 1) /* Already warned for this module. */
388
PyObject *show_fxn = get_warnings_attr("showwarning");
389
if (show_fxn == NULL) {
390
if (PyErr_Occurred())
392
show_warning(filename, lineno, text, category, sourceline);
397
if (!PyMethod_Check(show_fxn) && !PyFunction_Check(show_fxn)) {
398
PyErr_SetString(PyExc_TypeError,
399
"warnings.showwarning() must be set to a "
400
"function or method");
405
res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
406
filename, lineno_obj,
414
else /* if (rc == -1) */
424
Py_XDECREF(lineno_obj);
427
return result; /* Py_None or NULL. */
430
/* filename, module, and registry are new refs, globals is borrowed */
431
/* Returns 0 on error (no new refs), 1 on success */
433
setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
434
PyObject **module, PyObject **registry)
438
/* Setup globals and lineno. */
439
PyFrameObject *f = PyThreadState_GET()->frame;
440
while (--stack_level > 0 && f != NULL)
444
globals = PyThreadState_Get()->interp->sysdict;
448
globals = f->f_globals;
449
*lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
454
/* Setup registry. */
455
assert(globals != NULL);
456
assert(PyDict_Check(globals));
457
*registry = PyDict_GetItemString(globals, "__warningregistry__");
458
if (*registry == NULL) {
461
*registry = PyDict_New();
462
if (*registry == NULL)
465
rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
470
Py_INCREF(*registry);
473
*module = PyDict_GetItemString(globals, "__name__");
474
if (*module == NULL) {
475
*module = PyUnicode_FromString("<string>");
482
/* Setup filename. */
483
*filename = PyDict_GetItemString(globals, "__file__");
484
if (*filename != NULL) {
485
Py_ssize_t len = PyUnicode_GetSize(*filename);
486
const char *file_str = _PyUnicode_AsString(*filename);
487
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
490
/* if filename.lower().endswith((".pyc", ".pyo")): */
492
file_str[len-4] == '.' &&
493
tolower(file_str[len-3]) == 'p' &&
494
tolower(file_str[len-2]) == 'y' &&
495
(tolower(file_str[len-1]) == 'c' ||
496
tolower(file_str[len-1]) == 'o'))
498
*filename = PyUnicode_FromStringAndSize(file_str, len-1);
499
if (*filename == NULL)
503
Py_INCREF(*filename);
506
const char *module_str = _PyUnicode_AsString(*module);
507
if (module_str == NULL)
509
if (strcmp(module_str, "__main__") == 0) {
510
PyObject *argv = PySys_GetObject("argv");
511
if (argv != NULL && PyList_Size(argv) > 0) {
513
*filename = PyList_GetItem(argv, 0);
514
Py_INCREF(*filename);
515
/* If sys.argv[0] is false, then use '__main__'. */
516
is_true = PyObject_IsTrue(*filename);
518
Py_DECREF(*filename);
522
Py_DECREF(*filename);
523
*filename = PyUnicode_FromString("__main__");
524
if (*filename == NULL)
529
/* embedded interpreters don't have sys.argv, see bug #839151 */
530
*filename = PyUnicode_FromString("__main__");
531
if (*filename == NULL)
535
if (*filename == NULL) {
537
Py_INCREF(*filename);
544
/* filename not XDECREF'ed here as there is no way to jump here with a
545
dangling reference. */
546
Py_XDECREF(*registry);
552
get_category(PyObject *message, PyObject *category)
557
rc = PyObject_IsInstance(message, PyExc_Warning);
562
category = (PyObject*)message->ob_type;
563
else if (category == NULL)
564
category = PyExc_UserWarning;
566
/* Validate category. */
567
rc = PyObject_IsSubclass(category, PyExc_Warning);
571
PyErr_SetString(PyExc_ValueError,
572
"category is not a subclass of Warning");
580
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
582
PyObject *filename, *module, *registry, *res;
585
if (!setup_context(stack_level, &filename, &lineno, &module, ®istry))
588
res = warn_explicit(category, message, filename, lineno, module, registry,
597
warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
599
static char *kw_list[] = { "message", "category", "stacklevel", 0 };
600
PyObject *message, *category = NULL;
601
Py_ssize_t stack_level = 1;
603
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
604
&message, &category, &stack_level))
607
category = get_category(message, category);
608
if (category == NULL)
610
return do_warn(message, category, stack_level);
614
warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
616
static char *kwd_list[] = {"message", "category", "filename", "lineno",
617
"module", "registry", "module_globals", 0};
622
PyObject *module = NULL;
623
PyObject *registry = NULL;
624
PyObject *module_globals = NULL;
626
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
627
kwd_list, &message, &category, &filename, &lineno, &module,
628
®istry, &module_globals))
631
if (module_globals) {
632
static PyObject *get_source_name = NULL;
633
static PyObject *splitlines_name = NULL;
635
PyObject *module_name;
637
PyObject *source_list;
638
PyObject *source_line;
641
if (get_source_name == NULL) {
642
get_source_name = PyUnicode_InternFromString("get_source");
643
if (!get_source_name)
646
if (splitlines_name == NULL) {
647
splitlines_name = PyUnicode_InternFromString("splitlines");
648
if (!splitlines_name)
652
/* Check/get the requisite pieces needed for the loader. */
653
loader = PyDict_GetItemString(module_globals, "__loader__");
654
module_name = PyDict_GetItemString(module_globals, "__name__");
656
if (loader == NULL || module_name == NULL)
659
/* Make sure the loader implements the optional get_source() method. */
660
if (!PyObject_HasAttrString(loader, "get_source"))
662
/* Call get_source() to get the source code. */
663
source = PyObject_CallMethodObjArgs(loader, get_source_name,
667
else if (source == Py_None) {
672
/* Split the source into lines. */
673
source_list = PyObject_CallMethodObjArgs(source, splitlines_name,
679
/* Get the source line. */
680
source_line = PyList_GetItem(source_list, lineno-1);
682
Py_DECREF(source_list);
686
/* Handle the warning. */
687
returned = warn_explicit(category, message, filename, lineno, module,
688
registry, source_line);
689
Py_DECREF(source_list);
694
return warn_explicit(category, message, filename, lineno, module,
699
/* Function to issue a warning message; may raise an exception. */
701
PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
704
PyObject *message = PyUnicode_FromString(text);
708
if (category == NULL)
709
category = PyExc_RuntimeWarning;
711
res = do_warn(message, category, stack_level);
720
/* PyErr_Warn is only for backwards compatability and will be removed.
721
Use PyErr_WarnEx instead. */
726
PyErr_Warn(PyObject *category, char *text)
728
return PyErr_WarnEx(category, text, 1);
731
/* Warning with explicit origin */
733
PyErr_WarnExplicit(PyObject *category, const char *text,
734
const char *filename_str, int lineno,
735
const char *module_str, PyObject *registry)
738
PyObject *message = PyUnicode_FromString(text);
739
PyObject *filename = PyUnicode_FromString(filename_str);
740
PyObject *module = NULL;
743
if (message == NULL || filename == NULL)
745
if (module_str != NULL) {
746
module = PyUnicode_FromString(module_str);
751
if (category == NULL)
752
category = PyExc_RuntimeWarning;
753
res = warn_explicit(category, message, filename, lineno, module, registry,
763
Py_XDECREF(filename);
768
PyDoc_STRVAR(warn_doc,
769
"Issue a warning, or maybe ignore it or raise an exception.");
771
PyDoc_STRVAR(warn_explicit_doc,
772
"Low-level inferface to warnings functionality.");
774
static PyMethodDef warnings_functions[] = {
775
{"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
777
{"warn_explicit", (PyCFunction)warnings_warn_explicit,
778
METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
779
/* XXX(brett.cannon): add showwarning? */
780
/* XXX(brett.cannon): Reasonable to add formatwarning? */
781
{NULL, NULL} /* sentinel */
786
create_filter(PyObject *category, const char *action)
788
static PyObject *ignore_str = NULL;
789
static PyObject *error_str = NULL;
790
static PyObject *default_str = NULL;
791
PyObject *action_obj = NULL;
792
PyObject *lineno, *result;
794
if (!strcmp(action, "ignore")) {
795
if (ignore_str == NULL) {
796
ignore_str = PyUnicode_InternFromString("ignore");
797
if (ignore_str == NULL)
800
action_obj = ignore_str;
802
else if (!strcmp(action, "error")) {
803
if (error_str == NULL) {
804
error_str = PyUnicode_InternFromString("error");
805
if (error_str == NULL)
808
action_obj = error_str;
810
else if (!strcmp(action, "default")) {
811
if (default_str == NULL) {
812
default_str = PyUnicode_InternFromString("default");
813
if (default_str == NULL)
816
action_obj = default_str;
819
Py_FatalError("unknown action");
822
/* This assumes the line number is zero for now. */
823
lineno = PyLong_FromLong(0);
826
result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
834
PyObject *filters = PyList_New(3);
835
const char *bytes_action;
839
PyList_SET_ITEM(filters, 0,
840
create_filter(PyExc_PendingDeprecationWarning, "ignore"));
841
PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore"));
842
if (Py_BytesWarningFlag > 1)
843
bytes_action = "error";
844
else if (Py_BytesWarningFlag)
845
bytes_action = "default";
847
bytes_action = "ignore";
848
PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning,
851
if (PyList_GET_ITEM(filters, 0) == NULL ||
852
PyList_GET_ITEM(filters, 1) == NULL ||
853
PyList_GET_ITEM(filters, 2) == NULL) {
861
static struct PyModuleDef warningsmodule = {
862
PyModuleDef_HEAD_INIT,
875
_PyWarnings_Init(void)
877
PyObject *m, *default_action;
879
m = PyModule_Create(&warningsmodule);
883
_filters = init_filters();
884
if (_filters == NULL)
887
if (PyModule_AddObject(m, "filters", _filters) < 0)
890
_once_registry = PyDict_New();
891
if (_once_registry == NULL)
893
Py_INCREF(_once_registry);
894
if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
897
default_action = PyUnicode_InternFromString("default");
898
if (default_action == NULL)
900
if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0)