|
1 #include "Python.h" |
|
2 #include "code.h" /* For DeprecationWarning about adding 'line'. */ |
|
3 #include "frameobject.h" |
|
4 |
|
5 #define MODULE_NAME "_warnings" |
|
6 #define DEFAULT_ACTION_NAME "default_action" |
|
7 |
|
8 PyDoc_STRVAR(warnings__doc__, |
|
9 MODULE_NAME " provides basic warning filtering support.\n" |
|
10 "It is a helper module to speed up interpreter start-up."); |
|
11 |
|
12 /* Both 'filters' and 'onceregistry' can be set in warnings.py; |
|
13 get_warnings_attr() will reset these variables accordingly. */ |
|
14 static PyObject *_filters; /* List */ |
|
15 static PyObject *_once_registry; /* Dict */ |
|
16 |
|
17 |
|
18 static int |
|
19 check_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 */ |
|
39 static PyObject * |
|
40 get_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) { |
|
48 warnings_str = PyString_InternFromString("warnings"); |
|
49 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 |
|
65 static PyObject * |
|
66 get_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. */ |
|
83 static const char * |
|
84 get_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)) |
|
136 return PyString_AsString(action); |
|
137 } |
|
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) |
|
148 return PyString_AsString(action); |
|
149 |
|
150 PyErr_SetString(PyExc_ValueError, |
|
151 MODULE_NAME "." DEFAULT_ACTION_NAME " not found"); |
|
152 return NULL; |
|
153 } |
|
154 |
|
155 static int |
|
156 already_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. */ |
|
177 static PyObject * |
|
178 normalize_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) |
|
188 return PyString_FromString("<unknown>"); |
|
189 |
|
190 mod_str = PyString_AsString(filename); |
|
191 if (mod_str == NULL) |
|
192 return NULL; |
|
193 len = PyString_Size(filename); |
|
194 if (len < 0) |
|
195 return NULL; |
|
196 if (len >= 3 && |
|
197 strncmp(mod_str + (len - 3), ".py", 3) == 0) { |
|
198 module = PyString_FromStringAndSize(mod_str, len-3); |
|
199 } |
|
200 else { |
|
201 module = filename; |
|
202 Py_INCREF(module); |
|
203 } |
|
204 return module; |
|
205 } |
|
206 |
|
207 static int |
|
208 update_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 |
|
229 static void |
|
230 show_warning(PyObject *filename, int lineno, PyObject *text, PyObject |
|
231 *category, PyObject *sourceline) |
|
232 { |
|
233 PyObject *f_stderr; |
|
234 PyObject *name; |
|
235 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" */ |
|
260 if (sourceline) { |
|
261 char *source_line_str = PyString_AS_STRING(sourceline); |
|
262 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 |
|
270 _Py_DisplaySourceLine(f_stderr, PyString_AS_STRING(filename), |
|
271 lineno, 2); |
|
272 PyErr_Clear(); |
|
273 } |
|
274 |
|
275 static PyObject * |
|
276 warn_explicit(PyObject *category, PyObject *message, |
|
277 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; |
|
284 |
|
285 if (registry && !PyDict_Check(registry) && (registry != Py_None)) { |
|
286 PyErr_SetString(PyExc_TypeError, "'registry' must be a dict"); |
|
287 return NULL; |
|
288 } |
|
289 |
|
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); |
|
312 if (message == NULL) |
|
313 goto cleanup; |
|
314 } |
|
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 |
|
325 if ((registry != NULL) && (registry != Py_None)) { |
|
326 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) { |
|
347 if (registry != NULL && registry != Py_None && |
|
348 PyDict_SetItem(registry, key, Py_True) < 0) |
|
349 goto cleanup; |
|
350 else if (strcmp(action, "ignore") == 0) |
|
351 goto return_none; |
|
352 else if (strcmp(action, "once") == 0) { |
|
353 if (registry == NULL || registry == Py_None) { |
|
354 registry = get_once_registry(); |
|
355 if (registry == NULL) |
|
356 goto cleanup; |
|
357 } |
|
358 /* _once_registry[(text, category)] = 1 */ |
|
359 rc = update_registry(registry, text, category, 0); |
|
360 } |
|
361 else if (strcmp(action, "module") == 0) { |
|
362 /* registry[(text, category, 0)] = 1 */ |
|
363 if (registry != NULL && registry != Py_None) |
|
364 rc = update_registry(registry, text, category, 0); |
|
365 } |
|
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) |
|
371 err_str = PyString_AS_STRING(to_str); |
|
372 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 |
|
380 if (rc == 1) /* Already warned for this module. */ |
|
381 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 { |
|
390 const char *msg = "functions overriding warnings.showwarning() " |
|
391 "must support the 'line' argument"; |
|
392 const char *text_char = PyString_AS_STRING(text); |
|
393 |
|
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"); |
|
412 Py_DECREF(show_fxn); |
|
413 goto cleanup; |
|
414 } |
|
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)) { |
|
420 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 } |
|
428 } |
|
429 } |
|
430 res = PyObject_CallFunctionObjArgs(show_fxn, message, category, |
|
431 filename, lineno_obj, |
|
432 NULL); |
|
433 Py_DECREF(show_fxn); |
|
434 Py_XDECREF(res); |
|
435 if (res == NULL) |
|
436 goto cleanup; |
|
437 } |
|
438 } |
|
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); |
|
452 Py_XDECREF(message); |
|
453 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 */ |
|
458 static int |
|
459 setup_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; |
|
466 while (--stack_level > 0 && f != NULL) |
|
467 f = f->f_back; |
|
468 |
|
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) { |
|
501 *module = PyString_FromString("<string>"); |
|
502 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) { |
|
511 Py_ssize_t len = PyString_Size(*filename); |
|
512 const char *file_str = PyString_AsString(*filename); |
|
513 if (file_str == NULL || (len < 0 && PyErr_Occurred())) |
|
514 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' || |
|
522 tolower(file_str[len-1]) == 'o')) |
|
523 { |
|
524 *filename = PyString_FromStringAndSize(file_str, len-1); |
|
525 if (*filename == NULL) |
|
526 goto handle_error; |
|
527 } |
|
528 else |
|
529 Py_INCREF(*filename); |
|
530 } |
|
531 else { |
|
532 const char *module_str = PyString_AsString(*module); |
|
533 if (module_str && strcmp(module_str, "__main__") == 0) { |
|
534 PyObject *argv = PySys_GetObject("argv"); |
|
535 if (argv != NULL && PyList_Size(argv) > 0) { |
|
536 int is_true; |
|
537 *filename = PyList_GetItem(argv, 0); |
|
538 Py_INCREF(*filename); |
|
539 /* 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); |
|
547 *filename = PyString_FromString("__main__"); |
|
548 if (*filename == NULL) |
|
549 goto handle_error; |
|
550 } |
|
551 } |
|
552 else { |
|
553 /* embedded interpreters don't have sys.argv, see bug #839151 */ |
|
554 *filename = PyString_FromString("__main__"); |
|
555 if (*filename == NULL) |
|
556 goto handle_error; |
|
557 } |
|
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 |
|
575 static PyObject * |
|
576 get_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 |
|
603 static PyObject * |
|
604 do_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, ®istry)) |
|
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 |
|
620 static PyObject * |
|
621 warnings_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 |
|
627 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list, |
|
628 &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 |
|
637 static PyObject * |
|
638 warnings_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 ®istry, &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) { |
|
666 get_source_name = PyString_InternFromString("get_source"); |
|
667 if (!get_source_name) |
|
668 return NULL; |
|
669 } |
|
670 if (splitlines_name == NULL) { |
|
671 splitlines_name = PyString_InternFromString("splitlines"); |
|
672 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. */ |
|
724 int |
|
725 PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) |
|
726 { |
|
727 PyObject *res; |
|
728 PyObject *message = PyString_FromString(text); |
|
729 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 |
|
749 PyAPI_FUNC(int) |
|
750 PyErr_Warn(PyObject *category, char *text) |
|
751 { |
|
752 return PyErr_WarnEx(category, text, 1); |
|
753 } |
|
754 |
|
755 /* Warning with explicit origin */ |
|
756 int |
|
757 PyErr_WarnExplicit(PyObject *category, const char *text, |
|
758 const char *filename_str, int lineno, |
|
759 const char *module_str, PyObject *registry) |
|
760 { |
|
761 PyObject *res; |
|
762 PyObject *message = PyString_FromString(text); |
|
763 PyObject *filename = PyString_FromString(filename_str); |
|
764 PyObject *module = NULL; |
|
765 int ret = -1; |
|
766 |
|
767 if (message == NULL || filename == NULL) |
|
768 goto exit; |
|
769 if (module_str != NULL) { |
|
770 module = PyString_FromString(module_str); |
|
771 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 |
|
792 PyDoc_STRVAR(warn_doc, |
|
793 "Issue a warning, or maybe ignore it or raise an exception."); |
|
794 |
|
795 PyDoc_STRVAR(warn_explicit_doc, |
|
796 "Low-level inferface to warnings functionality."); |
|
797 |
|
798 static 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}, |
|
803 /* XXX(brett.cannon): add showwarning? */ |
|
804 /* XXX(brett.cannon): Reasonable to add formatwarning? */ |
|
805 {NULL, NULL} /* sentinel */ |
|
806 }; |
|
807 |
|
808 |
|
809 static PyObject * |
|
810 create_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) { |
|
820 ignore_str = PyString_InternFromString("ignore"); |
|
821 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) { |
|
828 error_str = PyString_InternFromString("error"); |
|
829 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) { |
|
836 default_str = PyString_InternFromString("default"); |
|
837 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 |
|
855 static PyObject * |
|
856 init_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 |
|
886 PyMODINIT_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 |
|
909 default_action = PyString_InternFromString("default"); |
|
910 if (default_action == NULL) |
|
911 return; |
|
912 if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0) |
|
913 return; |
|
914 } |