blob: 1f0f58e31d6361adddb187bb5d06f6cefcafee12 [file] [log] [blame]
Brett Cannone9746892008-04-12 23:44:07 +00001#include "Python.h"
Brett Cannon1eaf0742008-09-02 01:25:16 +00002#include "code.h" /* For DeprecationWarning about adding 'line'. */
Brett Cannone9746892008-04-12 23:44:07 +00003#include "frameobject.h"
4
5#define MODULE_NAME "_warnings"
6#define DEFAULT_ACTION_NAME "default_action"
7
8PyDoc_STRVAR(warnings__doc__,
9MODULE_NAME " provides basic warning filtering support.\n"
10"It is a helper module to speed up interpreter start-up.");
11
12/* Both 'filters' and 'onceregistry' can be set in warnings.py;
13 get_warnings_attr() will reset these variables accordingly. */
14static PyObject *_filters; /* List */
15static PyObject *_once_registry; /* Dict */
16
17
18static int
19check_matched(PyObject *obj, PyObject *arg)
20{
21 PyObject *result;
22 int rc;
23
24 if (obj == Py_None)
25 return 1;
26 result = PyObject_CallMethod(obj, "match", "O", arg);
27 if (result == NULL)
28 return -1;
29
30 rc = PyObject_IsTrue(result);
31 Py_DECREF(result);
32 return rc;
33}
34
35/*
36 Returns a new reference.
37 A NULL return value can mean false or an error.
38*/
39static PyObject *
40get_warnings_attr(const char *attr)
41{
42 static PyObject *warnings_str = NULL;
43 PyObject *all_modules;
44 PyObject *warnings_module;
45 int result;
46
47 if (warnings_str == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +000048 warnings_str = PyString_InternFromString("warnings");
Brett Cannone9746892008-04-12 23:44:07 +000049 if (warnings_str == NULL)
50 return NULL;
51 }
52
53 all_modules = PyImport_GetModuleDict();
54 result = PyDict_Contains(all_modules, warnings_str);
55 if (result == -1 || result == 0)
56 return NULL;
57
58 warnings_module = PyDict_GetItem(all_modules, warnings_str);
59 if (!PyObject_HasAttrString(warnings_module, attr))
60 return NULL;
61 return PyObject_GetAttrString(warnings_module, attr);
62}
63
64
Amaury Forgeot d'Arcf9e7ebe2008-04-14 20:07:48 +000065static PyObject *
Brett Cannone9746892008-04-12 23:44:07 +000066get_once_registry(void)
67{
68 PyObject *registry;
69
70 registry = get_warnings_attr("onceregistry");
71 if (registry == NULL) {
72 if (PyErr_Occurred())
73 return NULL;
74 return _once_registry;
75 }
76 Py_DECREF(_once_registry);
77 _once_registry = registry;
78 return registry;
79}
80
81
82/* The item is a borrowed reference. */
83static const char *
84get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
85 PyObject *module, PyObject **item)
86{
87 PyObject *action, *m, *d;
88 Py_ssize_t i;
89 PyObject *warnings_filters;
90
91 warnings_filters = get_warnings_attr("filters");
92 if (warnings_filters == NULL) {
93 if (PyErr_Occurred())
94 return NULL;
95 }
96 else {
97 Py_DECREF(_filters);
98 _filters = warnings_filters;
99 }
100
101 if (!PyList_Check(_filters)) {
102 PyErr_SetString(PyExc_ValueError,
103 MODULE_NAME ".filters must be a list");
104 return NULL;
105 }
106
107 /* _filters could change while we are iterating over it. */
108 for (i = 0; i < PyList_GET_SIZE(_filters); i++) {
109 PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
110 Py_ssize_t ln;
111 int is_subclass, good_msg, good_mod;
112
113 tmp_item = *item = PyList_GET_ITEM(_filters, i);
114 if (PyTuple_Size(tmp_item) != 5) {
115 PyErr_Format(PyExc_ValueError,
116 MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
117 return NULL;
118 }
119
120 /* Python code: action, msg, cat, mod, ln = item */
121 action = PyTuple_GET_ITEM(tmp_item, 0);
122 msg = PyTuple_GET_ITEM(tmp_item, 1);
123 cat = PyTuple_GET_ITEM(tmp_item, 2);
124 mod = PyTuple_GET_ITEM(tmp_item, 3);
125 ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
126
127 good_msg = check_matched(msg, text);
128 good_mod = check_matched(mod, module);
129 is_subclass = PyObject_IsSubclass(category, cat);
130 ln = PyInt_AsSsize_t(ln_obj);
131 if (good_msg == -1 || good_mod == -1 || is_subclass == -1 ||
132 (ln == -1 && PyErr_Occurred()))
133 return NULL;
134
135 if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000136 return PyString_AsString(action);
Brett Cannone9746892008-04-12 23:44:07 +0000137 }
138
139 m = PyImport_ImportModule(MODULE_NAME);
140 if (m == NULL)
141 return NULL;
142 d = PyModule_GetDict(m);
143 Py_DECREF(m);
144 if (d == NULL)
145 return NULL;
146 action = PyDict_GetItemString(d, DEFAULT_ACTION_NAME);
147 if (action != NULL)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000148 return PyString_AsString(action);
Brett Cannone9746892008-04-12 23:44:07 +0000149
150 PyErr_SetString(PyExc_ValueError,
151 MODULE_NAME "." DEFAULT_ACTION_NAME " not found");
152 return NULL;
153}
154
155static int
156already_warned(PyObject *registry, PyObject *key, int should_set)
157{
158 PyObject *already_warned;
159
160 if (key == NULL)
161 return -1;
162
163 already_warned = PyDict_GetItem(registry, key);
164 if (already_warned != NULL) {
165 int rc = PyObject_IsTrue(already_warned);
166 if (rc != 0)
167 return rc;
168 }
169
170 /* This warning wasn't found in the registry, set it. */
171 if (should_set)
172 return PyDict_SetItem(registry, key, Py_True);
173 return 0;
174}
175
176/* New reference. */
177static PyObject *
178normalize_module(PyObject *filename)
179{
180 PyObject *module;
181 const char *mod_str;
182 Py_ssize_t len;
183
184 int rc = PyObject_IsTrue(filename);
185 if (rc == -1)
186 return NULL;
187 else if (rc == 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000188 return PyString_FromString("<unknown>");
Brett Cannone9746892008-04-12 23:44:07 +0000189
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000190 mod_str = PyString_AsString(filename);
Brett Cannone9746892008-04-12 23:44:07 +0000191 if (mod_str == NULL)
192 return NULL;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000193 len = PyString_Size(filename);
Brett Cannone9746892008-04-12 23:44:07 +0000194 if (len < 0)
195 return NULL;
196 if (len >= 3 &&
197 strncmp(mod_str + (len - 3), ".py", 3) == 0) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000198 module = PyString_FromStringAndSize(mod_str, len-3);
Brett Cannone9746892008-04-12 23:44:07 +0000199 }
200 else {
201 module = filename;
202 Py_INCREF(module);
203 }
204 return module;
205}
206
207static int
208update_registry(PyObject *registry, PyObject *text, PyObject *category,
209 int add_zero)
210{
211 PyObject *altkey, *zero = NULL;
212 int rc;
213
214 if (add_zero) {
215 zero = PyInt_FromLong(0);
216 if (zero == NULL)
217 return -1;
218 altkey = PyTuple_Pack(3, text, category, zero);
219 }
220 else
221 altkey = PyTuple_Pack(2, text, category);
222
223 rc = already_warned(registry, altkey, 1);
224 Py_XDECREF(zero);
225 Py_XDECREF(altkey);
226 return rc;
227}
228
229static void
230show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
231 *category, PyObject *sourceline)
232{
Brett Cannon8a232cc2008-05-05 05:32:07 +0000233 PyObject *f_stderr;
234 PyObject *name;
Brett Cannone9746892008-04-12 23:44:07 +0000235 char lineno_str[128];
236
237 PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
238
239 name = PyObject_GetAttrString(category, "__name__");
240 if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */
241 return;
242
243 f_stderr = PySys_GetObject("stderr");
244 if (f_stderr == NULL) {
245 fprintf(stderr, "lost sys.stderr\n");
246 Py_DECREF(name);
247 return;
248 }
249
250 /* Print "filename:lineno: category: text\n" */
251 PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW);
252 PyFile_WriteString(lineno_str, f_stderr);
253 PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW);
254 PyFile_WriteString(": ", f_stderr);
255 PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW);
256 PyFile_WriteString("\n", f_stderr);
257 Py_XDECREF(name);
258
259 /* Print " source_line\n" */
Brett Cannone9746892008-04-12 23:44:07 +0000260 if (sourceline) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000261 char *source_line_str = PyString_AS_STRING(sourceline);
Brett Cannone9746892008-04-12 23:44:07 +0000262 while (*source_line_str == ' ' || *source_line_str == '\t' ||
263 *source_line_str == '\014')
264 source_line_str++;
265
266 PyFile_WriteString(source_line_str, f_stderr);
267 PyFile_WriteString("\n", f_stderr);
268 }
269 else
Amaury Forgeot d'Arc2252d112008-07-11 21:45:06 +0000270 _Py_DisplaySourceLine(f_stderr, PyString_AS_STRING(filename),
271 lineno, 2);
Brett Cannone9746892008-04-12 23:44:07 +0000272 PyErr_Clear();
273}
274
275static PyObject *
Brett Cannon8a232cc2008-05-05 05:32:07 +0000276warn_explicit(PyObject *category, PyObject *message,
Brett Cannone9746892008-04-12 23:44:07 +0000277 PyObject *filename, int lineno,
278 PyObject *module, PyObject *registry, PyObject *sourceline)
279{
280 PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
281 PyObject *item = Py_None;
282 const char *action;
283 int rc;
Brett Cannondea1b562008-06-27 00:31:13 +0000284
285 if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
286 PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
287 return NULL;
288 }
Brett Cannone9746892008-04-12 23:44:07 +0000289
290 /* Normalize module. */
291 if (module == NULL) {
292 module = normalize_module(filename);
293 if (module == NULL)
294 return NULL;
295 }
296 else
297 Py_INCREF(module);
298
299 /* Normalize message. */
300 Py_INCREF(message); /* DECREF'ed in cleanup. */
301 rc = PyObject_IsInstance(message, PyExc_Warning);
302 if (rc == -1) {
303 goto cleanup;
304 }
305 if (rc == 1) {
306 text = PyObject_Str(message);
Hirokazu Yamamotofcaa2102009-07-17 06:33:03 +0000307 if (text == NULL)
308 goto cleanup;
Brett Cannone9746892008-04-12 23:44:07 +0000309 category = (PyObject*)message->ob_type;
310 }
311 else {
312 text = message;
313 message = PyObject_CallFunction(category, "O", message);
Brett Cannondea1b562008-06-27 00:31:13 +0000314 if (message == NULL)
315 goto cleanup;
Brett Cannone9746892008-04-12 23:44:07 +0000316 }
317
318 lineno_obj = PyInt_FromLong(lineno);
319 if (lineno_obj == NULL)
320 goto cleanup;
321
322 /* Create key. */
323 key = PyTuple_Pack(3, text, category, lineno_obj);
324 if (key == NULL)
325 goto cleanup;
326
Brett Cannondea1b562008-06-27 00:31:13 +0000327 if ((registry != NULL) && (registry != Py_None)) {
Brett Cannone9746892008-04-12 23:44:07 +0000328 rc = already_warned(registry, key, 0);
329 if (rc == -1)
330 goto cleanup;
331 else if (rc == 1)
332 goto return_none;
333 /* Else this warning hasn't been generated before. */
334 }
335
336 action = get_filter(category, text, lineno, module, &item);
337 if (action == NULL)
338 goto cleanup;
339
340 if (strcmp(action, "error") == 0) {
341 PyErr_SetObject(category, message);
342 goto cleanup;
343 }
344
345 /* Store in the registry that we've been here, *except* when the action
346 is "always". */
347 rc = 0;
348 if (strcmp(action, "always") != 0) {
Brett Cannondea1b562008-06-27 00:31:13 +0000349 if (registry != NULL && registry != Py_None &&
350 PyDict_SetItem(registry, key, Py_True) < 0)
Brett Cannone9746892008-04-12 23:44:07 +0000351 goto cleanup;
352 else if (strcmp(action, "ignore") == 0)
353 goto return_none;
354 else if (strcmp(action, "once") == 0) {
Brett Cannondea1b562008-06-27 00:31:13 +0000355 if (registry == NULL || registry == Py_None) {
Brett Cannone9746892008-04-12 23:44:07 +0000356 registry = get_once_registry();
357 if (registry == NULL)
358 goto cleanup;
359 }
360 /* _once_registry[(text, category)] = 1 */
Brett Cannon8a232cc2008-05-05 05:32:07 +0000361 rc = update_registry(registry, text, category, 0);
Brett Cannone9746892008-04-12 23:44:07 +0000362 }
363 else if (strcmp(action, "module") == 0) {
364 /* registry[(text, category, 0)] = 1 */
Brett Cannondea1b562008-06-27 00:31:13 +0000365 if (registry != NULL && registry != Py_None)
Brett Cannon8a232cc2008-05-05 05:32:07 +0000366 rc = update_registry(registry, text, category, 0);
Brett Cannone9746892008-04-12 23:44:07 +0000367 }
368 else if (strcmp(action, "default") != 0) {
369 PyObject *to_str = PyObject_Str(item);
370 const char *err_str = "???";
371
372 if (to_str != NULL)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000373 err_str = PyString_AS_STRING(to_str);
Brett Cannone9746892008-04-12 23:44:07 +0000374 PyErr_Format(PyExc_RuntimeError,
375 "Unrecognized action (%s) in warnings.filters:\n %s",
376 action, err_str);
377 Py_XDECREF(to_str);
378 goto cleanup;
379 }
380 }
381
Christian Heimes4d8a6f42008-10-02 19:49:47 +0000382 if (rc == 1) /* Already warned for this module. */
Brett Cannone9746892008-04-12 23:44:07 +0000383 goto return_none;
384 if (rc == 0) {
385 PyObject *show_fxn = get_warnings_attr("showwarning");
386 if (show_fxn == NULL) {
387 if (PyErr_Occurred())
388 goto cleanup;
389 show_warning(filename, lineno, text, category, sourceline);
390 }
391 else {
Brett Cannon8a232cc2008-05-05 05:32:07 +0000392 const char *msg = "functions overriding warnings.showwarning() "
393 "must support the 'line' argument";
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000394 const char *text_char = PyString_AS_STRING(text);
Brett Cannon8a232cc2008-05-05 05:32:07 +0000395
396 if (strcmp(msg, text_char) == 0) {
397 /* Prevent infinite recursion by using built-in implementation
398 of showwarning(). */
399 show_warning(filename, lineno, text, category, sourceline);
400 }
401 else {
402 PyObject *check_fxn;
403 PyObject *defaults;
404 PyObject *res;
405
406 if (PyMethod_Check(show_fxn))
407 check_fxn = PyMethod_Function(show_fxn);
408 else if (PyFunction_Check(show_fxn))
409 check_fxn = show_fxn;
410 else {
411 PyErr_SetString(PyExc_TypeError,
412 "warnings.showwarning() must be set to a "
413 "function or method");
Benjamin Petersond2950322008-05-06 22:18:11 +0000414 Py_DECREF(show_fxn);
415 goto cleanup;
Brett Cannon8a232cc2008-05-05 05:32:07 +0000416 }
417
418 defaults = PyFunction_GetDefaults(check_fxn);
419 /* A proper implementation of warnings.showwarning() should
420 have at least two default arguments. */
421 if ((defaults == NULL) || (PyTuple_Size(defaults) < 2)) {
Brett Cannon1eaf0742008-09-02 01:25:16 +0000422 PyCodeObject *code = (PyCodeObject *)
423 PyFunction_GetCode(check_fxn);
424 if (!(code->co_flags & CO_VARARGS)) {
425 if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) <
426 0) {
427 Py_DECREF(show_fxn);
428 goto cleanup;
429 }
Georg Brandl9c5b5152008-05-13 21:32:03 +0000430 }
Brett Cannon1eaf0742008-09-02 01:25:16 +0000431 }
Brett Cannon8a232cc2008-05-05 05:32:07 +0000432 res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
Brett Cannone9746892008-04-12 23:44:07 +0000433 filename, lineno_obj,
Brett Cannone9746892008-04-12 23:44:07 +0000434 NULL);
Brett Cannon8a232cc2008-05-05 05:32:07 +0000435 Py_DECREF(show_fxn);
436 Py_XDECREF(res);
437 if (res == NULL)
438 goto cleanup;
439 }
Brett Cannone9746892008-04-12 23:44:07 +0000440 }
441 }
442 else /* if (rc == -1) */
443 goto cleanup;
444
445 return_none:
446 result = Py_None;
447 Py_INCREF(result);
448
449 cleanup:
450 Py_XDECREF(key);
451 Py_XDECREF(text);
452 Py_XDECREF(lineno_obj);
453 Py_DECREF(module);
Brett Cannondea1b562008-06-27 00:31:13 +0000454 Py_XDECREF(message);
Brett Cannone9746892008-04-12 23:44:07 +0000455 return result; /* Py_None or NULL. */
456}
457
458/* filename, module, and registry are new refs, globals is borrowed */
459/* Returns 0 on error (no new refs), 1 on success */
460static int
461setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
462 PyObject **module, PyObject **registry)
463{
464 PyObject *globals;
465
466 /* Setup globals and lineno. */
467 PyFrameObject *f = PyThreadState_GET()->frame;
Brett Cannone3dcb012008-05-06 04:37:31 +0000468 while (--stack_level > 0 && f != NULL)
Brett Cannone9746892008-04-12 23:44:07 +0000469 f = f->f_back;
Brett Cannone9746892008-04-12 23:44:07 +0000470
471 if (f == NULL) {
472 globals = PyThreadState_Get()->interp->sysdict;
473 *lineno = 1;
474 }
475 else {
476 globals = f->f_globals;
477 *lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
478 }
479
480 *module = NULL;
481
482 /* Setup registry. */
483 assert(globals != NULL);
484 assert(PyDict_Check(globals));
485 *registry = PyDict_GetItemString(globals, "__warningregistry__");
486 if (*registry == NULL) {
487 int rc;
488
489 *registry = PyDict_New();
490 if (*registry == NULL)
491 return 0;
492
493 rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
494 if (rc < 0)
495 goto handle_error;
496 }
497 else
498 Py_INCREF(*registry);
499
500 /* Setup module. */
501 *module = PyDict_GetItemString(globals, "__name__");
502 if (*module == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000503 *module = PyString_FromString("<string>");
Brett Cannone9746892008-04-12 23:44:07 +0000504 if (*module == NULL)
505 goto handle_error;
506 }
507 else
508 Py_INCREF(*module);
509
510 /* Setup filename. */
511 *filename = PyDict_GetItemString(globals, "__file__");
512 if (*filename != NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000513 Py_ssize_t len = PyString_Size(*filename);
514 const char *file_str = PyString_AsString(*filename);
Brett Cannonab9cc1b2008-05-03 01:02:41 +0000515 if (file_str == NULL || (len < 0 && PyErr_Occurred()))
Brett Cannone9746892008-04-12 23:44:07 +0000516 goto handle_error;
517
518 /* if filename.lower().endswith((".pyc", ".pyo")): */
519 if (len >= 4 &&
520 file_str[len-4] == '.' &&
521 tolower(file_str[len-3]) == 'p' &&
522 tolower(file_str[len-2]) == 'y' &&
523 (tolower(file_str[len-1]) == 'c' ||
Brett Cannonab9cc1b2008-05-03 01:02:41 +0000524 tolower(file_str[len-1]) == 'o'))
525 {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000526 *filename = PyString_FromStringAndSize(file_str, len-1);
Brett Cannonab9cc1b2008-05-03 01:02:41 +0000527 if (*filename == NULL)
528 goto handle_error;
529 }
530 else
Brett Cannone9746892008-04-12 23:44:07 +0000531 Py_INCREF(*filename);
532 }
533 else {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000534 const char *module_str = PyString_AsString(*module);
Brett Cannone9746892008-04-12 23:44:07 +0000535 if (module_str && strcmp(module_str, "__main__") == 0) {
536 PyObject *argv = PySys_GetObject("argv");
537 if (argv != NULL && PyList_Size(argv) > 0) {
Brett Cannon64a4bbe2008-05-03 03:19:39 +0000538 int is_true;
Brett Cannone9746892008-04-12 23:44:07 +0000539 *filename = PyList_GetItem(argv, 0);
540 Py_INCREF(*filename);
Brett Cannon64a4bbe2008-05-03 03:19:39 +0000541 /* If sys.argv[0] is false, then use '__main__'. */
542 is_true = PyObject_IsTrue(*filename);
543 if (is_true < 0) {
544 Py_DECREF(*filename);
545 goto handle_error;
546 }
547 else if (!is_true) {
548 Py_DECREF(*filename);
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000549 *filename = PyString_FromString("__main__");
Brett Cannon64a4bbe2008-05-03 03:19:39 +0000550 if (*filename == NULL)
551 goto handle_error;
552 }
Brett Cannone9746892008-04-12 23:44:07 +0000553 }
554 else {
555 /* embedded interpreters don't have sys.argv, see bug #839151 */
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000556 *filename = PyString_FromString("__main__");
Brett Cannonab9cc1b2008-05-03 01:02:41 +0000557 if (*filename == NULL)
558 goto handle_error;
Brett Cannone9746892008-04-12 23:44:07 +0000559 }
560 }
561 if (*filename == NULL) {
562 *filename = *module;
563 Py_INCREF(*filename);
564 }
565 }
566
567 return 1;
568
569 handle_error:
570 /* filename not XDECREF'ed here as there is no way to jump here with a
571 dangling reference. */
572 Py_XDECREF(*registry);
573 Py_XDECREF(*module);
574 return 0;
575}
576
577static PyObject *
578get_category(PyObject *message, PyObject *category)
579{
580 int rc;
581
582 /* Get category. */
583 rc = PyObject_IsInstance(message, PyExc_Warning);
584 if (rc == -1)
585 return NULL;
586
587 if (rc == 1)
588 category = (PyObject*)message->ob_type;
589 else if (category == NULL)
590 category = PyExc_UserWarning;
591
592 /* Validate category. */
593 rc = PyObject_IsSubclass(category, PyExc_Warning);
594 if (rc == -1)
595 return NULL;
596 if (rc == 0) {
597 PyErr_SetString(PyExc_ValueError,
598 "category is not a subclass of Warning");
599 return NULL;
600 }
601
602 return category;
603}
604
605static PyObject *
606do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
607{
608 PyObject *filename, *module, *registry, *res;
609 int lineno;
610
611 if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
612 return NULL;
613
614 res = warn_explicit(category, message, filename, lineno, module, registry,
615 NULL);
616 Py_DECREF(filename);
617 Py_DECREF(registry);
618 Py_DECREF(module);
619 return res;
620}
621
622static PyObject *
623warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
624{
625 static char *kw_list[] = { "message", "category", "stacklevel", 0 };
626 PyObject *message, *category = NULL;
627 Py_ssize_t stack_level = 1;
628
Brett Cannon8a232cc2008-05-05 05:32:07 +0000629 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
Brett Cannone9746892008-04-12 23:44:07 +0000630 &message, &category, &stack_level))
631 return NULL;
632
633 category = get_category(message, category);
634 if (category == NULL)
635 return NULL;
636 return do_warn(message, category, stack_level);
637}
638
639static PyObject *
640warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
641{
642 static char *kwd_list[] = {"message", "category", "filename", "lineno",
643 "module", "registry", "module_globals", 0};
644 PyObject *message;
645 PyObject *category;
646 PyObject *filename;
647 int lineno;
648 PyObject *module = NULL;
649 PyObject *registry = NULL;
650 PyObject *module_globals = NULL;
651
652 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
653 kwd_list, &message, &category, &filename, &lineno, &module,
654 &registry, &module_globals))
655 return NULL;
656
657 if (module_globals) {
658 static PyObject *get_source_name = NULL;
659 static PyObject *splitlines_name = NULL;
660 PyObject *loader;
661 PyObject *module_name;
662 PyObject *source;
663 PyObject *source_list;
664 PyObject *source_line;
665 PyObject *returned;
666
667 if (get_source_name == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000668 get_source_name = PyString_InternFromString("get_source");
Brett Cannone9746892008-04-12 23:44:07 +0000669 if (!get_source_name)
670 return NULL;
671 }
672 if (splitlines_name == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000673 splitlines_name = PyString_InternFromString("splitlines");
Brett Cannone9746892008-04-12 23:44:07 +0000674 if (!splitlines_name)
675 return NULL;
676 }
677
678 /* Check/get the requisite pieces needed for the loader. */
679 loader = PyDict_GetItemString(module_globals, "__loader__");
680 module_name = PyDict_GetItemString(module_globals, "__name__");
681
682 if (loader == NULL || module_name == NULL)
683 goto standard_call;
684
685 /* Make sure the loader implements the optional get_source() method. */
686 if (!PyObject_HasAttrString(loader, "get_source"))
687 goto standard_call;
688 /* Call get_source() to get the source code. */
689 source = PyObject_CallMethodObjArgs(loader, get_source_name,
690 module_name, NULL);
691 if (!source)
692 return NULL;
693 else if (source == Py_None) {
694 Py_DECREF(Py_None);
695 goto standard_call;
696 }
697
698 /* Split the source into lines. */
699 source_list = PyObject_CallMethodObjArgs(source, splitlines_name,
700 NULL);
701 Py_DECREF(source);
702 if (!source_list)
703 return NULL;
704
705 /* Get the source line. */
706 source_line = PyList_GetItem(source_list, lineno-1);
707 if (!source_line) {
708 Py_DECREF(source_list);
709 return NULL;
710 }
711
712 /* Handle the warning. */
713 returned = warn_explicit(category, message, filename, lineno, module,
714 registry, source_line);
715 Py_DECREF(source_list);
716 return returned;
717 }
718
719 standard_call:
720 return warn_explicit(category, message, filename, lineno, module,
721 registry, NULL);
722}
723
724
725/* Function to issue a warning message; may raise an exception. */
726int
727PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
728{
729 PyObject *res;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000730 PyObject *message = PyString_FromString(text);
Brett Cannone9746892008-04-12 23:44:07 +0000731 if (message == NULL)
732 return -1;
733
734 if (category == NULL)
735 category = PyExc_RuntimeWarning;
736
737 res = do_warn(message, category, stack_level);
738 Py_DECREF(message);
739 if (res == NULL)
740 return -1;
741 Py_DECREF(res);
742
743 return 0;
744}
745
746/* PyErr_Warn is only for backwards compatability and will be removed.
747 Use PyErr_WarnEx instead. */
748
749#undef PyErr_Warn
750
751PyAPI_FUNC(int)
752PyErr_Warn(PyObject *category, char *text)
753{
754 return PyErr_WarnEx(category, text, 1);
755}
756
757/* Warning with explicit origin */
758int
759PyErr_WarnExplicit(PyObject *category, const char *text,
760 const char *filename_str, int lineno,
761 const char *module_str, PyObject *registry)
762{
763 PyObject *res;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000764 PyObject *message = PyString_FromString(text);
765 PyObject *filename = PyString_FromString(filename_str);
Brett Cannone9746892008-04-12 23:44:07 +0000766 PyObject *module = NULL;
767 int ret = -1;
768
769 if (message == NULL || filename == NULL)
770 goto exit;
771 if (module_str != NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000772 module = PyString_FromString(module_str);
Brett Cannone9746892008-04-12 23:44:07 +0000773 if (module == NULL)
774 goto exit;
775 }
776
777 if (category == NULL)
778 category = PyExc_RuntimeWarning;
779 res = warn_explicit(category, message, filename, lineno, module, registry,
780 NULL);
781 if (res == NULL)
782 goto exit;
783 Py_DECREF(res);
784 ret = 0;
785
786 exit:
787 Py_XDECREF(message);
788 Py_XDECREF(module);
789 Py_XDECREF(filename);
790 return ret;
791}
792
793
Brett Cannone9746892008-04-12 23:44:07 +0000794PyDoc_STRVAR(warn_doc,
795"Issue a warning, or maybe ignore it or raise an exception.");
796
797PyDoc_STRVAR(warn_explicit_doc,
798"Low-level inferface to warnings functionality.");
799
800static PyMethodDef warnings_functions[] = {
801 {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
802 warn_doc},
803 {"warn_explicit", (PyCFunction)warnings_warn_explicit,
804 METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
Christian Heimes4d8a6f42008-10-02 19:49:47 +0000805 /* XXX(brett.cannon): add showwarning? */
806 /* XXX(brett.cannon): Reasonable to add formatwarning? */
Brett Cannone9746892008-04-12 23:44:07 +0000807 {NULL, NULL} /* sentinel */
808};
809
810
811static PyObject *
812create_filter(PyObject *category, const char *action)
813{
814 static PyObject *ignore_str = NULL;
815 static PyObject *error_str = NULL;
816 static PyObject *default_str = NULL;
817 PyObject *action_obj = NULL;
818 PyObject *lineno, *result;
819
820 if (!strcmp(action, "ignore")) {
821 if (ignore_str == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000822 ignore_str = PyString_InternFromString("ignore");
Brett Cannone9746892008-04-12 23:44:07 +0000823 if (ignore_str == NULL)
824 return NULL;
825 }
826 action_obj = ignore_str;
827 }
828 else if (!strcmp(action, "error")) {
829 if (error_str == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000830 error_str = PyString_InternFromString("error");
Brett Cannone9746892008-04-12 23:44:07 +0000831 if (error_str == NULL)
832 return NULL;
833 }
834 action_obj = error_str;
835 }
836 else if (!strcmp(action, "default")) {
837 if (default_str == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000838 default_str = PyString_InternFromString("default");
Brett Cannone9746892008-04-12 23:44:07 +0000839 if (default_str == NULL)
840 return NULL;
841 }
842 action_obj = default_str;
843 }
844 else {
845 Py_FatalError("unknown action");
846 }
847
848 /* This assumes the line number is zero for now. */
849 lineno = PyInt_FromLong(0);
850 if (lineno == NULL)
851 return NULL;
852 result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
853 Py_DECREF(lineno);
854 return result;
855}
856
857static PyObject *
858init_filters(void)
859{
860 PyObject *filters = PyList_New(3);
861 const char *bytes_action;
862 if (filters == NULL)
863 return NULL;
864
865 PyList_SET_ITEM(filters, 0,
866 create_filter(PyExc_PendingDeprecationWarning, "ignore"));
867 PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore"));
868 if (Py_BytesWarningFlag > 1)
869 bytes_action = "error";
870 else if (Py_BytesWarningFlag)
871 bytes_action = "default";
872 else
873 bytes_action = "ignore";
874 PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning,
875 bytes_action));
876
877 if (PyList_GET_ITEM(filters, 0) == NULL ||
878 PyList_GET_ITEM(filters, 1) == NULL ||
879 PyList_GET_ITEM(filters, 2) == NULL) {
880 Py_DECREF(filters);
881 return NULL;
882 }
883
884 return filters;
885}
886
887
888PyMODINIT_FUNC
889_PyWarnings_Init(void)
890{
891 PyObject *m, *default_action;
892
893 m = Py_InitModule3(MODULE_NAME, warnings_functions, warnings__doc__);
894 if (m == NULL)
895 return;
896
897 _filters = init_filters();
898 if (_filters == NULL)
899 return;
900 Py_INCREF(_filters);
901 if (PyModule_AddObject(m, "filters", _filters) < 0)
902 return;
903
904 _once_registry = PyDict_New();
905 if (_once_registry == NULL)
906 return;
907 Py_INCREF(_once_registry);
908 if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
909 return;
910
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000911 default_action = PyString_InternFromString("default");
Brett Cannone9746892008-04-12 23:44:07 +0000912 if (default_action == NULL)
913 return;
914 if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0)
915 return;
916}