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