blob: 6a970bbb2bb706e79f4e878b00c587baf4353ee6 [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);
307 category = (PyObject*)message->ob_type;
308 }
309 else {
310 text = message;
311 message = PyObject_CallFunction(category, "O", message);
Brett Cannondea1b562008-06-27 00:31:13 +0000312 if (message == NULL)
313 goto cleanup;
Brett Cannone9746892008-04-12 23:44:07 +0000314 }
315
316 lineno_obj = PyInt_FromLong(lineno);
317 if (lineno_obj == NULL)
318 goto cleanup;
319
320 /* Create key. */
321 key = PyTuple_Pack(3, text, category, lineno_obj);
322 if (key == NULL)
323 goto cleanup;
324
Brett Cannondea1b562008-06-27 00:31:13 +0000325 if ((registry != NULL) && (registry != Py_None)) {
Brett Cannone9746892008-04-12 23:44:07 +0000326 rc = already_warned(registry, key, 0);
327 if (rc == -1)
328 goto cleanup;
329 else if (rc == 1)
330 goto return_none;
331 /* Else this warning hasn't been generated before. */
332 }
333
334 action = get_filter(category, text, lineno, module, &item);
335 if (action == NULL)
336 goto cleanup;
337
338 if (strcmp(action, "error") == 0) {
339 PyErr_SetObject(category, message);
340 goto cleanup;
341 }
342
343 /* Store in the registry that we've been here, *except* when the action
344 is "always". */
345 rc = 0;
346 if (strcmp(action, "always") != 0) {
Brett Cannondea1b562008-06-27 00:31:13 +0000347 if (registry != NULL && registry != Py_None &&
348 PyDict_SetItem(registry, key, Py_True) < 0)
Brett Cannone9746892008-04-12 23:44:07 +0000349 goto cleanup;
350 else if (strcmp(action, "ignore") == 0)
351 goto return_none;
352 else if (strcmp(action, "once") == 0) {
Brett Cannondea1b562008-06-27 00:31:13 +0000353 if (registry == NULL || registry == Py_None) {
Brett Cannone9746892008-04-12 23:44:07 +0000354 registry = get_once_registry();
355 if (registry == NULL)
356 goto cleanup;
357 }
358 /* _once_registry[(text, category)] = 1 */
Brett Cannon8a232cc2008-05-05 05:32:07 +0000359 rc = update_registry(registry, text, category, 0);
Brett Cannone9746892008-04-12 23:44:07 +0000360 }
361 else if (strcmp(action, "module") == 0) {
362 /* registry[(text, category, 0)] = 1 */
Brett Cannondea1b562008-06-27 00:31:13 +0000363 if (registry != NULL && registry != Py_None)
Brett Cannon8a232cc2008-05-05 05:32:07 +0000364 rc = update_registry(registry, text, category, 0);
Brett Cannone9746892008-04-12 23:44:07 +0000365 }
366 else if (strcmp(action, "default") != 0) {
367 PyObject *to_str = PyObject_Str(item);
368 const char *err_str = "???";
369
370 if (to_str != NULL)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000371 err_str = PyString_AS_STRING(to_str);
Brett Cannone9746892008-04-12 23:44:07 +0000372 PyErr_Format(PyExc_RuntimeError,
373 "Unrecognized action (%s) in warnings.filters:\n %s",
374 action, err_str);
375 Py_XDECREF(to_str);
376 goto cleanup;
377 }
378 }
379
Christian Heimes32a66a02008-10-02 19:47:50 +0000380 if (rc == 1) /* Already warned for this module. */
Brett Cannone9746892008-04-12 23:44:07 +0000381 goto return_none;
382 if (rc == 0) {
383 PyObject *show_fxn = get_warnings_attr("showwarning");
384 if (show_fxn == NULL) {
385 if (PyErr_Occurred())
386 goto cleanup;
387 show_warning(filename, lineno, text, category, sourceline);
388 }
389 else {
Brett Cannon8a232cc2008-05-05 05:32:07 +0000390 const char *msg = "functions overriding warnings.showwarning() "
391 "must support the 'line' argument";
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000392 const char *text_char = PyString_AS_STRING(text);
Brett Cannon8a232cc2008-05-05 05:32:07 +0000393
394 if (strcmp(msg, text_char) == 0) {
395 /* Prevent infinite recursion by using built-in implementation
396 of showwarning(). */
397 show_warning(filename, lineno, text, category, sourceline);
398 }
399 else {
400 PyObject *check_fxn;
401 PyObject *defaults;
402 PyObject *res;
403
404 if (PyMethod_Check(show_fxn))
405 check_fxn = PyMethod_Function(show_fxn);
406 else if (PyFunction_Check(show_fxn))
407 check_fxn = show_fxn;
408 else {
409 PyErr_SetString(PyExc_TypeError,
410 "warnings.showwarning() must be set to a "
411 "function or method");
Benjamin Petersond2950322008-05-06 22:18:11 +0000412 Py_DECREF(show_fxn);
413 goto cleanup;
Brett Cannon8a232cc2008-05-05 05:32:07 +0000414 }
415
416 defaults = PyFunction_GetDefaults(check_fxn);
417 /* A proper implementation of warnings.showwarning() should
418 have at least two default arguments. */
419 if ((defaults == NULL) || (PyTuple_Size(defaults) < 2)) {
Brett Cannon1eaf0742008-09-02 01:25:16 +0000420 PyCodeObject *code = (PyCodeObject *)
421 PyFunction_GetCode(check_fxn);
422 if (!(code->co_flags & CO_VARARGS)) {
423 if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) <
424 0) {
425 Py_DECREF(show_fxn);
426 goto cleanup;
427 }
Georg Brandl9c5b5152008-05-13 21:32:03 +0000428 }
Brett Cannon1eaf0742008-09-02 01:25:16 +0000429 }
Brett Cannon8a232cc2008-05-05 05:32:07 +0000430 res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
Brett Cannone9746892008-04-12 23:44:07 +0000431 filename, lineno_obj,
Brett Cannone9746892008-04-12 23:44:07 +0000432 NULL);
Brett Cannon8a232cc2008-05-05 05:32:07 +0000433 Py_DECREF(show_fxn);
434 Py_XDECREF(res);
435 if (res == NULL)
436 goto cleanup;
437 }
Brett Cannone9746892008-04-12 23:44:07 +0000438 }
439 }
440 else /* if (rc == -1) */
441 goto cleanup;
442
443 return_none:
444 result = Py_None;
445 Py_INCREF(result);
446
447 cleanup:
448 Py_XDECREF(key);
449 Py_XDECREF(text);
450 Py_XDECREF(lineno_obj);
451 Py_DECREF(module);
Brett Cannondea1b562008-06-27 00:31:13 +0000452 Py_XDECREF(message);
Brett Cannone9746892008-04-12 23:44:07 +0000453 return result; /* Py_None or NULL. */
454}
455
456/* filename, module, and registry are new refs, globals is borrowed */
457/* Returns 0 on error (no new refs), 1 on success */
458static int
459setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
460 PyObject **module, PyObject **registry)
461{
462 PyObject *globals;
463
464 /* Setup globals and lineno. */
465 PyFrameObject *f = PyThreadState_GET()->frame;
Brett Cannone3dcb012008-05-06 04:37:31 +0000466 while (--stack_level > 0 && f != NULL)
Brett Cannone9746892008-04-12 23:44:07 +0000467 f = f->f_back;
Brett Cannone9746892008-04-12 23:44:07 +0000468
469 if (f == NULL) {
470 globals = PyThreadState_Get()->interp->sysdict;
471 *lineno = 1;
472 }
473 else {
474 globals = f->f_globals;
475 *lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
476 }
477
478 *module = NULL;
479
480 /* Setup registry. */
481 assert(globals != NULL);
482 assert(PyDict_Check(globals));
483 *registry = PyDict_GetItemString(globals, "__warningregistry__");
484 if (*registry == NULL) {
485 int rc;
486
487 *registry = PyDict_New();
488 if (*registry == NULL)
489 return 0;
490
491 rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
492 if (rc < 0)
493 goto handle_error;
494 }
495 else
496 Py_INCREF(*registry);
497
498 /* Setup module. */
499 *module = PyDict_GetItemString(globals, "__name__");
500 if (*module == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000501 *module = PyString_FromString("<string>");
Brett Cannone9746892008-04-12 23:44:07 +0000502 if (*module == NULL)
503 goto handle_error;
504 }
505 else
506 Py_INCREF(*module);
507
508 /* Setup filename. */
509 *filename = PyDict_GetItemString(globals, "__file__");
510 if (*filename != NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000511 Py_ssize_t len = PyString_Size(*filename);
512 const char *file_str = PyString_AsString(*filename);
Brett Cannonab9cc1b2008-05-03 01:02:41 +0000513 if (file_str == NULL || (len < 0 && PyErr_Occurred()))
Brett Cannone9746892008-04-12 23:44:07 +0000514 goto handle_error;
515
516 /* if filename.lower().endswith((".pyc", ".pyo")): */
517 if (len >= 4 &&
518 file_str[len-4] == '.' &&
519 tolower(file_str[len-3]) == 'p' &&
520 tolower(file_str[len-2]) == 'y' &&
521 (tolower(file_str[len-1]) == 'c' ||
Brett Cannonab9cc1b2008-05-03 01:02:41 +0000522 tolower(file_str[len-1]) == 'o'))
523 {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000524 *filename = PyString_FromStringAndSize(file_str, len-1);
Brett Cannonab9cc1b2008-05-03 01:02:41 +0000525 if (*filename == NULL)
526 goto handle_error;
527 }
528 else
Brett Cannone9746892008-04-12 23:44:07 +0000529 Py_INCREF(*filename);
530 }
531 else {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000532 const char *module_str = PyString_AsString(*module);
Brett Cannone9746892008-04-12 23:44:07 +0000533 if (module_str && strcmp(module_str, "__main__") == 0) {
534 PyObject *argv = PySys_GetObject("argv");
535 if (argv != NULL && PyList_Size(argv) > 0) {
Brett Cannon64a4bbe2008-05-03 03:19:39 +0000536 int is_true;
Brett Cannone9746892008-04-12 23:44:07 +0000537 *filename = PyList_GetItem(argv, 0);
538 Py_INCREF(*filename);
Brett Cannon64a4bbe2008-05-03 03:19:39 +0000539 /* If sys.argv[0] is false, then use '__main__'. */
540 is_true = PyObject_IsTrue(*filename);
541 if (is_true < 0) {
542 Py_DECREF(*filename);
543 goto handle_error;
544 }
545 else if (!is_true) {
546 Py_DECREF(*filename);
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000547 *filename = PyString_FromString("__main__");
Brett Cannon64a4bbe2008-05-03 03:19:39 +0000548 if (*filename == NULL)
549 goto handle_error;
550 }
Brett Cannone9746892008-04-12 23:44:07 +0000551 }
552 else {
553 /* embedded interpreters don't have sys.argv, see bug #839151 */
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000554 *filename = PyString_FromString("__main__");
Brett Cannonab9cc1b2008-05-03 01:02:41 +0000555 if (*filename == NULL)
556 goto handle_error;
Brett Cannone9746892008-04-12 23:44:07 +0000557 }
558 }
559 if (*filename == NULL) {
560 *filename = *module;
561 Py_INCREF(*filename);
562 }
563 }
564
565 return 1;
566
567 handle_error:
568 /* filename not XDECREF'ed here as there is no way to jump here with a
569 dangling reference. */
570 Py_XDECREF(*registry);
571 Py_XDECREF(*module);
572 return 0;
573}
574
575static PyObject *
576get_category(PyObject *message, PyObject *category)
577{
578 int rc;
579
580 /* Get category. */
581 rc = PyObject_IsInstance(message, PyExc_Warning);
582 if (rc == -1)
583 return NULL;
584
585 if (rc == 1)
586 category = (PyObject*)message->ob_type;
587 else if (category == NULL)
588 category = PyExc_UserWarning;
589
590 /* Validate category. */
591 rc = PyObject_IsSubclass(category, PyExc_Warning);
592 if (rc == -1)
593 return NULL;
594 if (rc == 0) {
595 PyErr_SetString(PyExc_ValueError,
596 "category is not a subclass of Warning");
597 return NULL;
598 }
599
600 return category;
601}
602
603static PyObject *
604do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
605{
606 PyObject *filename, *module, *registry, *res;
607 int lineno;
608
609 if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
610 return NULL;
611
612 res = warn_explicit(category, message, filename, lineno, module, registry,
613 NULL);
614 Py_DECREF(filename);
615 Py_DECREF(registry);
616 Py_DECREF(module);
617 return res;
618}
619
620static PyObject *
621warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
622{
623 static char *kw_list[] = { "message", "category", "stacklevel", 0 };
624 PyObject *message, *category = NULL;
625 Py_ssize_t stack_level = 1;
626
Brett Cannon8a232cc2008-05-05 05:32:07 +0000627 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
Brett Cannone9746892008-04-12 23:44:07 +0000628 &message, &category, &stack_level))
629 return NULL;
630
631 category = get_category(message, category);
632 if (category == NULL)
633 return NULL;
634 return do_warn(message, category, stack_level);
635}
636
637static PyObject *
638warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
639{
640 static char *kwd_list[] = {"message", "category", "filename", "lineno",
641 "module", "registry", "module_globals", 0};
642 PyObject *message;
643 PyObject *category;
644 PyObject *filename;
645 int lineno;
646 PyObject *module = NULL;
647 PyObject *registry = NULL;
648 PyObject *module_globals = NULL;
649
650 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
651 kwd_list, &message, &category, &filename, &lineno, &module,
652 &registry, &module_globals))
653 return NULL;
654
655 if (module_globals) {
656 static PyObject *get_source_name = NULL;
657 static PyObject *splitlines_name = NULL;
658 PyObject *loader;
659 PyObject *module_name;
660 PyObject *source;
661 PyObject *source_list;
662 PyObject *source_line;
663 PyObject *returned;
664
665 if (get_source_name == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000666 get_source_name = PyString_InternFromString("get_source");
Brett Cannone9746892008-04-12 23:44:07 +0000667 if (!get_source_name)
668 return NULL;
669 }
670 if (splitlines_name == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000671 splitlines_name = PyString_InternFromString("splitlines");
Brett Cannone9746892008-04-12 23:44:07 +0000672 if (!splitlines_name)
673 return NULL;
674 }
675
676 /* Check/get the requisite pieces needed for the loader. */
677 loader = PyDict_GetItemString(module_globals, "__loader__");
678 module_name = PyDict_GetItemString(module_globals, "__name__");
679
680 if (loader == NULL || module_name == NULL)
681 goto standard_call;
682
683 /* Make sure the loader implements the optional get_source() method. */
684 if (!PyObject_HasAttrString(loader, "get_source"))
685 goto standard_call;
686 /* Call get_source() to get the source code. */
687 source = PyObject_CallMethodObjArgs(loader, get_source_name,
688 module_name, NULL);
689 if (!source)
690 return NULL;
691 else if (source == Py_None) {
692 Py_DECREF(Py_None);
693 goto standard_call;
694 }
695
696 /* Split the source into lines. */
697 source_list = PyObject_CallMethodObjArgs(source, splitlines_name,
698 NULL);
699 Py_DECREF(source);
700 if (!source_list)
701 return NULL;
702
703 /* Get the source line. */
704 source_line = PyList_GetItem(source_list, lineno-1);
705 if (!source_line) {
706 Py_DECREF(source_list);
707 return NULL;
708 }
709
710 /* Handle the warning. */
711 returned = warn_explicit(category, message, filename, lineno, module,
712 registry, source_line);
713 Py_DECREF(source_list);
714 return returned;
715 }
716
717 standard_call:
718 return warn_explicit(category, message, filename, lineno, module,
719 registry, NULL);
720}
721
722
723/* Function to issue a warning message; may raise an exception. */
724int
725PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
726{
727 PyObject *res;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000728 PyObject *message = PyString_FromString(text);
Brett Cannone9746892008-04-12 23:44:07 +0000729 if (message == NULL)
730 return -1;
731
732 if (category == NULL)
733 category = PyExc_RuntimeWarning;
734
735 res = do_warn(message, category, stack_level);
736 Py_DECREF(message);
737 if (res == NULL)
738 return -1;
739 Py_DECREF(res);
740
741 return 0;
742}
743
744/* PyErr_Warn is only for backwards compatability and will be removed.
745 Use PyErr_WarnEx instead. */
746
747#undef PyErr_Warn
748
749PyAPI_FUNC(int)
750PyErr_Warn(PyObject *category, char *text)
751{
752 return PyErr_WarnEx(category, text, 1);
753}
754
755/* Warning with explicit origin */
756int
757PyErr_WarnExplicit(PyObject *category, const char *text,
758 const char *filename_str, int lineno,
759 const char *module_str, PyObject *registry)
760{
761 PyObject *res;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000762 PyObject *message = PyString_FromString(text);
763 PyObject *filename = PyString_FromString(filename_str);
Brett Cannone9746892008-04-12 23:44:07 +0000764 PyObject *module = NULL;
765 int ret = -1;
766
767 if (message == NULL || filename == NULL)
768 goto exit;
769 if (module_str != NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000770 module = PyString_FromString(module_str);
Brett Cannone9746892008-04-12 23:44:07 +0000771 if (module == NULL)
772 goto exit;
773 }
774
775 if (category == NULL)
776 category = PyExc_RuntimeWarning;
777 res = warn_explicit(category, message, filename, lineno, module, registry,
778 NULL);
779 if (res == NULL)
780 goto exit;
781 Py_DECREF(res);
782 ret = 0;
783
784 exit:
785 Py_XDECREF(message);
786 Py_XDECREF(module);
787 Py_XDECREF(filename);
788 return ret;
789}
790
791
Brett Cannone9746892008-04-12 23:44:07 +0000792PyDoc_STRVAR(warn_doc,
793"Issue a warning, or maybe ignore it or raise an exception.");
794
795PyDoc_STRVAR(warn_explicit_doc,
796"Low-level inferface to warnings functionality.");
797
798static PyMethodDef warnings_functions[] = {
799 {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
800 warn_doc},
801 {"warn_explicit", (PyCFunction)warnings_warn_explicit,
802 METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
Christian Heimes32a66a02008-10-02 19:47:50 +0000803 /* XXX(brett.cannon): add showwarning? */
804 /* XXX(brett.cannon): Reasonable to add formatwarning? */
Brett Cannone9746892008-04-12 23:44:07 +0000805 {NULL, NULL} /* sentinel */
806};
807
808
809static PyObject *
810create_filter(PyObject *category, const char *action)
811{
812 static PyObject *ignore_str = NULL;
813 static PyObject *error_str = NULL;
814 static PyObject *default_str = NULL;
815 PyObject *action_obj = NULL;
816 PyObject *lineno, *result;
817
818 if (!strcmp(action, "ignore")) {
819 if (ignore_str == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000820 ignore_str = PyString_InternFromString("ignore");
Brett Cannone9746892008-04-12 23:44:07 +0000821 if (ignore_str == NULL)
822 return NULL;
823 }
824 action_obj = ignore_str;
825 }
826 else if (!strcmp(action, "error")) {
827 if (error_str == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000828 error_str = PyString_InternFromString("error");
Brett Cannone9746892008-04-12 23:44:07 +0000829 if (error_str == NULL)
830 return NULL;
831 }
832 action_obj = error_str;
833 }
834 else if (!strcmp(action, "default")) {
835 if (default_str == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000836 default_str = PyString_InternFromString("default");
Brett Cannone9746892008-04-12 23:44:07 +0000837 if (default_str == NULL)
838 return NULL;
839 }
840 action_obj = default_str;
841 }
842 else {
843 Py_FatalError("unknown action");
844 }
845
846 /* This assumes the line number is zero for now. */
847 lineno = PyInt_FromLong(0);
848 if (lineno == NULL)
849 return NULL;
850 result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
851 Py_DECREF(lineno);
852 return result;
853}
854
855static PyObject *
856init_filters(void)
857{
858 PyObject *filters = PyList_New(3);
859 const char *bytes_action;
860 if (filters == NULL)
861 return NULL;
862
863 PyList_SET_ITEM(filters, 0,
864 create_filter(PyExc_PendingDeprecationWarning, "ignore"));
865 PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore"));
866 if (Py_BytesWarningFlag > 1)
867 bytes_action = "error";
868 else if (Py_BytesWarningFlag)
869 bytes_action = "default";
870 else
871 bytes_action = "ignore";
872 PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning,
873 bytes_action));
874
875 if (PyList_GET_ITEM(filters, 0) == NULL ||
876 PyList_GET_ITEM(filters, 1) == NULL ||
877 PyList_GET_ITEM(filters, 2) == NULL) {
878 Py_DECREF(filters);
879 return NULL;
880 }
881
882 return filters;
883}
884
885
886PyMODINIT_FUNC
887_PyWarnings_Init(void)
888{
889 PyObject *m, *default_action;
890
891 m = Py_InitModule3(MODULE_NAME, warnings_functions, warnings__doc__);
892 if (m == NULL)
893 return;
894
895 _filters = init_filters();
896 if (_filters == NULL)
897 return;
898 Py_INCREF(_filters);
899 if (PyModule_AddObject(m, "filters", _filters) < 0)
900 return;
901
902 _once_registry = PyDict_New();
903 if (_once_registry == NULL)
904 return;
905 Py_INCREF(_once_registry);
906 if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
907 return;
908
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000909 default_action = PyString_InternFromString("default");
Brett Cannone9746892008-04-12 23:44:07 +0000910 if (default_action == NULL)
911 return;
912 if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0)
913 return;
914}