_warnings.c 34.9 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 */
15
static long _filters_version;
Christian Heimes's avatar
Christian Heimes committed
16

17 18
_Py_IDENTIFIER(argv);
_Py_IDENTIFIER(stderr);
Christian Heimes's avatar
Christian Heimes committed
19 20 21 22 23

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

    if (obj == Py_None)
        return 1;
29
    result = _PyObject_CallMethodId(obj, &PyId_match, "O", arg);
Christian Heimes's avatar
Christian Heimes committed
30 31 32 33 34 35 36 37 38 39 40 41 42
    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 *
43
get_warnings_attr(const char *attr, int try_import)
Christian Heimes's avatar
Christian Heimes committed
44 45 46
{
    static PyObject *warnings_str = NULL;
    PyObject *all_modules;
47
    PyObject *warnings_module, *obj;
Christian Heimes's avatar
Christian Heimes committed
48 49 50 51 52 53 54

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

55 56 57 58 59 60 61 62 63 64 65 66 67 68
    /* don't try to import after the start of the Python finallization */
    if (try_import && _Py_Finalizing == NULL) {
        warnings_module = PyImport_Import(warnings_str);
        if (warnings_module == NULL) {
            /* Fallback to the C implementation if we cannot get
               the Python implementation */
            PyErr_Clear();
            return NULL;
        }
    }
    else {
        all_modules = PyImport_GetModuleDict();

        warnings_module = PyDict_GetItem(all_modules, warnings_str);
69 70 71
        if (warnings_module == NULL)
            return NULL;

72 73 74 75 76
        Py_INCREF(warnings_module);
    }

    if (!PyObject_HasAttrString(warnings_module, attr)) {
        Py_DECREF(warnings_module);
Christian Heimes's avatar
Christian Heimes committed
77
        return NULL;
78
    }
Christian Heimes's avatar
Christian Heimes committed
79

80 81 82
    obj = PyObject_GetAttrString(warnings_module, attr);
    Py_DECREF(warnings_module);
    return obj;
Christian Heimes's avatar
Christian Heimes committed
83 84 85
}


Neal Norwitz's avatar
Neal Norwitz committed
86
static PyObject *
Christian Heimes's avatar
Christian Heimes committed
87 88 89 90
get_once_registry(void)
{
    PyObject *registry;

91
    registry = get_warnings_attr("onceregistry", 0);
Christian Heimes's avatar
Christian Heimes committed
92 93 94 95 96 97 98 99 100 101 102
    if (registry == NULL) {
        if (PyErr_Occurred())
            return NULL;
        return _once_registry;
    }
    Py_DECREF(_once_registry);
    _once_registry = registry;
    return registry;
}


103 104 105 106 107
static PyObject *
get_default_action(void)
{
    PyObject *default_action;

108
    default_action = get_warnings_attr("defaultaction", 0);
109
    if (default_action == NULL) {
110 111 112 113
        if (PyErr_Occurred()) {
            return NULL;
        }
        return _default_action;
114 115 116 117 118 119 120 121
    }

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


122
/* The item is a new reference. */
123
static PyObject*
Christian Heimes's avatar
Christian Heimes committed
124 125 126
get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
           PyObject *module, PyObject **item)
{
127
    PyObject *action;
Christian Heimes's avatar
Christian Heimes committed
128 129 130
    Py_ssize_t i;
    PyObject *warnings_filters;

131
    warnings_filters = get_warnings_attr("filters", 0);
Christian Heimes's avatar
Christian Heimes committed
132 133 134 135 136 137 138 139 140
    if (warnings_filters == NULL) {
        if (PyErr_Occurred())
            return NULL;
    }
    else {
        Py_DECREF(_filters);
        _filters = warnings_filters;
    }

141
    if (_filters == NULL || !PyList_Check(_filters)) {
Christian Heimes's avatar
Christian Heimes committed
142 143 144 145 146 147 148 149 150 151 152
        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;

153 154
        tmp_item = PyList_GET_ITEM(_filters, i);
        if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {
Christian Heimes's avatar
Christian Heimes committed
155 156 157 158 159 160
            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 */
161
        Py_INCREF(tmp_item);
Christian Heimes's avatar
Christian Heimes committed
162 163 164 165 166 167 168
        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);
Benjamin Peterson's avatar
Benjamin Peterson committed
169 170
        if (good_msg == -1) {
            Py_DECREF(tmp_item);
171
            return NULL;
Benjamin Peterson's avatar
Benjamin Peterson committed
172
        }
173

Christian Heimes's avatar
Christian Heimes committed
174
        good_mod = check_matched(mod, module);
Benjamin Peterson's avatar
Benjamin Peterson committed
175 176
        if (good_mod == -1) {
            Py_DECREF(tmp_item);
177
            return NULL;
Benjamin Peterson's avatar
Benjamin Peterson committed
178
        }
179

Christian Heimes's avatar
Christian Heimes committed
180
        is_subclass = PyObject_IsSubclass(category, cat);
Benjamin Peterson's avatar
Benjamin Peterson committed
181 182
        if (is_subclass == -1) {
            Py_DECREF(tmp_item);
183
            return NULL;
Benjamin Peterson's avatar
Benjamin Peterson committed
184
        }
185

Christian Heimes's avatar
Christian Heimes committed
186
        ln = PyLong_AsSsize_t(ln_obj);
Benjamin Peterson's avatar
Benjamin Peterson committed
187
        if (ln == -1 && PyErr_Occurred()) {
188
            Py_DECREF(tmp_item);
Christian Heimes's avatar
Christian Heimes committed
189
            return NULL;
190
        }
Christian Heimes's avatar
Christian Heimes committed
191

192 193
        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
            *item = tmp_item;
194
            return action;
195 196 197
        }

        Py_DECREF(tmp_item);
Christian Heimes's avatar
Christian Heimes committed
198 199
    }

200 201
    action = get_default_action();
    if (action != NULL) {
202 203
        Py_INCREF(Py_None);
        *item = Py_None;
204
        return action;
205
    }
Christian Heimes's avatar
Christian Heimes committed
206 207

    PyErr_SetString(PyExc_ValueError,
208
                    MODULE_NAME ".defaultaction not found");
Christian Heimes's avatar
Christian Heimes committed
209 210 211
    return NULL;
}

212

Christian Heimes's avatar
Christian Heimes committed
213 214 215
static int
already_warned(PyObject *registry, PyObject *key, int should_set)
{
216 217
    PyObject *version_obj, *already_warned;
    _Py_IDENTIFIER(version);
Christian Heimes's avatar
Christian Heimes committed
218 219 220 221

    if (key == NULL)
        return -1;

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    version_obj = _PyDict_GetItemId(registry, &PyId_version);
    if (version_obj == NULL
        || !PyLong_CheckExact(version_obj)
        || PyLong_AsLong(version_obj) != _filters_version) {
        PyDict_Clear(registry);
        version_obj = PyLong_FromLong(_filters_version);
        if (version_obj == NULL)
            return -1;
        if (_PyDict_SetItemId(registry, &PyId_version, version_obj) < 0) {
            Py_DECREF(version_obj);
            return -1;
        }
        Py_DECREF(version_obj);
    }
    else {
        already_warned = PyDict_GetItem(registry, key);
        if (already_warned != NULL) {
            int rc = PyObject_IsTrue(already_warned);
            if (rc != 0)
                return rc;
        }
Christian Heimes's avatar
Christian Heimes committed
243 244 245 246 247 248 249 250 251 252 253 254 255
    }

    /* 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;
256 257
    int kind;
    void *data;
Christian Heimes's avatar
Christian Heimes committed
258 259
    Py_ssize_t len;

260
    len = PyUnicode_GetLength(filename);
Christian Heimes's avatar
Christian Heimes committed
261 262
    if (len < 0)
        return NULL;
263 264 265 266 267 268 269 270

    if (len == 0)
        return PyUnicode_FromString("<unknown>");

    kind = PyUnicode_KIND(filename);
    data = PyUnicode_DATA(filename);

    /* if filename.endswith(".py"): */
Christian Heimes's avatar
Christian Heimes committed
271
    if (len >= 3 &&
272 273 274 275
        PyUnicode_READ(kind, data, len-3) == '.' &&
        PyUnicode_READ(kind, data, len-2) == 'p' &&
        PyUnicode_READ(kind, data, len-1) == 'y')
    {
276
        module = PyUnicode_Substring(filename, 0, len-3);
Christian Heimes's avatar
Christian Heimes committed
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
    }
    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
308 309
show_warning(PyObject *filename, int lineno, PyObject *text,
             PyObject *category, PyObject *sourceline)
Christian Heimes's avatar
Christian Heimes committed
310
{
311 312
    PyObject *f_stderr;
    PyObject *name;
Christian Heimes's avatar
Christian Heimes committed
313
    char lineno_str[128];
314
    _Py_IDENTIFIER(__name__);
Christian Heimes's avatar
Christian Heimes committed
315 316 317

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

318
    name = _PyObject_GetAttrId(category, &PyId___name__);
Christian Heimes's avatar
Christian Heimes committed
319
    if (name == NULL)  /* XXX Can an object lack a '__name__' attribute? */
320
        goto error;
Christian Heimes's avatar
Christian Heimes committed
321

322
    f_stderr = _PySys_GetObjectId(&PyId_stderr);
Christian Heimes's avatar
Christian Heimes committed
323 324
    if (f_stderr == NULL) {
        fprintf(stderr, "lost sys.stderr\n");
325
        goto error;
Christian Heimes's avatar
Christian Heimes committed
326 327 328
    }

    /* Print "filename:lineno: category: text\n" */
329 330 331 332 333 334 335 336 337 338 339 340 341
    if (PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW) < 0)
        goto error;
    if (PyFile_WriteString(lineno_str, f_stderr) < 0)
        goto error;
    if (PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW) < 0)
        goto error;
    if (PyFile_WriteString(": ", f_stderr) < 0)
        goto error;
    if (PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW) < 0)
        goto error;
    if (PyFile_WriteString("\n", f_stderr) < 0)
        goto error;
    Py_CLEAR(name);
Christian Heimes's avatar
Christian Heimes committed
342 343 344

    /* Print "  source_line\n" */
    if (sourceline) {
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
        int kind;
        void *data;
        Py_ssize_t i, len;
        Py_UCS4 ch;
        PyObject *truncated;

        if (PyUnicode_READY(sourceline) < 1)
            goto error;

        kind = PyUnicode_KIND(sourceline);
        data = PyUnicode_DATA(sourceline);
        len = PyUnicode_GET_LENGTH(sourceline);
        for (i=0; i<len; i++) {
            ch = PyUnicode_READ(kind, data, i);
            if (ch != ' ' && ch != '\t' && ch != '\014')
                break;
        }

        truncated = PyUnicode_Substring(sourceline, i, len);
        if (truncated == NULL)
            goto error;

        PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW);
        Py_DECREF(truncated);
Christian Heimes's avatar
Christian Heimes committed
369 370
        PyFile_WriteString("\n", f_stderr);
    }
371 372 373
    else {
        _Py_DisplaySourceLine(f_stderr, filename, lineno, 2);
    }
374 375

error:
376
    Py_XDECREF(name);
Christian Heimes's avatar
Christian Heimes committed
377 378 379
    PyErr_Clear();
}

380 381 382
static int
call_show_warning(PyObject *category, PyObject *text, PyObject *message,
                  PyObject *filename, int lineno, PyObject *lineno_obj,
383
                  PyObject *sourceline, PyObject *source)
384 385 386
{
    PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;

387 388 389 390
    /* If the source parameter is set, try to get the Python implementation.
       The Python implementation is able to log the traceback where the source
       was allocated, whereas the C implementation doesnt. */
    show_fn = get_warnings_attr("_showwarnmsg", source != NULL);
391 392 393 394 395 396 397 398 399 400 401 402 403
    if (show_fn == NULL) {
        if (PyErr_Occurred())
            return -1;
        show_warning(filename, lineno, text, category, sourceline);
        return 0;
    }

    if (!PyCallable_Check(show_fn)) {
        PyErr_SetString(PyExc_TypeError,
                "warnings._showwarnmsg() must be set to a callable");
        goto error;
    }

404
    warnmsg_cls = get_warnings_attr("WarningMessage", 0);
405 406 407 408 409 410 411
    if (warnmsg_cls == NULL) {
        PyErr_SetString(PyExc_RuntimeError,
                "unable to get warnings.WarningMessage");
        goto error;
    }

    msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category,
412
            filename, lineno_obj, Py_None, Py_None, source,
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
            NULL);
    Py_DECREF(warnmsg_cls);
    if (msg == NULL)
        goto error;

    res = PyObject_CallFunctionObjArgs(show_fn, msg, NULL);
    Py_DECREF(show_fn);
    Py_DECREF(msg);

    if (res == NULL)
        return -1;

    Py_DECREF(res);
    return 0;

error:
    Py_XDECREF(show_fn);
    return -1;
}

Christian Heimes's avatar
Christian Heimes committed
433
static PyObject *
434
warn_explicit(PyObject *category, PyObject *message,
Christian Heimes's avatar
Christian Heimes committed
435
              PyObject *filename, int lineno,
436 437
              PyObject *module, PyObject *registry, PyObject *sourceline,
              PyObject *source)
Christian Heimes's avatar
Christian Heimes committed
438 439
{
    PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
440
    PyObject *item = NULL;
441
    PyObject *action;
Christian Heimes's avatar
Christian Heimes committed
442
    int rc;
443

444 445 446 447 448 449 450
    /* module can be None if a warning is emitted late during Python shutdown.
       In this case, the Python warnings module was probably unloaded, filters
       are no more available to choose as action. It is safer to ignore the
       warning and do nothing. */
    if (module == Py_None)
        Py_RETURN_NONE;

451 452 453 454
    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
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472

    /* 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);
473 474
        if (text == NULL)
            goto cleanup;
Christian Heimes's avatar
Christian Heimes committed
475 476 477 478 479
        category = (PyObject*)message->ob_type;
    }
    else {
        text = message;
        message = PyObject_CallFunction(category, "O", message);
480 481
        if (message == NULL)
            goto cleanup;
Christian Heimes's avatar
Christian Heimes committed
482 483 484 485 486 487 488 489 490 491 492
    }

    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;

493
    if ((registry != NULL) && (registry != Py_None)) {
Christian Heimes's avatar
Christian Heimes committed
494 495 496
        rc = already_warned(registry, key, 0);
        if (rc == -1)
            goto cleanup;
497
        else if (rc == 1)
Christian Heimes's avatar
Christian Heimes committed
498 499 500 501 502 503 504 505
            goto return_none;
        /* Else this warning hasn't been generated before. */
    }

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

506
    if (PyUnicode_CompareWithASCIIString(action, "error") == 0) {
Christian Heimes's avatar
Christian Heimes committed
507 508 509 510 511 512 513
        PyErr_SetObject(category, message);
        goto cleanup;
    }

    /* Store in the registry that we've been here, *except* when the action
       is "always". */
    rc = 0;
514
    if (PyUnicode_CompareWithASCIIString(action, "always") != 0) {
515 516
        if (registry != NULL && registry != Py_None &&
                PyDict_SetItem(registry, key, Py_True) < 0)
Christian Heimes's avatar
Christian Heimes committed
517
            goto cleanup;
518
        else if (PyUnicode_CompareWithASCIIString(action, "ignore") == 0)
Christian Heimes's avatar
Christian Heimes committed
519
            goto return_none;
520
        else if (PyUnicode_CompareWithASCIIString(action, "once") == 0) {
521
            if (registry == NULL || registry == Py_None) {
Christian Heimes's avatar
Christian Heimes committed
522 523 524 525 526
                registry = get_once_registry();
                if (registry == NULL)
                    goto cleanup;
            }
            /* _once_registry[(text, category)] = 1 */
527
            rc = update_registry(registry, text, category, 0);
Christian Heimes's avatar
Christian Heimes committed
528
        }
529
        else if (PyUnicode_CompareWithASCIIString(action, "module") == 0) {
Christian Heimes's avatar
Christian Heimes committed
530
            /* registry[(text, category, 0)] = 1 */
531
            if (registry != NULL && registry != Py_None)
532
                rc = update_registry(registry, text, category, 0);
Christian Heimes's avatar
Christian Heimes committed
533
        }
534
        else if (PyUnicode_CompareWithASCIIString(action, "default") != 0) {
Christian Heimes's avatar
Christian Heimes committed
535
            PyErr_Format(PyExc_RuntimeError,
536 537
                        "Unrecognized action (%R) in warnings.filters:\n %R",
                        action, item);
Christian Heimes's avatar
Christian Heimes committed
538 539 540 541
            goto cleanup;
        }
    }

542
    if (rc == 1)  /* Already warned for this module. */
Christian Heimes's avatar
Christian Heimes committed
543 544
        goto return_none;
    if (rc == 0) {
545
        if (call_show_warning(category, text, message, filename, lineno,
546
                              lineno_obj, sourceline, source) < 0)
547
            goto cleanup;
Christian Heimes's avatar
Christian Heimes committed
548 549 550 551 552 553 554 555 556
    }
    else /* if (rc == -1) */
        goto cleanup;

 return_none:
    result = Py_None;
    Py_INCREF(result);

 cleanup:
557
    Py_XDECREF(item);
Christian Heimes's avatar
Christian Heimes committed
558 559 560 561
    Py_XDECREF(key);
    Py_XDECREF(text);
    Py_XDECREF(lineno_obj);
    Py_DECREF(module);
562
    Py_XDECREF(message);
Christian Heimes's avatar
Christian Heimes committed
563 564 565
    return result;  /* Py_None or NULL. */
}

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
static int
is_internal_frame(PyFrameObject *frame)
{
    static PyObject *importlib_string = NULL;
    static PyObject *bootstrap_string = NULL;
    PyObject *filename;
    int contains;

    if (importlib_string == NULL) {
        importlib_string = PyUnicode_FromString("importlib");
        if (importlib_string == NULL) {
            return 0;
        }

        bootstrap_string = PyUnicode_FromString("_bootstrap");
        if (bootstrap_string == NULL) {
            Py_DECREF(importlib_string);
            return 0;
        }
        Py_INCREF(importlib_string);
        Py_INCREF(bootstrap_string);
    }

    if (frame == NULL || frame->f_code == NULL ||
            frame->f_code->co_filename == NULL) {
        return 0;
    }
    filename = frame->f_code->co_filename;
    if (!PyUnicode_Check(filename)) {
        return 0;
    }
    contains = PyUnicode_Contains(filename, importlib_string);
    if (contains < 0) {
        return 0;
    }
    else if (contains > 0) {
        contains = PyUnicode_Contains(filename, bootstrap_string);
        if (contains < 0) {
            return 0;
        }
        else if (contains > 0) {
            return 1;
        }
    }

    return 0;
}

static PyFrameObject *
next_external_frame(PyFrameObject *frame)
{
    do {
        frame = frame->f_back;
    } while (frame != NULL && is_internal_frame(frame));

    return frame;
}

Christian Heimes's avatar
Christian Heimes committed
624 625 626 627 628 629 630 631 632 633
/* 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;
634 635 636 637 638 639 640 641 642 643 644 645
    // Stack level comparisons to Python code is off by one as there is no
    // warnings-related stack level to avoid.
    if (stack_level <= 0 || is_internal_frame(f)) {
        while (--stack_level > 0 && f != NULL) {
            f = f->f_back;
        }
    }
    else {
        while (--stack_level > 0 && f != NULL) {
            f = next_external_frame(f);
        }
    }
Christian Heimes's avatar
Christian Heimes committed
646 647 648 649 650 651 652

    if (f == NULL) {
        globals = PyThreadState_Get()->interp->sysdict;
        *lineno = 1;
    }
    else {
        globals = f->f_globals;
653
        *lineno = PyFrame_GetLineNumber(f);
Christian Heimes's avatar
Christian Heimes committed
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
    }

    *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__");
688
    if (*filename != NULL && PyUnicode_Check(*filename)) {
689 690 691 692 693 694 695
        Py_ssize_t len;
        int kind;
        void *data;

        if (PyUnicode_READY(*filename))
            goto handle_error;

696
        len = PyUnicode_GetLength(*filename);
697 698
        kind = PyUnicode_KIND(*filename);
        data = PyUnicode_DATA(*filename);
Christian Heimes's avatar
Christian Heimes committed
699

700
#define ascii_lower(c) ((c <= 127) ? Py_TOLOWER(c) : 0)
701
        /* if filename.lower().endswith(".pyc"): */
Christian Heimes's avatar
Christian Heimes committed
702
        if (len >= 4 &&
Martin v. Löwis's avatar
Martin v. Löwis committed
703
            PyUnicode_READ(kind, data, len-4) == '.' &&
704 705
            ascii_lower(PyUnicode_READ(kind, data, len-3)) == 'p' &&
            ascii_lower(PyUnicode_READ(kind, data, len-2)) == 'y' &&
706
            ascii_lower(PyUnicode_READ(kind, data, len-1)) == 'c')
Christian Heimes's avatar
Christian Heimes committed
707
        {
Martin v. Löwis's avatar
Martin v. Löwis committed
708 709
            *filename = PyUnicode_Substring(*filename, 0,
                                            PyUnicode_GET_LENGTH(*filename)-1);
710 711 712 713
            if (*filename == NULL)
                goto handle_error;
        }
        else
Christian Heimes's avatar
Christian Heimes committed
714 715 716
            Py_INCREF(*filename);
    }
    else {
717
        *filename = NULL;
718
        if (*module != Py_None && PyUnicode_CompareWithASCIIString(*module, "__main__") == 0) {
719
            PyObject *argv = _PySys_GetObjectId(&PyId_argv);
720 721 722
            /* PyList_Check() is needed because sys.argv is set to None during
               Python finalization */
            if (argv != NULL && PyList_Check(argv) && PyList_Size(argv) > 0) {
Christian Heimes's avatar
Christian Heimes committed
723
                int is_true;
Christian Heimes's avatar
Christian Heimes committed
724 725
                *filename = PyList_GetItem(argv, 0);
                Py_INCREF(*filename);
Christian Heimes's avatar
Christian Heimes committed
726 727 728 729 730 731 732
                /* 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) {
733
                    Py_SETREF(*filename, PyUnicode_FromString("__main__"));
Christian Heimes's avatar
Christian Heimes committed
734 735 736
                    if (*filename == NULL)
                        goto handle_error;
                }
Christian Heimes's avatar
Christian Heimes committed
737 738 739 740
            }
            else {
                /* embedded interpreters don't have sys.argv, see bug #839151 */
                *filename = PyUnicode_FromString("__main__");
741 742
                if (*filename == NULL)
                    goto handle_error;
Christian Heimes's avatar
Christian Heimes committed
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
            }
        }
        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;
773
    else if (category == NULL || category == Py_None)
Christian Heimes's avatar
Christian Heimes committed
774 775 776 777
        category = PyExc_UserWarning;

    /* Validate category. */
    rc = PyObject_IsSubclass(category, PyExc_Warning);
778 779 780 781 782 783
    /* category is not a subclass of PyExc_Warning or
       PyObject_IsSubclass raised an error */
    if (rc == -1 || rc == 0) {
        PyErr_Format(PyExc_TypeError,
                     "category must be a Warning subclass, not '%s'",
                     Py_TYPE(category)->tp_name);
Christian Heimes's avatar
Christian Heimes committed
784 785 786 787 788 789 790
        return NULL;
    }

    return category;
}

static PyObject *
791 792
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
        PyObject *source)
Christian Heimes's avatar
Christian Heimes committed
793 794 795 796 797 798 799
{
    PyObject *filename, *module, *registry, *res;
    int lineno;

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

800
    res = warn_explicit(category, message, filename, lineno, module, registry,
801
                        NULL, source);
Christian Heimes's avatar
Christian Heimes committed
802 803 804 805 806 807 808 809 810
    Py_DECREF(filename);
    Py_DECREF(registry);
    Py_DECREF(module);
    return res;
}

static PyObject *
warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
{
811 812 813
    static char *kw_list[] = {"message", "category", "stacklevel",
                              "source", NULL};
    PyObject *message, *category = NULL, *source = NULL;
Christian Heimes's avatar
Christian Heimes committed
814 815
    Py_ssize_t stack_level = 1;

816 817
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OnO:warn", kw_list,
                                     &message, &category, &stack_level, &source))
Christian Heimes's avatar
Christian Heimes committed
818 819 820 821 822
        return NULL;

    category = get_category(message, category);
    if (category == NULL)
        return NULL;
823
    return do_warn(message, category, stack_level, source);
Christian Heimes's avatar
Christian Heimes committed
824 825 826 827 828 829
}

static PyObject *
warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
{
    static char *kwd_list[] = {"message", "category", "filename", "lineno",
830 831
                                "module", "registry", "module_globals",
                                "source", 0};
Christian Heimes's avatar
Christian Heimes committed
832 833 834 835 836 837 838
    PyObject *message;
    PyObject *category;
    PyObject *filename;
    int lineno;
    PyObject *module = NULL;
    PyObject *registry = NULL;
    PyObject *module_globals = NULL;
839
    PyObject *sourceobj = NULL;
Christian Heimes's avatar
Christian Heimes committed
840

841
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit",
Christian Heimes's avatar
Christian Heimes committed
842
                kwd_list, &message, &category, &filename, &lineno, &module,
843
                &registry, &module_globals, &sourceobj))
Christian Heimes's avatar
Christian Heimes committed
844 845 846
        return NULL;

    if (module_globals) {
847 848 849
        _Py_IDENTIFIER(get_source);
        _Py_IDENTIFIER(splitlines);
        PyObject *tmp;
Christian Heimes's avatar
Christian Heimes committed
850 851 852 853 854 855 856
        PyObject *loader;
        PyObject *module_name;
        PyObject *source;
        PyObject *source_list;
        PyObject *source_line;
        PyObject *returned;

857 858 859 860
        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
861 862 863 864 865 866 867 868 869

        /* 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. */
870
        if (!_PyObject_HasAttrId(loader, &PyId_get_source))
Christian Heimes's avatar
Christian Heimes committed
871 872
                goto standard_call;
        /* Call get_source() to get the source code. */
873 874
        source = PyObject_CallMethodObjArgs(loader, PyId_get_source.object,
                                            module_name, NULL);
Christian Heimes's avatar
Christian Heimes committed
875 876 877 878 879 880 881 882
        if (!source)
            return NULL;
        else if (source == Py_None) {
            Py_DECREF(Py_None);
            goto standard_call;
        }

        /* Split the source into lines. */
883
        source_list = PyObject_CallMethodObjArgs(source,
884 885
                                                 PyId_splitlines.object,
                                                 NULL);
Christian Heimes's avatar
Christian Heimes committed
886 887 888 889 890 891 892 893 894 895 896 897 898
        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,
899
                                 registry, source_line, sourceobj);
Christian Heimes's avatar
Christian Heimes committed
900 901 902 903 904 905
        Py_DECREF(source_list);
        return returned;
    }

 standard_call:
    return warn_explicit(category, message, filename, lineno, module,
906
                         registry, NULL, sourceobj);
Christian Heimes's avatar
Christian Heimes committed
907 908
}

909 910 911 912 913 914 915
static PyObject *
warnings_filters_mutated(PyObject *self, PyObject *args)
{
    _filters_version++;
    Py_RETURN_NONE;
}

Christian Heimes's avatar
Christian Heimes committed
916 917

/* Function to issue a warning message; may raise an exception. */
918 919 920

static int
warn_unicode(PyObject *category, PyObject *message,
921
             Py_ssize_t stack_level, PyObject *source)
Christian Heimes's avatar
Christian Heimes committed
922 923 924 925 926 927
{
    PyObject *res;

    if (category == NULL)
        category = PyExc_RuntimeWarning;

928
    res = do_warn(message, category, stack_level, source);
Christian Heimes's avatar
Christian Heimes committed
929 930 931 932 933 934 935
    if (res == NULL)
        return -1;
    Py_DECREF(res);

    return 0;
}

936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952
static int
_PyErr_WarnFormatV(PyObject *source,
                   PyObject *category, Py_ssize_t stack_level,
                   const char *format, va_list vargs)
{
    PyObject *message;
    int res;

    message = PyUnicode_FromFormatV(format, vargs);
    if (message == NULL)
        return -1;

    res = warn_unicode(category, message, stack_level, source);
    Py_DECREF(message);
    return res;
}

953 954 955 956
int
PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
                 const char *format, ...)
{
957
    int res;
958 959 960 961 962 963 964
    va_list vargs;

#ifdef HAVE_STDARG_PROTOTYPES
    va_start(vargs, format);
#else
    va_start(vargs);
#endif
965
    res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
966
    va_end(vargs);
967
    return res;
968 969
}

970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
int
PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
                      const char *format, ...)
{
    int res;
    va_list vargs;

#ifdef HAVE_STDARG_PROTOTYPES
    va_start(vargs, format);
#else
    va_start(vargs);
#endif
    res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
                             stack_level, format, vargs);
    va_end(vargs);
    return res;
}


989 990 991 992 993 994 995
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;
996
    ret = warn_unicode(category, message, stack_level, NULL);
997 998 999 1000
    Py_DECREF(message);
    return ret;
}

1001
/* PyErr_Warn is only for backwards compatibility and will be removed.
Christian Heimes's avatar
Christian Heimes committed
1002 1003 1004 1005 1006
   Use PyErr_WarnEx instead. */

#undef PyErr_Warn

PyAPI_FUNC(int)
1007
PyErr_Warn(PyObject *category, const char *text)
Christian Heimes's avatar
Christian Heimes committed
1008 1009 1010 1011 1012
{
    return PyErr_WarnEx(category, text, 1);
}

/* Warning with explicit origin */
1013 1014 1015 1016 1017 1018 1019 1020 1021
int
PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
                         PyObject *filename, int lineno,
                         PyObject *module, PyObject *registry)
{
    PyObject *res;
    if (category == NULL)
        category = PyExc_RuntimeWarning;
    res = warn_explicit(category, message, filename, lineno,
1022
                        module, registry, NULL, NULL);
1023 1024 1025 1026 1027 1028
    if (res == NULL)
        return -1;
    Py_DECREF(res);
    return 0;
}

Christian Heimes's avatar
Christian Heimes committed
1029 1030 1031 1032 1033 1034
int
PyErr_WarnExplicit(PyObject *category, const char *text,
                   const char *filename_str, int lineno,
                   const char *module_str, PyObject *registry)
{
    PyObject *message = PyUnicode_FromString(text);
1035
    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
Christian Heimes's avatar
Christian Heimes committed
1036 1037 1038 1039 1040 1041 1042
    PyObject *module = NULL;
    int ret = -1;

    if (message == NULL || filename == NULL)
        goto exit;
    if (module_str != NULL) {
        module = PyUnicode_FromString(module_str);
1043 1044
        if (module == NULL)
            goto exit;
Christian Heimes's avatar
Christian Heimes committed
1045 1046
    }

1047 1048
    ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
                                   module, registry);
Christian Heimes's avatar
Christian Heimes committed
1049 1050 1051 1052 1053 1054 1055 1056

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

1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
int
PyErr_WarnExplicitFormat(PyObject *category,
                         const char *filename_str, int lineno,
                         const char *module_str, PyObject *registry,
                         const char *format, ...)
{
    PyObject *message;
    PyObject *module = NULL;
    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
    int ret = -1;
    va_list vargs;

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

#ifdef HAVE_STDARG_PROTOTYPES
    va_start(vargs, format);
#else
    va_start(vargs);
#endif
    message = PyUnicode_FromFormatV(format, vargs);
    if (message != NULL) {
        PyObject *res;
        res = warn_explicit(category, message, filename, lineno,
1086
                            module, registry, NULL, NULL);
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
        Py_DECREF(message);
        if (res != NULL) {
            Py_DECREF(res);
            ret = 0;
        }
    }
    va_end(vargs);
exit:
    Py_XDECREF(module);
    Py_XDECREF(filename);
    return ret;
}

Christian Heimes's avatar
Christian Heimes committed
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111

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},
1112 1113
    {"_filters_mutated", (PyCFunction)warnings_filters_mutated, METH_NOARGS,
        NULL},
1114 1115
    /* XXX(brett.cannon): add showwarning? */
    /* XXX(brett.cannon): Reasonable to add formatwarning? */
1116
    {NULL, NULL}                /* sentinel */
Christian Heimes's avatar
Christian Heimes committed
1117 1118 1119 1120 1121 1122 1123 1124 1125
};


static PyObject *
create_filter(PyObject *category, const char *action)
{
    static PyObject *ignore_str = NULL;
    static PyObject *error_str = NULL;
    static PyObject *default_str = NULL;
1126
    static PyObject *always_str = NULL;
Christian Heimes's avatar
Christian Heimes committed
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
    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;
    }
1154 1155 1156 1157 1158 1159 1160 1161
    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
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
    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)
{
1178
    PyObject *filters = PyList_New(5);
1179 1180
    unsigned int pos = 0;  /* Post-incremented in each use. */
    unsigned int x;
1181
    const char *bytes_action, *resource_action;
1182

Christian Heimes's avatar
Christian Heimes committed
1183 1184 1185
    if (filters == NULL)
        return NULL;

1186 1187 1188
    PyList_SET_ITEM(filters, pos++,
                    create_filter(PyExc_DeprecationWarning, "ignore"));
    PyList_SET_ITEM(filters, pos++,
Christian Heimes's avatar
Christian Heimes committed
1189
                    create_filter(PyExc_PendingDeprecationWarning, "ignore"));
1190 1191
    PyList_SET_ITEM(filters, pos++,
                    create_filter(PyExc_ImportWarning, "ignore"));
Christian Heimes's avatar
Christian Heimes committed
1192 1193 1194 1195 1196 1197
    if (Py_BytesWarningFlag > 1)
        bytes_action = "error";
    else if (Py_BytesWarningFlag)
        bytes_action = "default";
    else
        bytes_action = "ignore";
1198
    PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning,
Christian Heimes's avatar
Christian Heimes committed
1199
                    bytes_action));
1200 1201 1202 1203 1204 1205 1206 1207
    /* 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));
1208 1209 1210 1211 1212
    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
1213 1214 1215 1216 1217
    }

    return filters;
}

1218
static struct PyModuleDef warningsmodule = {
1219 1220 1221 1222 1223 1224 1225 1226 1227
        PyModuleDef_HEAD_INIT,
        MODULE_NAME,
        warnings__doc__,
        0,
        warnings_functions,
        NULL,
        NULL,
        NULL,
        NULL
1228 1229
};

Christian Heimes's avatar
Christian Heimes committed
1230 1231 1232 1233

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

1236
    m = PyModule_Create(&warningsmodule);
Christian Heimes's avatar
Christian Heimes committed
1237
    if (m == NULL)
1238
        return NULL;
Christian Heimes's avatar
Christian Heimes committed
1239

1240 1241 1242 1243 1244
    if (_filters == NULL) {
        _filters = init_filters();
        if (_filters == NULL)
            return NULL;
    }
Christian Heimes's avatar
Christian Heimes committed
1245 1246
    Py_INCREF(_filters);
    if (PyModule_AddObject(m, "filters", _filters) < 0)
1247
        return NULL;
Christian Heimes's avatar
Christian Heimes committed
1248

1249 1250 1251 1252 1253
    if (_once_registry == NULL) {
        _once_registry = PyDict_New();
        if (_once_registry == NULL)
            return NULL;
    }
Christian Heimes's avatar
Christian Heimes committed
1254
    Py_INCREF(_once_registry);
1255
    if (PyModule_AddObject(m, "_onceregistry", _once_registry) < 0)
1256
        return NULL;
Christian Heimes's avatar
Christian Heimes committed
1257

1258 1259 1260 1261 1262 1263
    if (_default_action == NULL) {
        _default_action = PyUnicode_FromString("default");
        if (_default_action == NULL)
            return NULL;
    }
    Py_INCREF(_default_action);
1264
    if (PyModule_AddObject(m, "_defaultaction", _default_action) < 0)
1265
        return NULL;
1266 1267

    _filters_version = 0;
1268
    return m;
Christian Heimes's avatar
Christian Heimes committed
1269
}