]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | #include "Python.h"\r |
2 | #include "frameobject.h"\r | |
3 | \r | |
4 | #define MODULE_NAME "_warnings"\r | |
5 | \r | |
6 | PyDoc_STRVAR(warnings__doc__,\r | |
7 | MODULE_NAME " provides basic warning filtering support.\n"\r | |
8 | "It is a helper module to speed up interpreter start-up.");\r | |
9 | \r | |
10 | /* Both 'filters' and 'onceregistry' can be set in warnings.py;\r | |
11 | get_warnings_attr() will reset these variables accordingly. */\r | |
12 | static PyObject *_filters; /* List */\r | |
13 | static PyObject *_once_registry; /* Dict */\r | |
14 | static PyObject *_default_action; /* String */\r | |
15 | \r | |
16 | \r | |
17 | static int\r | |
18 | check_matched(PyObject *obj, PyObject *arg)\r | |
19 | {\r | |
20 | PyObject *result;\r | |
21 | int rc;\r | |
22 | \r | |
23 | if (obj == Py_None)\r | |
24 | return 1;\r | |
25 | result = PyObject_CallMethod(obj, "match", "O", arg);\r | |
26 | if (result == NULL)\r | |
27 | return -1;\r | |
28 | \r | |
29 | rc = PyObject_IsTrue(result);\r | |
30 | Py_DECREF(result);\r | |
31 | return rc;\r | |
32 | }\r | |
33 | \r | |
34 | /*\r | |
35 | Returns a new reference.\r | |
36 | A NULL return value can mean false or an error.\r | |
37 | */\r | |
38 | static PyObject *\r | |
39 | get_warnings_attr(const char *attr)\r | |
40 | {\r | |
41 | static PyObject *warnings_str = NULL;\r | |
42 | PyObject *all_modules;\r | |
43 | PyObject *warnings_module;\r | |
44 | int result;\r | |
45 | \r | |
46 | if (warnings_str == NULL) {\r | |
47 | warnings_str = PyString_InternFromString("warnings");\r | |
48 | if (warnings_str == NULL)\r | |
49 | return NULL;\r | |
50 | }\r | |
51 | \r | |
52 | all_modules = PyImport_GetModuleDict();\r | |
53 | result = PyDict_Contains(all_modules, warnings_str);\r | |
54 | if (result == -1 || result == 0)\r | |
55 | return NULL;\r | |
56 | \r | |
57 | warnings_module = PyDict_GetItem(all_modules, warnings_str);\r | |
58 | if (!PyObject_HasAttrString(warnings_module, attr))\r | |
59 | return NULL;\r | |
60 | return PyObject_GetAttrString(warnings_module, attr);\r | |
61 | }\r | |
62 | \r | |
63 | \r | |
64 | static PyObject *\r | |
65 | get_once_registry(void)\r | |
66 | {\r | |
67 | PyObject *registry;\r | |
68 | \r | |
69 | registry = get_warnings_attr("onceregistry");\r | |
70 | if (registry == NULL) {\r | |
71 | if (PyErr_Occurred())\r | |
72 | return NULL;\r | |
73 | return _once_registry;\r | |
74 | }\r | |
75 | Py_DECREF(_once_registry);\r | |
76 | _once_registry = registry;\r | |
77 | return registry;\r | |
78 | }\r | |
79 | \r | |
80 | \r | |
81 | static PyObject *\r | |
82 | get_default_action(void)\r | |
83 | {\r | |
84 | PyObject *default_action;\r | |
85 | \r | |
86 | default_action = get_warnings_attr("defaultaction");\r | |
87 | if (default_action == NULL) {\r | |
88 | if (PyErr_Occurred()) {\r | |
89 | return NULL;\r | |
90 | }\r | |
91 | return _default_action;\r | |
92 | }\r | |
93 | \r | |
94 | Py_DECREF(_default_action);\r | |
95 | _default_action = default_action;\r | |
96 | return default_action;\r | |
97 | }\r | |
98 | \r | |
99 | \r | |
100 | /* The item is a borrowed reference. */\r | |
101 | static const char *\r | |
102 | get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,\r | |
103 | PyObject *module, PyObject **item)\r | |
104 | {\r | |
105 | PyObject *action;\r | |
106 | Py_ssize_t i;\r | |
107 | PyObject *warnings_filters;\r | |
108 | \r | |
109 | warnings_filters = get_warnings_attr("filters");\r | |
110 | if (warnings_filters == NULL) {\r | |
111 | if (PyErr_Occurred())\r | |
112 | return NULL;\r | |
113 | }\r | |
114 | else {\r | |
115 | Py_DECREF(_filters);\r | |
116 | _filters = warnings_filters;\r | |
117 | }\r | |
118 | \r | |
119 | if (!PyList_Check(_filters)) {\r | |
120 | PyErr_SetString(PyExc_ValueError,\r | |
121 | MODULE_NAME ".filters must be a list");\r | |
122 | return NULL;\r | |
123 | }\r | |
124 | \r | |
125 | /* _filters could change while we are iterating over it. */\r | |
126 | for (i = 0; i < PyList_GET_SIZE(_filters); i++) {\r | |
127 | PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;\r | |
128 | Py_ssize_t ln;\r | |
129 | int is_subclass, good_msg, good_mod;\r | |
130 | \r | |
131 | tmp_item = *item = PyList_GET_ITEM(_filters, i);\r | |
132 | if (PyTuple_Size(tmp_item) != 5) {\r | |
133 | PyErr_Format(PyExc_ValueError,\r | |
134 | MODULE_NAME ".filters item %zd isn't a 5-tuple", i);\r | |
135 | return NULL;\r | |
136 | }\r | |
137 | \r | |
138 | /* Python code: action, msg, cat, mod, ln = item */\r | |
139 | action = PyTuple_GET_ITEM(tmp_item, 0);\r | |
140 | msg = PyTuple_GET_ITEM(tmp_item, 1);\r | |
141 | cat = PyTuple_GET_ITEM(tmp_item, 2);\r | |
142 | mod = PyTuple_GET_ITEM(tmp_item, 3);\r | |
143 | ln_obj = PyTuple_GET_ITEM(tmp_item, 4);\r | |
144 | \r | |
145 | good_msg = check_matched(msg, text);\r | |
146 | good_mod = check_matched(mod, module);\r | |
147 | is_subclass = PyObject_IsSubclass(category, cat);\r | |
148 | ln = PyInt_AsSsize_t(ln_obj);\r | |
149 | if (good_msg == -1 || good_mod == -1 || is_subclass == -1 ||\r | |
150 | (ln == -1 && PyErr_Occurred()))\r | |
151 | return NULL;\r | |
152 | \r | |
153 | if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))\r | |
154 | return PyString_AsString(action);\r | |
155 | }\r | |
156 | \r | |
157 | action = get_default_action();\r | |
158 | if (action != NULL) {\r | |
159 | return PyString_AsString(action);\r | |
160 | }\r | |
161 | \r | |
162 | PyErr_SetString(PyExc_ValueError,\r | |
163 | MODULE_NAME ".defaultaction not found");\r | |
164 | return NULL;\r | |
165 | }\r | |
166 | \r | |
167 | \r | |
168 | static int\r | |
169 | already_warned(PyObject *registry, PyObject *key, int should_set)\r | |
170 | {\r | |
171 | PyObject *already_warned;\r | |
172 | \r | |
173 | if (key == NULL)\r | |
174 | return -1;\r | |
175 | \r | |
176 | already_warned = PyDict_GetItem(registry, key);\r | |
177 | if (already_warned != NULL) {\r | |
178 | int rc = PyObject_IsTrue(already_warned);\r | |
179 | if (rc != 0)\r | |
180 | return rc;\r | |
181 | }\r | |
182 | \r | |
183 | /* This warning wasn't found in the registry, set it. */\r | |
184 | if (should_set)\r | |
185 | return PyDict_SetItem(registry, key, Py_True);\r | |
186 | return 0;\r | |
187 | }\r | |
188 | \r | |
189 | /* New reference. */\r | |
190 | static PyObject *\r | |
191 | normalize_module(PyObject *filename)\r | |
192 | {\r | |
193 | PyObject *module;\r | |
194 | const char *mod_str;\r | |
195 | Py_ssize_t len;\r | |
196 | \r | |
197 | int rc = PyObject_IsTrue(filename);\r | |
198 | if (rc == -1)\r | |
199 | return NULL;\r | |
200 | else if (rc == 0)\r | |
201 | return PyString_FromString("<unknown>");\r | |
202 | \r | |
203 | mod_str = PyString_AsString(filename);\r | |
204 | if (mod_str == NULL)\r | |
205 | return NULL;\r | |
206 | len = PyString_Size(filename);\r | |
207 | if (len < 0)\r | |
208 | return NULL;\r | |
209 | if (len >= 3 &&\r | |
210 | strncmp(mod_str + (len - 3), ".py", 3) == 0) {\r | |
211 | module = PyString_FromStringAndSize(mod_str, len-3);\r | |
212 | }\r | |
213 | else {\r | |
214 | module = filename;\r | |
215 | Py_INCREF(module);\r | |
216 | }\r | |
217 | return module;\r | |
218 | }\r | |
219 | \r | |
220 | static int\r | |
221 | update_registry(PyObject *registry, PyObject *text, PyObject *category,\r | |
222 | int add_zero)\r | |
223 | {\r | |
224 | PyObject *altkey, *zero = NULL;\r | |
225 | int rc;\r | |
226 | \r | |
227 | if (add_zero) {\r | |
228 | zero = PyInt_FromLong(0);\r | |
229 | if (zero == NULL)\r | |
230 | return -1;\r | |
231 | altkey = PyTuple_Pack(3, text, category, zero);\r | |
232 | }\r | |
233 | else\r | |
234 | altkey = PyTuple_Pack(2, text, category);\r | |
235 | \r | |
236 | rc = already_warned(registry, altkey, 1);\r | |
237 | Py_XDECREF(zero);\r | |
238 | Py_XDECREF(altkey);\r | |
239 | return rc;\r | |
240 | }\r | |
241 | \r | |
242 | static void\r | |
243 | show_warning(PyObject *filename, int lineno, PyObject *text, PyObject\r | |
244 | *category, PyObject *sourceline)\r | |
245 | {\r | |
246 | PyObject *f_stderr;\r | |
247 | PyObject *name;\r | |
248 | char lineno_str[128];\r | |
249 | \r | |
250 | PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);\r | |
251 | \r | |
252 | name = PyObject_GetAttrString(category, "__name__");\r | |
253 | if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */\r | |
254 | return;\r | |
255 | \r | |
256 | f_stderr = PySys_GetObject("stderr");\r | |
257 | if (f_stderr == NULL) {\r | |
258 | fprintf(stderr, "lost sys.stderr\n");\r | |
259 | Py_DECREF(name);\r | |
260 | return;\r | |
261 | }\r | |
262 | \r | |
263 | /* Print "filename:lineno: category: text\n" */\r | |
264 | PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW);\r | |
265 | PyFile_WriteString(lineno_str, f_stderr);\r | |
266 | PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW);\r | |
267 | PyFile_WriteString(": ", f_stderr);\r | |
268 | PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW);\r | |
269 | PyFile_WriteString("\n", f_stderr);\r | |
270 | Py_XDECREF(name);\r | |
271 | \r | |
272 | /* Print " source_line\n" */\r | |
273 | if (sourceline) {\r | |
274 | char *source_line_str = PyString_AS_STRING(sourceline);\r | |
275 | while (*source_line_str == ' ' || *source_line_str == '\t' ||\r | |
276 | *source_line_str == '\014')\r | |
277 | source_line_str++;\r | |
278 | \r | |
279 | PyFile_WriteString(source_line_str, f_stderr);\r | |
280 | PyFile_WriteString("\n", f_stderr);\r | |
281 | }\r | |
282 | else\r | |
283 | _Py_DisplaySourceLine(f_stderr, PyString_AS_STRING(filename),\r | |
284 | lineno, 2);\r | |
285 | PyErr_Clear();\r | |
286 | }\r | |
287 | \r | |
288 | static PyObject *\r | |
289 | warn_explicit(PyObject *category, PyObject *message,\r | |
290 | PyObject *filename, int lineno,\r | |
291 | PyObject *module, PyObject *registry, PyObject *sourceline)\r | |
292 | {\r | |
293 | PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;\r | |
294 | PyObject *item = Py_None;\r | |
295 | const char *action;\r | |
296 | int rc;\r | |
297 | \r | |
298 | if (registry && !PyDict_Check(registry) && (registry != Py_None)) {\r | |
299 | PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");\r | |
300 | return NULL;\r | |
301 | }\r | |
302 | \r | |
303 | /* Normalize module. */\r | |
304 | if (module == NULL) {\r | |
305 | module = normalize_module(filename);\r | |
306 | if (module == NULL)\r | |
307 | return NULL;\r | |
308 | }\r | |
309 | else\r | |
310 | Py_INCREF(module);\r | |
311 | \r | |
312 | /* Normalize message. */\r | |
313 | Py_INCREF(message); /* DECREF'ed in cleanup. */\r | |
314 | rc = PyObject_IsInstance(message, PyExc_Warning);\r | |
315 | if (rc == -1) {\r | |
316 | goto cleanup;\r | |
317 | }\r | |
318 | if (rc == 1) {\r | |
319 | text = PyObject_Str(message);\r | |
320 | if (text == NULL)\r | |
321 | goto cleanup;\r | |
322 | category = (PyObject*)message->ob_type;\r | |
323 | }\r | |
324 | else {\r | |
325 | text = message;\r | |
326 | message = PyObject_CallFunction(category, "O", message);\r | |
327 | if (message == NULL)\r | |
328 | goto cleanup;\r | |
329 | }\r | |
330 | \r | |
331 | lineno_obj = PyInt_FromLong(lineno);\r | |
332 | if (lineno_obj == NULL)\r | |
333 | goto cleanup;\r | |
334 | \r | |
335 | /* Create key. */\r | |
336 | key = PyTuple_Pack(3, text, category, lineno_obj);\r | |
337 | if (key == NULL)\r | |
338 | goto cleanup;\r | |
339 | \r | |
340 | if ((registry != NULL) && (registry != Py_None)) {\r | |
341 | rc = already_warned(registry, key, 0);\r | |
342 | if (rc == -1)\r | |
343 | goto cleanup;\r | |
344 | else if (rc == 1)\r | |
345 | goto return_none;\r | |
346 | /* Else this warning hasn't been generated before. */\r | |
347 | }\r | |
348 | \r | |
349 | action = get_filter(category, text, lineno, module, &item);\r | |
350 | if (action == NULL)\r | |
351 | goto cleanup;\r | |
352 | \r | |
353 | if (strcmp(action, "error") == 0) {\r | |
354 | PyErr_SetObject(category, message);\r | |
355 | goto cleanup;\r | |
356 | }\r | |
357 | \r | |
358 | /* Store in the registry that we've been here, *except* when the action\r | |
359 | is "always". */\r | |
360 | rc = 0;\r | |
361 | if (strcmp(action, "always") != 0) {\r | |
362 | if (registry != NULL && registry != Py_None &&\r | |
363 | PyDict_SetItem(registry, key, Py_True) < 0)\r | |
364 | goto cleanup;\r | |
365 | else if (strcmp(action, "ignore") == 0)\r | |
366 | goto return_none;\r | |
367 | else if (strcmp(action, "once") == 0) {\r | |
368 | if (registry == NULL || registry == Py_None) {\r | |
369 | registry = get_once_registry();\r | |
370 | if (registry == NULL)\r | |
371 | goto cleanup;\r | |
372 | }\r | |
373 | /* _once_registry[(text, category)] = 1 */\r | |
374 | rc = update_registry(registry, text, category, 0);\r | |
375 | }\r | |
376 | else if (strcmp(action, "module") == 0) {\r | |
377 | /* registry[(text, category, 0)] = 1 */\r | |
378 | if (registry != NULL && registry != Py_None)\r | |
379 | rc = update_registry(registry, text, category, 0);\r | |
380 | }\r | |
381 | else if (strcmp(action, "default") != 0) {\r | |
382 | PyObject *to_str = PyObject_Str(item);\r | |
383 | const char *err_str = "???";\r | |
384 | \r | |
385 | if (to_str != NULL)\r | |
386 | err_str = PyString_AS_STRING(to_str);\r | |
387 | PyErr_Format(PyExc_RuntimeError,\r | |
388 | "Unrecognized action (%s) in warnings.filters:\n %s",\r | |
389 | action, err_str);\r | |
390 | Py_XDECREF(to_str);\r | |
391 | goto cleanup;\r | |
392 | }\r | |
393 | }\r | |
394 | \r | |
395 | if (rc == 1) /* Already warned for this module. */\r | |
396 | goto return_none;\r | |
397 | if (rc == 0) {\r | |
398 | PyObject *show_fxn = get_warnings_attr("showwarning");\r | |
399 | if (show_fxn == NULL) {\r | |
400 | if (PyErr_Occurred())\r | |
401 | goto cleanup;\r | |
402 | show_warning(filename, lineno, text, category, sourceline);\r | |
403 | }\r | |
404 | else {\r | |
405 | PyObject *res;\r | |
406 | \r | |
407 | if (!PyMethod_Check(show_fxn) && !PyFunction_Check(show_fxn)) {\r | |
408 | PyErr_SetString(PyExc_TypeError,\r | |
409 | "warnings.showwarning() must be set to a "\r | |
410 | "function or method");\r | |
411 | Py_DECREF(show_fxn);\r | |
412 | goto cleanup;\r | |
413 | }\r | |
414 | \r | |
415 | res = PyObject_CallFunctionObjArgs(show_fxn, message, category,\r | |
416 | filename, lineno_obj,\r | |
417 | NULL);\r | |
418 | Py_DECREF(show_fxn);\r | |
419 | Py_XDECREF(res);\r | |
420 | if (res == NULL)\r | |
421 | goto cleanup;\r | |
422 | }\r | |
423 | }\r | |
424 | else /* if (rc == -1) */\r | |
425 | goto cleanup;\r | |
426 | \r | |
427 | return_none:\r | |
428 | result = Py_None;\r | |
429 | Py_INCREF(result);\r | |
430 | \r | |
431 | cleanup:\r | |
432 | Py_XDECREF(key);\r | |
433 | Py_XDECREF(text);\r | |
434 | Py_XDECREF(lineno_obj);\r | |
435 | Py_DECREF(module);\r | |
436 | Py_XDECREF(message);\r | |
437 | return result; /* Py_None or NULL. */\r | |
438 | }\r | |
439 | \r | |
440 | /* filename, module, and registry are new refs, globals is borrowed */\r | |
441 | /* Returns 0 on error (no new refs), 1 on success */\r | |
442 | static int\r | |
443 | setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,\r | |
444 | PyObject **module, PyObject **registry)\r | |
445 | {\r | |
446 | PyObject *globals;\r | |
447 | \r | |
448 | /* Setup globals and lineno. */\r | |
449 | PyFrameObject *f = PyThreadState_GET()->frame;\r | |
450 | while (--stack_level > 0 && f != NULL)\r | |
451 | f = f->f_back;\r | |
452 | \r | |
453 | if (f == NULL) {\r | |
454 | globals = PyThreadState_Get()->interp->sysdict;\r | |
455 | *lineno = 1;\r | |
456 | }\r | |
457 | else {\r | |
458 | globals = f->f_globals;\r | |
459 | *lineno = PyFrame_GetLineNumber(f);\r | |
460 | }\r | |
461 | \r | |
462 | *module = NULL;\r | |
463 | \r | |
464 | /* Setup registry. */\r | |
465 | assert(globals != NULL);\r | |
466 | assert(PyDict_Check(globals));\r | |
467 | *registry = PyDict_GetItemString(globals, "__warningregistry__");\r | |
468 | if (*registry == NULL) {\r | |
469 | int rc;\r | |
470 | \r | |
471 | *registry = PyDict_New();\r | |
472 | if (*registry == NULL)\r | |
473 | return 0;\r | |
474 | \r | |
475 | rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);\r | |
476 | if (rc < 0)\r | |
477 | goto handle_error;\r | |
478 | }\r | |
479 | else\r | |
480 | Py_INCREF(*registry);\r | |
481 | \r | |
482 | /* Setup module. */\r | |
483 | *module = PyDict_GetItemString(globals, "__name__");\r | |
484 | if (*module == NULL) {\r | |
485 | *module = PyString_FromString("<string>");\r | |
486 | if (*module == NULL)\r | |
487 | goto handle_error;\r | |
488 | }\r | |
489 | else\r | |
490 | Py_INCREF(*module);\r | |
491 | \r | |
492 | /* Setup filename. */\r | |
493 | *filename = PyDict_GetItemString(globals, "__file__");\r | |
494 | if (*filename != NULL) {\r | |
495 | Py_ssize_t len = PyString_Size(*filename);\r | |
496 | const char *file_str = PyString_AsString(*filename);\r | |
497 | if (file_str == NULL || (len < 0 && PyErr_Occurred()))\r | |
498 | goto handle_error;\r | |
499 | \r | |
500 | /* if filename.lower().endswith((".pyc", ".pyo")): */\r | |
501 | if (len >= 4 &&\r | |
502 | file_str[len-4] == '.' &&\r | |
503 | tolower(file_str[len-3]) == 'p' &&\r | |
504 | tolower(file_str[len-2]) == 'y' &&\r | |
505 | (tolower(file_str[len-1]) == 'c' ||\r | |
506 | tolower(file_str[len-1]) == 'o'))\r | |
507 | {\r | |
508 | *filename = PyString_FromStringAndSize(file_str, len-1);\r | |
509 | if (*filename == NULL)\r | |
510 | goto handle_error;\r | |
511 | }\r | |
512 | else\r | |
513 | Py_INCREF(*filename);\r | |
514 | }\r | |
515 | else {\r | |
516 | const char *module_str = PyString_AsString(*module);\r | |
517 | if (module_str && strcmp(module_str, "__main__") == 0) {\r | |
518 | PyObject *argv = PySys_GetObject("argv");\r | |
519 | if (argv != NULL && PyList_Size(argv) > 0) {\r | |
520 | int is_true;\r | |
521 | *filename = PyList_GetItem(argv, 0);\r | |
522 | Py_INCREF(*filename);\r | |
523 | /* If sys.argv[0] is false, then use '__main__'. */\r | |
524 | is_true = PyObject_IsTrue(*filename);\r | |
525 | if (is_true < 0) {\r | |
526 | Py_DECREF(*filename);\r | |
527 | goto handle_error;\r | |
528 | }\r | |
529 | else if (!is_true) {\r | |
530 | Py_DECREF(*filename);\r | |
531 | *filename = PyString_FromString("__main__");\r | |
532 | if (*filename == NULL)\r | |
533 | goto handle_error;\r | |
534 | }\r | |
535 | }\r | |
536 | else {\r | |
537 | /* embedded interpreters don't have sys.argv, see bug #839151 */\r | |
538 | *filename = PyString_FromString("__main__");\r | |
539 | if (*filename == NULL)\r | |
540 | goto handle_error;\r | |
541 | }\r | |
542 | }\r | |
543 | if (*filename == NULL) {\r | |
544 | *filename = *module;\r | |
545 | Py_INCREF(*filename);\r | |
546 | }\r | |
547 | }\r | |
548 | \r | |
549 | return 1;\r | |
550 | \r | |
551 | handle_error:\r | |
552 | /* filename not XDECREF'ed here as there is no way to jump here with a\r | |
553 | dangling reference. */\r | |
554 | Py_XDECREF(*registry);\r | |
555 | Py_XDECREF(*module);\r | |
556 | return 0;\r | |
557 | }\r | |
558 | \r | |
559 | static PyObject *\r | |
560 | get_category(PyObject *message, PyObject *category)\r | |
561 | {\r | |
562 | int rc;\r | |
563 | \r | |
564 | /* Get category. */\r | |
565 | rc = PyObject_IsInstance(message, PyExc_Warning);\r | |
566 | if (rc == -1)\r | |
567 | return NULL;\r | |
568 | \r | |
569 | if (rc == 1)\r | |
570 | category = (PyObject*)message->ob_type;\r | |
571 | else if (category == NULL)\r | |
572 | category = PyExc_UserWarning;\r | |
573 | \r | |
574 | /* Validate category. */\r | |
575 | rc = PyObject_IsSubclass(category, PyExc_Warning);\r | |
576 | if (rc == -1)\r | |
577 | return NULL;\r | |
578 | if (rc == 0) {\r | |
579 | PyErr_SetString(PyExc_ValueError,\r | |
580 | "category is not a subclass of Warning");\r | |
581 | return NULL;\r | |
582 | }\r | |
583 | \r | |
584 | return category;\r | |
585 | }\r | |
586 | \r | |
587 | static PyObject *\r | |
588 | do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)\r | |
589 | {\r | |
590 | PyObject *filename, *module, *registry, *res;\r | |
591 | int lineno;\r | |
592 | \r | |
593 | if (!setup_context(stack_level, &filename, &lineno, &module, ®istry))\r | |
594 | return NULL;\r | |
595 | \r | |
596 | res = warn_explicit(category, message, filename, lineno, module, registry,\r | |
597 | NULL);\r | |
598 | Py_DECREF(filename);\r | |
599 | Py_DECREF(registry);\r | |
600 | Py_DECREF(module);\r | |
601 | return res;\r | |
602 | }\r | |
603 | \r | |
604 | static PyObject *\r | |
605 | warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)\r | |
606 | {\r | |
607 | static char *kw_list[] = { "message", "category", "stacklevel", 0 };\r | |
608 | PyObject *message, *category = NULL;\r | |
609 | Py_ssize_t stack_level = 1;\r | |
610 | \r | |
611 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,\r | |
612 | &message, &category, &stack_level))\r | |
613 | return NULL;\r | |
614 | \r | |
615 | category = get_category(message, category);\r | |
616 | if (category == NULL)\r | |
617 | return NULL;\r | |
618 | return do_warn(message, category, stack_level);\r | |
619 | }\r | |
620 | \r | |
621 | static PyObject *\r | |
622 | warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)\r | |
623 | {\r | |
624 | static char *kwd_list[] = {"message", "category", "filename", "lineno",\r | |
625 | "module", "registry", "module_globals", 0};\r | |
626 | PyObject *message;\r | |
627 | PyObject *category;\r | |
628 | PyObject *filename;\r | |
629 | int lineno;\r | |
630 | PyObject *module = NULL;\r | |
631 | PyObject *registry = NULL;\r | |
632 | PyObject *module_globals = NULL;\r | |
633 | \r | |
634 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",\r | |
635 | kwd_list, &message, &category, &filename, &lineno, &module,\r | |
636 | ®istry, &module_globals))\r | |
637 | return NULL;\r | |
638 | \r | |
639 | if (module_globals) {\r | |
640 | static PyObject *get_source_name = NULL;\r | |
641 | static PyObject *splitlines_name = NULL;\r | |
642 | PyObject *loader;\r | |
643 | PyObject *module_name;\r | |
644 | PyObject *source;\r | |
645 | PyObject *source_list;\r | |
646 | PyObject *source_line;\r | |
647 | PyObject *returned;\r | |
648 | \r | |
649 | if (get_source_name == NULL) {\r | |
650 | get_source_name = PyString_InternFromString("get_source");\r | |
651 | if (!get_source_name)\r | |
652 | return NULL;\r | |
653 | }\r | |
654 | if (splitlines_name == NULL) {\r | |
655 | splitlines_name = PyString_InternFromString("splitlines");\r | |
656 | if (!splitlines_name)\r | |
657 | return NULL;\r | |
658 | }\r | |
659 | \r | |
660 | /* Check/get the requisite pieces needed for the loader. */\r | |
661 | loader = PyDict_GetItemString(module_globals, "__loader__");\r | |
662 | module_name = PyDict_GetItemString(module_globals, "__name__");\r | |
663 | \r | |
664 | if (loader == NULL || module_name == NULL)\r | |
665 | goto standard_call;\r | |
666 | \r | |
667 | /* Make sure the loader implements the optional get_source() method. */\r | |
668 | if (!PyObject_HasAttrString(loader, "get_source"))\r | |
669 | goto standard_call;\r | |
670 | /* Call get_source() to get the source code. */\r | |
671 | source = PyObject_CallMethodObjArgs(loader, get_source_name,\r | |
672 | module_name, NULL);\r | |
673 | if (!source)\r | |
674 | return NULL;\r | |
675 | else if (source == Py_None) {\r | |
676 | Py_DECREF(Py_None);\r | |
677 | goto standard_call;\r | |
678 | }\r | |
679 | \r | |
680 | /* Split the source into lines. */\r | |
681 | source_list = PyObject_CallMethodObjArgs(source, splitlines_name,\r | |
682 | NULL);\r | |
683 | Py_DECREF(source);\r | |
684 | if (!source_list)\r | |
685 | return NULL;\r | |
686 | \r | |
687 | /* Get the source line. */\r | |
688 | source_line = PyList_GetItem(source_list, lineno-1);\r | |
689 | if (!source_line) {\r | |
690 | Py_DECREF(source_list);\r | |
691 | return NULL;\r | |
692 | }\r | |
693 | \r | |
694 | /* Handle the warning. */\r | |
695 | returned = warn_explicit(category, message, filename, lineno, module,\r | |
696 | registry, source_line);\r | |
697 | Py_DECREF(source_list);\r | |
698 | return returned;\r | |
699 | }\r | |
700 | \r | |
701 | standard_call:\r | |
702 | return warn_explicit(category, message, filename, lineno, module,\r | |
703 | registry, NULL);\r | |
704 | }\r | |
705 | \r | |
706 | \r | |
707 | /* Function to issue a warning message; may raise an exception. */\r | |
708 | int\r | |
709 | PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)\r | |
710 | {\r | |
711 | PyObject *res;\r | |
712 | PyObject *message = PyString_FromString(text);\r | |
713 | if (message == NULL)\r | |
714 | return -1;\r | |
715 | \r | |
716 | if (category == NULL)\r | |
717 | category = PyExc_RuntimeWarning;\r | |
718 | \r | |
719 | res = do_warn(message, category, stack_level);\r | |
720 | Py_DECREF(message);\r | |
721 | if (res == NULL)\r | |
722 | return -1;\r | |
723 | Py_DECREF(res);\r | |
724 | \r | |
725 | return 0;\r | |
726 | }\r | |
727 | \r | |
728 | /* PyErr_Warn is only for backwards compatibility and will be removed.\r | |
729 | Use PyErr_WarnEx instead. */\r | |
730 | \r | |
731 | #undef PyErr_Warn\r | |
732 | \r | |
733 | PyAPI_FUNC(int)\r | |
734 | PyErr_Warn(PyObject *category, char *text)\r | |
735 | {\r | |
736 | return PyErr_WarnEx(category, text, 1);\r | |
737 | }\r | |
738 | \r | |
739 | /* Warning with explicit origin */\r | |
740 | int\r | |
741 | PyErr_WarnExplicit(PyObject *category, const char *text,\r | |
742 | const char *filename_str, int lineno,\r | |
743 | const char *module_str, PyObject *registry)\r | |
744 | {\r | |
745 | PyObject *res;\r | |
746 | PyObject *message = PyString_FromString(text);\r | |
747 | PyObject *filename = PyString_FromString(filename_str);\r | |
748 | PyObject *module = NULL;\r | |
749 | int ret = -1;\r | |
750 | \r | |
751 | if (message == NULL || filename == NULL)\r | |
752 | goto exit;\r | |
753 | if (module_str != NULL) {\r | |
754 | module = PyString_FromString(module_str);\r | |
755 | if (module == NULL)\r | |
756 | goto exit;\r | |
757 | }\r | |
758 | \r | |
759 | if (category == NULL)\r | |
760 | category = PyExc_RuntimeWarning;\r | |
761 | res = warn_explicit(category, message, filename, lineno, module, registry,\r | |
762 | NULL);\r | |
763 | if (res == NULL)\r | |
764 | goto exit;\r | |
765 | Py_DECREF(res);\r | |
766 | ret = 0;\r | |
767 | \r | |
768 | exit:\r | |
769 | Py_XDECREF(message);\r | |
770 | Py_XDECREF(module);\r | |
771 | Py_XDECREF(filename);\r | |
772 | return ret;\r | |
773 | }\r | |
774 | \r | |
775 | \r | |
776 | PyDoc_STRVAR(warn_doc,\r | |
777 | "Issue a warning, or maybe ignore it or raise an exception.");\r | |
778 | \r | |
779 | PyDoc_STRVAR(warn_explicit_doc,\r | |
780 | "Low-level inferface to warnings functionality.");\r | |
781 | \r | |
782 | static PyMethodDef warnings_functions[] = {\r | |
783 | {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,\r | |
784 | warn_doc},\r | |
785 | {"warn_explicit", (PyCFunction)warnings_warn_explicit,\r | |
786 | METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},\r | |
787 | /* XXX(brett.cannon): add showwarning? */\r | |
788 | /* XXX(brett.cannon): Reasonable to add formatwarning? */\r | |
789 | {NULL, NULL} /* sentinel */\r | |
790 | };\r | |
791 | \r | |
792 | \r | |
793 | static PyObject *\r | |
794 | create_filter(PyObject *category, const char *action)\r | |
795 | {\r | |
796 | static PyObject *ignore_str = NULL;\r | |
797 | static PyObject *error_str = NULL;\r | |
798 | static PyObject *default_str = NULL;\r | |
799 | PyObject *action_obj = NULL;\r | |
800 | PyObject *lineno, *result;\r | |
801 | \r | |
802 | if (!strcmp(action, "ignore")) {\r | |
803 | if (ignore_str == NULL) {\r | |
804 | ignore_str = PyString_InternFromString("ignore");\r | |
805 | if (ignore_str == NULL)\r | |
806 | return NULL;\r | |
807 | }\r | |
808 | action_obj = ignore_str;\r | |
809 | }\r | |
810 | else if (!strcmp(action, "error")) {\r | |
811 | if (error_str == NULL) {\r | |
812 | error_str = PyString_InternFromString("error");\r | |
813 | if (error_str == NULL)\r | |
814 | return NULL;\r | |
815 | }\r | |
816 | action_obj = error_str;\r | |
817 | }\r | |
818 | else if (!strcmp(action, "default")) {\r | |
819 | if (default_str == NULL) {\r | |
820 | default_str = PyString_InternFromString("default");\r | |
821 | if (default_str == NULL)\r | |
822 | return NULL;\r | |
823 | }\r | |
824 | action_obj = default_str;\r | |
825 | }\r | |
826 | else {\r | |
827 | Py_FatalError("unknown action");\r | |
828 | }\r | |
829 | \r | |
830 | /* This assumes the line number is zero for now. */\r | |
831 | lineno = PyInt_FromLong(0);\r | |
832 | if (lineno == NULL)\r | |
833 | return NULL;\r | |
834 | result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);\r | |
835 | Py_DECREF(lineno);\r | |
836 | return result;\r | |
837 | }\r | |
838 | \r | |
839 | static PyObject *\r | |
840 | init_filters(void)\r | |
841 | {\r | |
842 | /* Don't silence DeprecationWarning if -3 or -Q were used. */\r | |
843 | PyObject *filters = PyList_New(Py_Py3kWarningFlag ||\r | |
844 | Py_DivisionWarningFlag ? 3 : 4);\r | |
845 | unsigned int pos = 0; /* Post-incremented in each use. */\r | |
846 | unsigned int x;\r | |
847 | const char *bytes_action;\r | |
848 | \r | |
849 | if (filters == NULL)\r | |
850 | return NULL;\r | |
851 | \r | |
852 | /* If guard changes, make sure to update 'filters' initialization above. */\r | |
853 | if (!Py_Py3kWarningFlag && !Py_DivisionWarningFlag) {\r | |
854 | PyList_SET_ITEM(filters, pos++,\r | |
855 | create_filter(PyExc_DeprecationWarning, "ignore"));\r | |
856 | }\r | |
857 | PyList_SET_ITEM(filters, pos++,\r | |
858 | create_filter(PyExc_PendingDeprecationWarning, "ignore"));\r | |
859 | PyList_SET_ITEM(filters, pos++,\r | |
860 | create_filter(PyExc_ImportWarning, "ignore"));\r | |
861 | if (Py_BytesWarningFlag > 1)\r | |
862 | bytes_action = "error";\r | |
863 | else if (Py_BytesWarningFlag)\r | |
864 | bytes_action = "default";\r | |
865 | else\r | |
866 | bytes_action = "ignore";\r | |
867 | PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning,\r | |
868 | bytes_action));\r | |
869 | \r | |
870 | for (x = 0; x < pos; x += 1) {\r | |
871 | if (PyList_GET_ITEM(filters, x) == NULL) {\r | |
872 | Py_DECREF(filters);\r | |
873 | return NULL;\r | |
874 | }\r | |
875 | }\r | |
876 | \r | |
877 | return filters;\r | |
878 | }\r | |
879 | \r | |
880 | \r | |
881 | PyMODINIT_FUNC\r | |
882 | _PyWarnings_Init(void)\r | |
883 | {\r | |
884 | PyObject *m;\r | |
885 | \r | |
886 | m = Py_InitModule3(MODULE_NAME, warnings_functions, warnings__doc__);\r | |
887 | if (m == NULL)\r | |
888 | return;\r | |
889 | \r | |
890 | _filters = init_filters();\r | |
891 | if (_filters == NULL)\r | |
892 | return;\r | |
893 | Py_INCREF(_filters);\r | |
894 | if (PyModule_AddObject(m, "filters", _filters) < 0)\r | |
895 | return;\r | |
896 | \r | |
897 | _once_registry = PyDict_New();\r | |
898 | if (_once_registry == NULL)\r | |
899 | return;\r | |
900 | Py_INCREF(_once_registry);\r | |
901 | if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)\r | |
902 | return;\r | |
903 | \r | |
904 | _default_action = PyString_FromString("default");\r | |
905 | if (_default_action == NULL)\r | |
906 | return;\r | |
907 | if (PyModule_AddObject(m, "default_action", _default_action) < 0)\r | |
908 | return;\r | |
909 | }\r |