_warnings.c 27.5 KB
Newer Older
Christian Heimes's avatar
Christian Heimes committed
1 2 3 4 5 6 7 8 9 10 11 12 13
#include "Python.h"
#include "frameobject.h"

#define MODULE_NAME "_warnings"

PyDoc_STRVAR(warnings__doc__,
MODULE_NAME " provides basic warning filtering support.\n"
"It is a helper module to speed up interpreter start-up.");

/* Both 'filters' and 'onceregistry' can be set in warnings.py;
   get_warnings_attr() will reset these variables accordingly. */
static PyObject *_filters;  /* List */
static PyObject *_once_registry;  /* Dict */
14
static PyObject *_default_action; /* String */
Christian Heimes's avatar
Christian Heimes committed
15 16 17 18 19 20


static int
check_matched(PyObject *obj, PyObject *arg)
{
    PyObject *result;
21
    _Py_IDENTIFIER(match);
Christian Heimes's avatar
Christian Heimes committed
22 23 24 25
    int rc;

    if (obj == Py_None)
        return 1;
26
    result = _PyObject_CallMethodId(obj, &PyId_match, "O", arg);
Christian Heimes's avatar
Christian Heimes committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
    if (result == NULL)
        return -1;

    rc = PyObject_IsTrue(result);
    Py_DECREF(result);
    return rc;
}

/*
   Returns a new reference.
   A NULL return value can mean false or an error.
*/
static PyObject *
get_warnings_attr(const char *attr)
{
    static PyObject *warnings_str = NULL;
    PyObject *all_modules;
    PyObject *warnings_module;
    int result;

    if (warnings_str == NULL) {
        warnings_str = PyUnicode_InternFromString("warnings");
        if (warnings_str == NULL)
            return NULL;
    }

    all_modules = PyImport_GetModuleDict();
    result = PyDict_Contains(all_modules, warnings_str);
    if (result == -1 || result == 0)
        return NULL;

    warnings_module = PyDict_GetItem(all_modules, warnings_str);
    if (!PyObject_HasAttrString(warnings_module, attr))
            return NULL;
    return PyObject_GetAttrString(warnings_module, attr);
}


Neal Norwitz's avatar
Neal Norwitz committed
65
static PyObject *
Christian Heimes's avatar
Christian Heimes committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
get_once_registry(void)
{
    PyObject *registry;

    registry = get_warnings_attr("onceregistry");
    if (registry == NULL) {
        if (PyErr_Occurred())
            return NULL;
        return _once_registry;
    }
    Py_DECREF(_once_registry);
    _once_registry = registry;
    return registry;
}


82 83 84 85 86 87 88
static PyObject *
get_default_action(void)
{
    PyObject *default_action;

    default_action = get_warnings_attr("defaultaction");
    if (default_action == NULL) {
89 90 91 92
        if (PyErr_Occurred()) {
            return NULL;
        }
        return _default_action;
93 94 95 96 97 98 99 100
    }

    Py_DECREF(_default_action);
    _default_action = default_action;
    return default_action;
}


Christian Heimes's avatar
Christian Heimes committed
101 102 103 104 105
/* The item is a borrowed reference. */
static const char *
get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
           PyObject *module, PyObject **item)
{
106
    PyObject *action;
Christian Heimes's avatar
Christian Heimes committed
107 108 109 110 111 112 113 114 115 116 117 118 119
    Py_ssize_t i;
    PyObject *warnings_filters;

    warnings_filters = get_warnings_attr("filters");
    if (warnings_filters == NULL) {
        if (PyErr_Occurred())
            return NULL;
    }
    else {
        Py_DECREF(_filters);
        _filters = warnings_filters;
    }

120
    if (_filters == NULL || !PyList_Check(_filters)) {
Christian Heimes's avatar
Christian Heimes committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
        PyErr_SetString(PyExc_ValueError,
                        MODULE_NAME ".filters must be a list");
        return NULL;
    }

    /* _filters could change while we are iterating over it. */
    for (i = 0; i < PyList_GET_SIZE(_filters); i++) {
        PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
        Py_ssize_t ln;
        int is_subclass, good_msg, good_mod;

        tmp_item = *item = PyList_GET_ITEM(_filters, i);
        if (PyTuple_Size(tmp_item) != 5) {
            PyErr_Format(PyExc_ValueError,
                         MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
            return NULL;
        }

        /* Python code: action, msg, cat, mod, ln = item */
        action = PyTuple_GET_ITEM(tmp_item, 0);
        msg = PyTuple_GET_ITEM(tmp_item, 1);
        cat = PyTuple_GET_ITEM(tmp_item, 2);
        mod = PyTuple_GET_ITEM(tmp_item, 3);
        ln_obj = PyTuple_GET_ITEM(tmp_item, 4);

        good_msg = check_matched(msg, text);
        good_mod = check_matched(mod, module);
        is_subclass = PyObject_IsSubclass(category, cat);
        ln = PyLong_AsSsize_t(ln_obj);
        if (good_msg == -1 || good_mod == -1 || is_subclass == -1 ||
            (ln == -1 && PyErr_Occurred()))
            return NULL;

        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))
155
            return _PyUnicode_AsString(action);
Christian Heimes's avatar
Christian Heimes committed
156 157
    }

158 159
    action = get_default_action();
    if (action != NULL) {
160
        return _PyUnicode_AsString(action);
161
    }
Christian Heimes's avatar
Christian Heimes committed
162 163

    PyErr_SetString(PyExc_ValueError,
164
                    MODULE_NAME ".defaultaction not found");
Christian Heimes's avatar
Christian Heimes committed
165 166 167
    return NULL;
}

168

Christian Heimes's avatar
Christian Heimes committed
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
static int
already_warned(PyObject *registry, PyObject *key, int should_set)
{
    PyObject *already_warned;

    if (key == NULL)
        return -1;

    already_warned = PyDict_GetItem(registry, key);
    if (already_warned != NULL) {
        int rc = PyObject_IsTrue(already_warned);
        if (rc != 0)
            return rc;
    }

    /* This warning wasn't found in the registry, set it. */
    if (should_set)
        return PyDict_SetItem(registry, key, Py_True);
    return 0;
}

/* New reference. */
static PyObject *
normalize_module(PyObject *filename)
{
    PyObject *module;
    const char *mod_str;
    Py_ssize_t len;

    int rc = PyObject_IsTrue(filename);
    if (rc == -1)
        return NULL;
    else if (rc == 0)
        return PyUnicode_FromString("<unknown>");

204
    mod_str = _PyUnicode_AsString(filename);
Christian Heimes's avatar
Christian Heimes committed
205
    if (mod_str == NULL)
206 207
        return NULL;
    len = PyUnicode_GetLength(filename);
Christian Heimes's avatar
Christian Heimes committed
208 209 210
    if (len < 0)
        return NULL;
    if (len >= 3 &&
211
        strncmp(mod_str + (len - 3), ".py", 3) == 0) {
212
        module = PyUnicode_Substring(filename, 0, len-3);
Christian Heimes's avatar
Christian Heimes committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    }
    else {
        module = filename;
        Py_INCREF(module);
    }
    return module;
}

static int
update_registry(PyObject *registry, PyObject *text, PyObject *category,
                int add_zero)
{
    PyObject *altkey, *zero = NULL;
    int rc;

    if (add_zero) {
        zero = PyLong_FromLong(0);
        if (zero == NULL)
            return -1;
        altkey = PyTuple_Pack(3, text, category, zero);
    }
    else
        altkey = PyTuple_Pack(2, text, category);

    rc = already_warned(registry, altkey, 1);
    Py_XDECREF(zero);
    Py_XDECREF(altkey);
    return rc;
}

static void
show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
                *category, PyObject *sourceline)
{
247 248
    PyObject *f_stderr;
    PyObject *name;
Christian Heimes's avatar
Christian Heimes committed
249
    char lineno_str[128];
250
    _Py_IDENTIFIER(__name__);
Christian Heimes's avatar
Christian Heimes committed
251 252 253

    PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);

254
    name = _PyObject_GetAttrId(category, &PyId___name__);
Christian Heimes's avatar
Christian Heimes committed
255
    if (name == NULL)  /* XXX Can an object lack a '__name__' attribute? */
256
        return;
Christian Heimes's avatar
Christian Heimes committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275

    f_stderr = PySys_GetObject("stderr");
    if (f_stderr == NULL) {
        fprintf(stderr, "lost sys.stderr\n");
        Py_DECREF(name);
        return;
    }

    /* Print "filename:lineno: category: text\n" */
    PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW);
    PyFile_WriteString(lineno_str, f_stderr);
    PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW);
    PyFile_WriteString(": ", f_stderr);
    PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW);
    PyFile_WriteString("\n", f_stderr);
    Py_XDECREF(name);

    /* Print "  source_line\n" */
    if (sourceline) {
276
        char *source_line_str = _PyUnicode_AsString(sourceline);
277 278
        if (source_line_str == NULL)
                return;
Christian Heimes's avatar
Christian Heimes committed
279 280 281 282 283 284 285 286
        while (*source_line_str == ' ' || *source_line_str == '\t' ||
                *source_line_str == '\014')
            source_line_str++;

        PyFile_WriteString(source_line_str, f_stderr);
        PyFile_WriteString("\n", f_stderr);
    }
    else
287
        if (_Py_DisplaySourceLine(f_stderr, filename, lineno, 2) < 0)
288
                return;
Christian Heimes's avatar
Christian Heimes committed
289 290 291 292
    PyErr_Clear();
}

static PyObject *
293
warn_explicit(PyObject *category, PyObject *message,
Christian Heimes's avatar
Christian Heimes committed
294 295 296 297 298 299 300
              PyObject *filename, int lineno,
              PyObject *module, PyObject *registry, PyObject *sourceline)
{
    PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
    PyObject *item = Py_None;
    const char *action;
    int rc;
301

302 303 304 305
    if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
        PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
        return NULL;
    }
Christian Heimes's avatar
Christian Heimes committed
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323

    /* Normalize module. */
    if (module == NULL) {
        module = normalize_module(filename);
        if (module == NULL)
            return NULL;
    }
    else
        Py_INCREF(module);

    /* Normalize message. */
    Py_INCREF(message);  /* DECREF'ed in cleanup. */
    rc = PyObject_IsInstance(message, PyExc_Warning);
    if (rc == -1) {
        goto cleanup;
    }
    if (rc == 1) {
        text = PyObject_Str(message);
324 325
        if (text == NULL)
            goto cleanup;
Christian Heimes's avatar
Christian Heimes committed
326 327 328 329 330
        category = (PyObject*)message->ob_type;
    }
    else {
        text = message;
        message = PyObject_CallFunction(category, "O", message);
331 332
        if (message == NULL)
            goto cleanup;
Christian Heimes's avatar
Christian Heimes committed
333 334 335 336 337 338 339 340 341 342 343
    }

    lineno_obj = PyLong_FromLong(lineno);
    if (lineno_obj == NULL)
        goto cleanup;

    /* Create key. */
    key = PyTuple_Pack(3, text, category, lineno_obj);
    if (key == NULL)
        goto cleanup;

344
    if ((registry != NULL) && (registry != Py_None)) {
Christian Heimes's avatar
Christian Heimes committed
345 346 347
        rc = already_warned(registry, key, 0);
        if (rc == -1)
            goto cleanup;
348
        else if (rc == 1)
Christian Heimes's avatar
Christian Heimes committed
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
            goto return_none;
        /* Else this warning hasn't been generated before. */
    }

    action = get_filter(category, text, lineno, module, &item);
    if (action == NULL)
        goto cleanup;

    if (strcmp(action, "error") == 0) {
        PyErr_SetObject(category, message);
        goto cleanup;
    }

    /* Store in the registry that we've been here, *except* when the action
       is "always". */
    rc = 0;
    if (strcmp(action, "always") != 0) {
366 367
        if (registry != NULL && registry != Py_None &&
                PyDict_SetItem(registry, key, Py_True) < 0)
Christian Heimes's avatar
Christian Heimes committed
368 369 370 371
            goto cleanup;
        else if (strcmp(action, "ignore") == 0)
            goto return_none;
        else if (strcmp(action, "once") == 0) {
372
            if (registry == NULL || registry == Py_None) {
Christian Heimes's avatar
Christian Heimes committed
373 374 375 376 377
                registry = get_once_registry();
                if (registry == NULL)
                    goto cleanup;
            }
            /* _once_registry[(text, category)] = 1 */
378
            rc = update_registry(registry, text, category, 0);
Christian Heimes's avatar
Christian Heimes committed
379 380 381
        }
        else if (strcmp(action, "module") == 0) {
            /* registry[(text, category, 0)] = 1 */
382
            if (registry != NULL && registry != Py_None)
383
                rc = update_registry(registry, text, category, 0);
Christian Heimes's avatar
Christian Heimes committed
384 385 386 387 388
        }
        else if (strcmp(action, "default") != 0) {
            PyObject *to_str = PyObject_Str(item);
            const char *err_str = "???";

389
            if (to_str != NULL) {
390
                err_str = _PyUnicode_AsString(to_str);
391 392 393
                if (err_str == NULL)
                        goto cleanup;
            }
Christian Heimes's avatar
Christian Heimes committed
394 395 396 397 398 399 400 401
            PyErr_Format(PyExc_RuntimeError,
                        "Unrecognized action (%s) in warnings.filters:\n %s",
                        action, err_str);
            Py_XDECREF(to_str);
            goto cleanup;
        }
    }

402
    if (rc == 1)  /* Already warned for this module. */
Christian Heimes's avatar
Christian Heimes committed
403 404 405 406 407 408 409 410 411
        goto return_none;
    if (rc == 0) {
        PyObject *show_fxn = get_warnings_attr("showwarning");
        if (show_fxn == NULL) {
            if (PyErr_Occurred())
                goto cleanup;
            show_warning(filename, lineno, text, category, sourceline);
        }
        else {
412 413
            PyObject *res;

414
            if (!PyCallable_Check(show_fxn)) {
415 416
                PyErr_SetString(PyExc_TypeError,
                                "warnings.showwarning() must be set to a "
417
                                "callable");
418
                Py_DECREF(show_fxn);
419
                goto cleanup;
420
            }
421 422 423 424 425 426 427 428

            res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
                                                filename, lineno_obj,
                                                NULL);
            Py_DECREF(show_fxn);
            Py_XDECREF(res);
            if (res == NULL)
                goto cleanup;
Christian Heimes's avatar
Christian Heimes committed
429 430 431 432 433 434 435 436 437 438 439 440 441 442
        }
    }
    else /* if (rc == -1) */
        goto cleanup;

 return_none:
    result = Py_None;
    Py_INCREF(result);

 cleanup:
    Py_XDECREF(key);
    Py_XDECREF(text);
    Py_XDECREF(lineno_obj);
    Py_DECREF(module);
443
    Py_XDECREF(message);
Christian Heimes's avatar
Christian Heimes committed
444 445 446 447 448 449 450 451 452 453 454 455 456
    return result;  /* Py_None or NULL. */
}

/* filename, module, and registry are new refs, globals is borrowed */
/* Returns 0 on error (no new refs), 1 on success */
static int
setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
              PyObject **module, PyObject **registry)
{
    PyObject *globals;

    /* Setup globals and lineno. */
    PyFrameObject *f = PyThreadState_GET()->frame;
457
    while (--stack_level > 0 && f != NULL)
Christian Heimes's avatar
Christian Heimes committed
458 459 460 461 462 463 464 465
        f = f->f_back;

    if (f == NULL) {
        globals = PyThreadState_Get()->interp->sysdict;
        *lineno = 1;
    }
    else {
        globals = f->f_globals;
466
        *lineno = PyFrame_GetLineNumber(f);
Christian Heimes's avatar
Christian Heimes committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
    }

    *module = NULL;

    /* Setup registry. */
    assert(globals != NULL);
    assert(PyDict_Check(globals));
    *registry = PyDict_GetItemString(globals, "__warningregistry__");
    if (*registry == NULL) {
        int rc;

        *registry = PyDict_New();
        if (*registry == NULL)
            return 0;

         rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
         if (rc < 0)
            goto handle_error;
    }
    else
        Py_INCREF(*registry);

    /* Setup module. */
    *module = PyDict_GetItemString(globals, "__name__");
    if (*module == NULL) {
        *module = PyUnicode_FromString("<string>");
        if (*module == NULL)
            goto handle_error;
    }
    else
        Py_INCREF(*module);

    /* Setup filename. */
    *filename = PyDict_GetItemString(globals, "__file__");
501
    if (*filename != NULL && PyUnicode_Check(*filename)) {
502 503 504 505 506 507 508
        Py_ssize_t len;
        int kind;
        void *data;

        if (PyUnicode_READY(*filename))
            goto handle_error;

509
        len = PyUnicode_GetLength(*filename);
510 511
        kind = PyUnicode_KIND(*filename);
        data = PyUnicode_DATA(*filename);
Christian Heimes's avatar
Christian Heimes committed
512

513
#define ascii_lower(c) ((c <= 127) ? Py_TOLOWER(c) : 0)
Christian Heimes's avatar
Christian Heimes committed
514 515
        /* if filename.lower().endswith((".pyc", ".pyo")): */
        if (len >= 4 &&
Martin v. Löwis's avatar
Martin v. Löwis committed
516
            PyUnicode_READ(kind, data, len-4) == '.' &&
517 518 519 520
            ascii_lower(PyUnicode_READ(kind, data, len-3)) == 'p' &&
            ascii_lower(PyUnicode_READ(kind, data, len-2)) == 'y' &&
            (ascii_lower(PyUnicode_READ(kind, data, len-1)) == 'c' ||
                ascii_lower(PyUnicode_READ(kind, data, len-1)) == 'o'))
Christian Heimes's avatar
Christian Heimes committed
521
        {
Martin v. Löwis's avatar
Martin v. Löwis committed
522 523
            *filename = PyUnicode_Substring(*filename, 0,
                                            PyUnicode_GET_LENGTH(*filename)-1);
524 525 526 527
            if (*filename == NULL)
                goto handle_error;
        }
        else
Christian Heimes's avatar
Christian Heimes committed
528 529 530
            Py_INCREF(*filename);
    }
    else {
531
        const char *module_str = _PyUnicode_AsString(*module);
532
        *filename = NULL;
533 534
        if (module_str == NULL)
                goto handle_error;
535
        if (strcmp(module_str, "__main__") == 0) {
Christian Heimes's avatar
Christian Heimes committed
536 537
            PyObject *argv = PySys_GetObject("argv");
            if (argv != NULL && PyList_Size(argv) > 0) {
Christian Heimes's avatar
Christian Heimes committed
538
                int is_true;
Christian Heimes's avatar
Christian Heimes committed
539 540
                *filename = PyList_GetItem(argv, 0);
                Py_INCREF(*filename);
Christian Heimes's avatar
Christian Heimes committed
541 542 543 544 545 546 547 548
                /* If sys.argv[0] is false, then use '__main__'. */
                is_true = PyObject_IsTrue(*filename);
                if (is_true < 0) {
                    Py_DECREF(*filename);
                    goto handle_error;
                }
                else if (!is_true) {
                    Py_DECREF(*filename);
Benjamin Peterson's avatar
Benjamin Peterson committed
549
                    *filename = PyUnicode_FromString("__main__");
Christian Heimes's avatar
Christian Heimes committed
550 551 552
                    if (*filename == NULL)
                        goto handle_error;
                }
Christian Heimes's avatar
Christian Heimes committed
553 554 555 556
            }
            else {
                /* embedded interpreters don't have sys.argv, see bug #839151 */
                *filename = PyUnicode_FromString("__main__");
557 558
                    if (*filename == NULL)
                        goto handle_error;
Christian Heimes's avatar
Christian Heimes committed
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
            }
        }
        if (*filename == NULL) {
            *filename = *module;
            Py_INCREF(*filename);
        }
    }

    return 1;

 handle_error:
    /* filename not XDECREF'ed here as there is no way to jump here with a
       dangling reference. */
    Py_XDECREF(*registry);
    Py_XDECREF(*module);
    return 0;
}

static PyObject *
get_category(PyObject *message, PyObject *category)
{
    int rc;

    /* Get category. */
    rc = PyObject_IsInstance(message, PyExc_Warning);
    if (rc == -1)
        return NULL;

    if (rc == 1)
        category = (PyObject*)message->ob_type;
    else if (category == NULL)
        category = PyExc_UserWarning;

    /* Validate category. */
    rc = PyObject_IsSubclass(category, PyExc_Warning);
    if (rc == -1)
        return NULL;
    if (rc == 0) {
        PyErr_SetString(PyExc_ValueError,
                        "category is not a subclass of Warning");
        return NULL;
    }

    return category;
}

static PyObject *
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
{
    PyObject *filename, *module, *registry, *res;
    int lineno;

    if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
        return NULL;

    res = warn_explicit(category, message, filename, lineno, module, registry,
                        NULL);
    Py_DECREF(filename);
    Py_DECREF(registry);
    Py_DECREF(module);
    return res;
}

static PyObject *
warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
{
    static char *kw_list[] = { "message", "category", "stacklevel", 0 };
    PyObject *message, *category = NULL;
    Py_ssize_t stack_level = 1;

629
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
Christian Heimes's avatar
Christian Heimes committed
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
                                     &message, &category, &stack_level))
        return NULL;

    category = get_category(message, category);
    if (category == NULL)
        return NULL;
    return do_warn(message, category, stack_level);
}

static PyObject *
warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
{
    static char *kwd_list[] = {"message", "category", "filename", "lineno",
                                "module", "registry", "module_globals", 0};
    PyObject *message;
    PyObject *category;
    PyObject *filename;
    int lineno;
    PyObject *module = NULL;
    PyObject *registry = NULL;
    PyObject *module_globals = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
                kwd_list, &message, &category, &filename, &lineno, &module,
                &registry, &module_globals))
        return NULL;

    if (module_globals) {
658 659 660
        _Py_IDENTIFIER(get_source);
        _Py_IDENTIFIER(splitlines);
        PyObject *tmp;
Christian Heimes's avatar
Christian Heimes committed
661 662 663 664 665 666 667
        PyObject *loader;
        PyObject *module_name;
        PyObject *source;
        PyObject *source_list;
        PyObject *source_line;
        PyObject *returned;

668 669 670 671
        if ((tmp = _PyUnicode_FromId(&PyId_get_source)) == NULL)
            return NULL;
        if ((tmp = _PyUnicode_FromId(&PyId_splitlines)) == NULL)
            return NULL;
Christian Heimes's avatar
Christian Heimes committed
672 673 674 675 676 677 678 679 680

        /* Check/get the requisite pieces needed for the loader. */
        loader = PyDict_GetItemString(module_globals, "__loader__");
        module_name = PyDict_GetItemString(module_globals, "__name__");

        if (loader == NULL || module_name == NULL)
            goto standard_call;

        /* Make sure the loader implements the optional get_source() method. */
681
        if (!_PyObject_HasAttrId(loader, &PyId_get_source))
Christian Heimes's avatar
Christian Heimes committed
682 683
                goto standard_call;
        /* Call get_source() to get the source code. */
684 685
        source = PyObject_CallMethodObjArgs(loader, PyId_get_source.object,
                                            module_name, NULL);
Christian Heimes's avatar
Christian Heimes committed
686 687 688 689 690 691 692 693
        if (!source)
            return NULL;
        else if (source == Py_None) {
            Py_DECREF(Py_None);
            goto standard_call;
        }

        /* Split the source into lines. */
694
        source_list = PyObject_CallMethodObjArgs(source,
695 696
                                                 PyId_splitlines.object,
                                                 NULL);
Christian Heimes's avatar
Christian Heimes committed
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
        Py_DECREF(source);
        if (!source_list)
            return NULL;

        /* Get the source line. */
        source_line = PyList_GetItem(source_list, lineno-1);
        if (!source_line) {
            Py_DECREF(source_list);
            return NULL;
        }

        /* Handle the warning. */
        returned = warn_explicit(category, message, filename, lineno, module,
                            registry, source_line);
        Py_DECREF(source_list);
        return returned;
    }

 standard_call:
    return warn_explicit(category, message, filename, lineno, module,
                                registry, NULL);
}


/* Function to issue a warning message; may raise an exception. */
722 723 724 725

static int
warn_unicode(PyObject *category, PyObject *message,
             Py_ssize_t stack_level)
Christian Heimes's avatar
Christian Heimes committed
726 727 728 729 730 731 732 733 734 735 736 737 738 739
{
    PyObject *res;

    if (category == NULL)
        category = PyExc_RuntimeWarning;

    res = do_warn(message, category, stack_level);
    if (res == NULL)
        return -1;
    Py_DECREF(res);

    return 0;
}

740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
int
PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
                 const char *format, ...)
{
    int ret;
    PyObject *message;
    va_list vargs;

#ifdef HAVE_STDARG_PROTOTYPES
    va_start(vargs, format);
#else
    va_start(vargs);
#endif
    message = PyUnicode_FromFormatV(format, vargs);
    if (message != NULL) {
        ret = warn_unicode(category, message, stack_level);
        Py_DECREF(message);
    }
    else
        ret = -1;
    va_end(vargs);
    return ret;
}

int
PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
{
    int ret;
    PyObject *message = PyUnicode_FromString(text);
    if (message == NULL)
        return -1;
    ret = warn_unicode(category, message, stack_level);
    Py_DECREF(message);
    return ret;
}

776
/* PyErr_Warn is only for backwards compatibility and will be removed.
Christian Heimes's avatar
Christian Heimes committed
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
   Use PyErr_WarnEx instead. */

#undef PyErr_Warn

PyAPI_FUNC(int)
PyErr_Warn(PyObject *category, char *text)
{
    return PyErr_WarnEx(category, text, 1);
}

/* Warning with explicit origin */
int
PyErr_WarnExplicit(PyObject *category, const char *text,
                   const char *filename_str, int lineno,
                   const char *module_str, PyObject *registry)
{
    PyObject *res;
    PyObject *message = PyUnicode_FromString(text);
795
    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
Christian Heimes's avatar
Christian Heimes committed
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
    PyObject *module = NULL;
    int ret = -1;

    if (message == NULL || filename == NULL)
        goto exit;
    if (module_str != NULL) {
        module = PyUnicode_FromString(module_str);
            if (module == NULL)
                goto exit;
    }

    if (category == NULL)
        category = PyExc_RuntimeWarning;
    res = warn_explicit(category, message, filename, lineno, module, registry,
                        NULL);
    if (res == NULL)
        goto exit;
    Py_DECREF(res);
    ret = 0;

 exit:
    Py_XDECREF(message);
    Py_XDECREF(module);
    Py_XDECREF(filename);
    return ret;
}


PyDoc_STRVAR(warn_doc,
"Issue a warning, or maybe ignore it or raise an exception.");

PyDoc_STRVAR(warn_explicit_doc,
"Low-level inferface to warnings functionality.");

static PyMethodDef warnings_functions[] = {
    {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
        warn_doc},
    {"warn_explicit", (PyCFunction)warnings_warn_explicit,
        METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
835 836
    /* XXX(brett.cannon): add showwarning? */
    /* XXX(brett.cannon): Reasonable to add formatwarning? */
837
    {NULL, NULL}                /* sentinel */
Christian Heimes's avatar
Christian Heimes committed
838 839 840 841 842 843 844 845 846
};


static PyObject *
create_filter(PyObject *category, const char *action)
{
    static PyObject *ignore_str = NULL;
    static PyObject *error_str = NULL;
    static PyObject *default_str = NULL;
847
    static PyObject *always_str = NULL;
Christian Heimes's avatar
Christian Heimes committed
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
    PyObject *action_obj = NULL;
    PyObject *lineno, *result;

    if (!strcmp(action, "ignore")) {
        if (ignore_str == NULL) {
            ignore_str = PyUnicode_InternFromString("ignore");
            if (ignore_str == NULL)
                return NULL;
        }
        action_obj = ignore_str;
    }
    else if (!strcmp(action, "error")) {
        if (error_str == NULL) {
            error_str = PyUnicode_InternFromString("error");
            if (error_str == NULL)
                return NULL;
        }
        action_obj = error_str;
    }
    else if (!strcmp(action, "default")) {
        if (default_str == NULL) {
            default_str = PyUnicode_InternFromString("default");
            if (default_str == NULL)
                return NULL;
        }
        action_obj = default_str;
    }
875 876 877 878 879 880 881 882
    else if (!strcmp(action, "always")) {
        if (always_str == NULL) {
            always_str = PyUnicode_InternFromString("always");
            if (always_str == NULL)
                return NULL;
        }
        action_obj = always_str;
    }
Christian Heimes's avatar
Christian Heimes committed
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
    else {
        Py_FatalError("unknown action");
    }

    /* This assumes the line number is zero for now. */
    lineno = PyLong_FromLong(0);
    if (lineno == NULL)
        return NULL;
    result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
    Py_DECREF(lineno);
    return result;
}

static PyObject *
init_filters(void)
{
899
    PyObject *filters = PyList_New(5);
900 901
    unsigned int pos = 0;  /* Post-incremented in each use. */
    unsigned int x;
902
    const char *bytes_action, *resource_action;
903

Christian Heimes's avatar
Christian Heimes committed
904 905 906
    if (filters == NULL)
        return NULL;

907 908 909
    PyList_SET_ITEM(filters, pos++,
                    create_filter(PyExc_DeprecationWarning, "ignore"));
    PyList_SET_ITEM(filters, pos++,
Christian Heimes's avatar
Christian Heimes committed
910
                    create_filter(PyExc_PendingDeprecationWarning, "ignore"));
911 912
    PyList_SET_ITEM(filters, pos++,
                    create_filter(PyExc_ImportWarning, "ignore"));
Christian Heimes's avatar
Christian Heimes committed
913 914 915 916 917 918
    if (Py_BytesWarningFlag > 1)
        bytes_action = "error";
    else if (Py_BytesWarningFlag)
        bytes_action = "default";
    else
        bytes_action = "ignore";
919
    PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning,
Christian Heimes's avatar
Christian Heimes committed
920
                    bytes_action));
921 922 923 924 925 926 927 928
    /* resource usage warnings are enabled by default in pydebug mode */
#ifdef Py_DEBUG
    resource_action = "always";
#else
    resource_action = "ignore";
#endif
    PyList_SET_ITEM(filters, pos++, create_filter(PyExc_ResourceWarning,
                    resource_action));
929 930 931 932 933
    for (x = 0; x < pos; x += 1) {
        if (PyList_GET_ITEM(filters, x) == NULL) {
            Py_DECREF(filters);
            return NULL;
        }
Christian Heimes's avatar
Christian Heimes committed
934 935 936 937 938
    }

    return filters;
}

939
static struct PyModuleDef warningsmodule = {
940 941 942 943 944 945 946 947 948
        PyModuleDef_HEAD_INIT,
        MODULE_NAME,
        warnings__doc__,
        0,
        warnings_functions,
        NULL,
        NULL,
        NULL,
        NULL
949 950
};

Christian Heimes's avatar
Christian Heimes committed
951 952 953 954

PyMODINIT_FUNC
_PyWarnings_Init(void)
{
955
    PyObject *m;
Christian Heimes's avatar
Christian Heimes committed
956

957
    m = PyModule_Create(&warningsmodule);
Christian Heimes's avatar
Christian Heimes committed
958
    if (m == NULL)
959
        return NULL;
Christian Heimes's avatar
Christian Heimes committed
960

961 962 963 964 965
    if (_filters == NULL) {
        _filters = init_filters();
        if (_filters == NULL)
            return NULL;
    }
Christian Heimes's avatar
Christian Heimes committed
966 967
    Py_INCREF(_filters);
    if (PyModule_AddObject(m, "filters", _filters) < 0)
968
        return NULL;
Christian Heimes's avatar
Christian Heimes committed
969

970 971 972 973 974
    if (_once_registry == NULL) {
        _once_registry = PyDict_New();
        if (_once_registry == NULL)
            return NULL;
    }
Christian Heimes's avatar
Christian Heimes committed
975
    Py_INCREF(_once_registry);
976
    if (PyModule_AddObject(m, "_onceregistry", _once_registry) < 0)
977
        return NULL;
Christian Heimes's avatar
Christian Heimes committed
978

979 980 981 982 983 984
    if (_default_action == NULL) {
        _default_action = PyUnicode_FromString("default");
        if (_default_action == NULL)
            return NULL;
    }
    Py_INCREF(_default_action);
985
    if (PyModule_AddObject(m, "_defaultaction", _default_action) < 0)
986 987
        return NULL;
    return m;
Christian Heimes's avatar
Christian Heimes committed
988
}