~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Python/_warnings.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "Python.h"
 
2
#include "frameobject.h"
 
3
 
 
4
#define MODULE_NAME "_warnings"
 
5
#define DEFAULT_ACTION_NAME "default_action"
 
6
 
 
7
PyDoc_STRVAR(warnings__doc__,
 
8
MODULE_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. */
 
13
static PyObject *_filters;  /* List */
 
14
static PyObject *_once_registry;  /* Dict */
 
15
 
 
16
 
 
17
static int
 
18
check_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
*/
 
38
static PyObject *
 
39
get_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 = PyUnicode_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
 
 
64
static PyObject *
 
65
get_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. */
 
82
static const char *
 
83
get_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 = PyLong_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 _PyUnicode_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 _PyUnicode_AsString(action);
 
148
 
 
149
    PyErr_SetString(PyExc_ValueError,
 
150
                    MODULE_NAME "." DEFAULT_ACTION_NAME " not found");
 
151
    return NULL;
 
152
}
 
153
 
 
154
static int
 
155
already_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. */
 
176
static PyObject *
 
177
normalize_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 PyUnicode_FromString("<unknown>");
 
188
 
 
189
    mod_str = _PyUnicode_AsString(filename);
 
190
    if (mod_str == NULL)
 
191
            return NULL;
 
192
    len = PyUnicode_GetSize(filename);
 
193
    if (len < 0)
 
194
        return NULL;
 
195
    if (len >= 3 &&
 
196
        strncmp(mod_str + (len - 3), ".py", 3) == 0) {
 
197
        module = PyUnicode_FromStringAndSize(mod_str, len-3);
 
198
    }
 
199
    else {
 
200
        module = filename;
 
201
        Py_INCREF(module);
 
202
    }
 
203
    return module;
 
204
}
 
205
 
 
206
static int
 
207
update_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 = PyLong_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
 
 
228
static void
 
229
show_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
    if (sourceline) {
 
260
        char *source_line_str = _PyUnicode_AsString(sourceline);
 
261
        if (source_line_str == NULL)
 
262
                return;
 
263
        while (*source_line_str == ' ' || *source_line_str == '\t' ||
 
264
                *source_line_str == '\014')
 
265
            source_line_str++;
 
266
 
 
267
        PyFile_WriteString(source_line_str, f_stderr);
 
268
        PyFile_WriteString("\n", f_stderr);
 
269
    }
 
270
    else
 
271
        if (_Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename),
 
272
                              lineno, 2) < 0)
 
273
                return;
 
274
    PyErr_Clear();
 
275
}
 
276
 
 
277
static PyObject *
 
278
warn_explicit(PyObject *category, PyObject *message, 
 
279
              PyObject *filename, int lineno,
 
280
              PyObject *module, PyObject *registry, PyObject *sourceline)
 
281
{
 
282
    PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
 
283
    PyObject *item = Py_None;
 
284
    const char *action;
 
285
    int rc;
 
286
    
 
287
    if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
 
288
        PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
 
289
        return NULL;
 
290
    }
 
291
 
 
292
    /* Normalize module. */
 
293
    if (module == NULL) {
 
294
        module = normalize_module(filename);
 
295
        if (module == NULL)
 
296
            return NULL;
 
297
    }
 
298
    else
 
299
        Py_INCREF(module);
 
300
 
 
301
    /* Normalize message. */
 
302
    Py_INCREF(message);  /* DECREF'ed in cleanup. */
 
303
    rc = PyObject_IsInstance(message, PyExc_Warning);
 
304
    if (rc == -1) {
 
305
        goto cleanup;
 
306
    }
 
307
    if (rc == 1) {
 
308
        text = PyObject_Str(message);
 
309
        category = (PyObject*)message->ob_type;
 
310
    }
 
311
    else {
 
312
        text = message;
 
313
        message = PyObject_CallFunction(category, "O", message);
 
314
        if (message == NULL)
 
315
            goto cleanup;
 
316
    }
 
317
 
 
318
    lineno_obj = PyLong_FromLong(lineno);
 
319
    if (lineno_obj == NULL)
 
320
        goto cleanup;
 
321
 
 
322
    /* Create key. */
 
323
    key = PyTuple_Pack(3, text, category, lineno_obj);
 
324
    if (key == NULL)
 
325
        goto cleanup;
 
326
 
 
327
    if ((registry != NULL) && (registry != Py_None)) {
 
328
        rc = already_warned(registry, key, 0);
 
329
        if (rc == -1)
 
330
            goto cleanup;
 
331
        else if (rc == 1)
 
332
            goto return_none;
 
333
        /* Else this warning hasn't been generated before. */
 
334
    }
 
335
 
 
336
    action = get_filter(category, text, lineno, module, &item);
 
337
    if (action == NULL)
 
338
        goto cleanup;
 
339
 
 
340
    if (strcmp(action, "error") == 0) {
 
341
        PyErr_SetObject(category, message);
 
342
        goto cleanup;
 
343
    }
 
344
 
 
345
    /* Store in the registry that we've been here, *except* when the action
 
346
       is "always". */
 
347
    rc = 0;
 
348
    if (strcmp(action, "always") != 0) {
 
349
        if (registry != NULL && registry != Py_None &&
 
350
                PyDict_SetItem(registry, key, Py_True) < 0)
 
351
            goto cleanup;
 
352
        else if (strcmp(action, "ignore") == 0)
 
353
            goto return_none;
 
354
        else if (strcmp(action, "once") == 0) {
 
355
            if (registry == NULL || registry == Py_None) {
 
356
                registry = get_once_registry();
 
357
                if (registry == NULL)
 
358
                    goto cleanup;
 
359
            }
 
360
            /* _once_registry[(text, category)] = 1 */
 
361
            rc = update_registry(registry, text, category, 0); 
 
362
        }
 
363
        else if (strcmp(action, "module") == 0) {
 
364
            /* registry[(text, category, 0)] = 1 */
 
365
            if (registry != NULL && registry != Py_None)
 
366
                rc = update_registry(registry, text, category, 0); 
 
367
        }
 
368
        else if (strcmp(action, "default") != 0) {
 
369
            PyObject *to_str = PyObject_Str(item);
 
370
            const char *err_str = "???";
 
371
 
 
372
            if (to_str != NULL) {
 
373
                err_str = _PyUnicode_AsString(to_str);
 
374
                if (err_str == NULL)
 
375
                        goto cleanup;
 
376
            }
 
377
            PyErr_Format(PyExc_RuntimeError,
 
378
                        "Unrecognized action (%s) in warnings.filters:\n %s",
 
379
                        action, err_str);
 
380
            Py_XDECREF(to_str);
 
381
            goto cleanup;
 
382
        }
 
383
    }
 
384
 
 
385
    if (rc == 1)  /* Already warned for this module. */
 
386
        goto return_none;
 
387
    if (rc == 0) {
 
388
        PyObject *show_fxn = get_warnings_attr("showwarning");
 
389
        if (show_fxn == NULL) {
 
390
            if (PyErr_Occurred())
 
391
                goto cleanup;
 
392
            show_warning(filename, lineno, text, category, sourceline);
 
393
        }
 
394
        else {
 
395
            PyObject *res;
 
396
 
 
397
            if (!PyMethod_Check(show_fxn) && !PyFunction_Check(show_fxn)) {
 
398
                PyErr_SetString(PyExc_TypeError,
 
399
                                "warnings.showwarning() must be set to a "
 
400
                                "function or method");
 
401
                Py_DECREF(show_fxn);
 
402
                goto cleanup;
 
403
            }
 
404
 
 
405
            res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
 
406
                                                filename, lineno_obj,
 
407
                                                NULL);
 
408
            Py_DECREF(show_fxn);
 
409
            Py_XDECREF(res);
 
410
            if (res == NULL)
 
411
                goto cleanup;
 
412
        }
 
413
    }
 
414
    else /* if (rc == -1) */
 
415
        goto cleanup;
 
416
 
 
417
 return_none:
 
418
    result = Py_None;
 
419
    Py_INCREF(result);
 
420
 
 
421
 cleanup:
 
422
    Py_XDECREF(key);
 
423
    Py_XDECREF(text);
 
424
    Py_XDECREF(lineno_obj);
 
425
    Py_DECREF(module);
 
426
    Py_XDECREF(message);
 
427
    return result;  /* Py_None or NULL. */
 
428
}
 
429
 
 
430
/* filename, module, and registry are new refs, globals is borrowed */
 
431
/* Returns 0 on error (no new refs), 1 on success */
 
432
static int
 
433
setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
 
434
              PyObject **module, PyObject **registry)
 
435
{
 
436
    PyObject *globals;
 
437
 
 
438
    /* Setup globals and lineno. */
 
439
    PyFrameObject *f = PyThreadState_GET()->frame;
 
440
    while (--stack_level > 0 && f != NULL)
 
441
        f = f->f_back;
 
442
 
 
443
    if (f == NULL) {
 
444
        globals = PyThreadState_Get()->interp->sysdict;
 
445
        *lineno = 1;
 
446
    }
 
447
    else {
 
448
        globals = f->f_globals;
 
449
        *lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
 
450
    }
 
451
 
 
452
    *module = NULL;
 
453
 
 
454
    /* Setup registry. */
 
455
    assert(globals != NULL);
 
456
    assert(PyDict_Check(globals));
 
457
    *registry = PyDict_GetItemString(globals, "__warningregistry__");
 
458
    if (*registry == NULL) {
 
459
        int rc;
 
460
 
 
461
        *registry = PyDict_New();
 
462
        if (*registry == NULL)
 
463
            return 0;
 
464
 
 
465
         rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
 
466
         if (rc < 0)
 
467
            goto handle_error;
 
468
    }
 
469
    else
 
470
        Py_INCREF(*registry);
 
471
 
 
472
    /* Setup module. */
 
473
    *module = PyDict_GetItemString(globals, "__name__");
 
474
    if (*module == NULL) {
 
475
        *module = PyUnicode_FromString("<string>");
 
476
        if (*module == NULL)
 
477
            goto handle_error;
 
478
    }
 
479
    else
 
480
        Py_INCREF(*module);
 
481
 
 
482
    /* Setup filename. */
 
483
    *filename = PyDict_GetItemString(globals, "__file__");
 
484
    if (*filename != NULL) {
 
485
        Py_ssize_t len = PyUnicode_GetSize(*filename);
 
486
        const char *file_str = _PyUnicode_AsString(*filename);
 
487
            if (file_str == NULL || (len < 0 && PyErr_Occurred()))
 
488
            goto handle_error;
 
489
 
 
490
        /* if filename.lower().endswith((".pyc", ".pyo")): */
 
491
        if (len >= 4 &&
 
492
            file_str[len-4] == '.' &&
 
493
            tolower(file_str[len-3]) == 'p' &&
 
494
            tolower(file_str[len-2]) == 'y' &&
 
495
            (tolower(file_str[len-1]) == 'c' ||
 
496
                tolower(file_str[len-1]) == 'o'))
 
497
        {
 
498
            *filename = PyUnicode_FromStringAndSize(file_str, len-1);
 
499
                if (*filename == NULL)
 
500
                        goto handle_error;
 
501
            }
 
502
            else
 
503
            Py_INCREF(*filename);
 
504
    }
 
505
    else {
 
506
        const char *module_str = _PyUnicode_AsString(*module);
 
507
        if (module_str == NULL)
 
508
                goto handle_error;
 
509
        if (strcmp(module_str, "__main__") == 0) {
 
510
            PyObject *argv = PySys_GetObject("argv");
 
511
            if (argv != NULL && PyList_Size(argv) > 0) {
 
512
                int is_true;
 
513
                *filename = PyList_GetItem(argv, 0);
 
514
                Py_INCREF(*filename);
 
515
                /* If sys.argv[0] is false, then use '__main__'. */
 
516
                is_true = PyObject_IsTrue(*filename);
 
517
                if (is_true < 0) {
 
518
                    Py_DECREF(*filename);
 
519
                    goto handle_error;
 
520
                }
 
521
                else if (!is_true) {
 
522
                    Py_DECREF(*filename);
 
523
                    *filename = PyUnicode_FromString("__main__");
 
524
                    if (*filename == NULL)
 
525
                        goto handle_error;
 
526
                }
 
527
            }
 
528
            else {
 
529
                /* embedded interpreters don't have sys.argv, see bug #839151 */
 
530
                *filename = PyUnicode_FromString("__main__");
 
531
                    if (*filename == NULL)
 
532
                        goto handle_error;
 
533
            }
 
534
        }
 
535
        if (*filename == NULL) {
 
536
            *filename = *module;
 
537
            Py_INCREF(*filename);
 
538
        }
 
539
    }
 
540
 
 
541
    return 1;
 
542
 
 
543
 handle_error:
 
544
    /* filename not XDECREF'ed here as there is no way to jump here with a
 
545
       dangling reference. */
 
546
    Py_XDECREF(*registry);
 
547
    Py_XDECREF(*module);
 
548
    return 0;
 
549
}
 
550
 
 
551
static PyObject *
 
552
get_category(PyObject *message, PyObject *category)
 
553
{
 
554
    int rc;
 
555
 
 
556
    /* Get category. */
 
557
    rc = PyObject_IsInstance(message, PyExc_Warning);
 
558
    if (rc == -1)
 
559
        return NULL;
 
560
 
 
561
    if (rc == 1)
 
562
        category = (PyObject*)message->ob_type;
 
563
    else if (category == NULL)
 
564
        category = PyExc_UserWarning;
 
565
 
 
566
    /* Validate category. */
 
567
    rc = PyObject_IsSubclass(category, PyExc_Warning);
 
568
    if (rc == -1)
 
569
        return NULL;
 
570
    if (rc == 0) {
 
571
        PyErr_SetString(PyExc_ValueError,
 
572
                        "category is not a subclass of Warning");
 
573
        return NULL;
 
574
    }
 
575
 
 
576
    return category;
 
577
}
 
578
 
 
579
static PyObject *
 
580
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
 
581
{
 
582
    PyObject *filename, *module, *registry, *res;
 
583
    int lineno;
 
584
 
 
585
    if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
 
586
        return NULL;
 
587
 
 
588
    res = warn_explicit(category, message, filename, lineno, module, registry,
 
589
                        NULL);
 
590
    Py_DECREF(filename);
 
591
    Py_DECREF(registry);
 
592
    Py_DECREF(module);
 
593
    return res;
 
594
}
 
595
 
 
596
static PyObject *
 
597
warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
 
598
{
 
599
    static char *kw_list[] = { "message", "category", "stacklevel", 0 };
 
600
    PyObject *message, *category = NULL;
 
601
    Py_ssize_t stack_level = 1;
 
602
 
 
603
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list, 
 
604
                                     &message, &category, &stack_level))
 
605
        return NULL;
 
606
 
 
607
    category = get_category(message, category);
 
608
    if (category == NULL)
 
609
        return NULL;
 
610
    return do_warn(message, category, stack_level);
 
611
}
 
612
 
 
613
static PyObject *
 
614
warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
 
615
{
 
616
    static char *kwd_list[] = {"message", "category", "filename", "lineno",
 
617
                                "module", "registry", "module_globals", 0};
 
618
    PyObject *message;
 
619
    PyObject *category;
 
620
    PyObject *filename;
 
621
    int lineno;
 
622
    PyObject *module = NULL;
 
623
    PyObject *registry = NULL;
 
624
    PyObject *module_globals = NULL;
 
625
 
 
626
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
 
627
                kwd_list, &message, &category, &filename, &lineno, &module,
 
628
                &registry, &module_globals))
 
629
        return NULL;
 
630
 
 
631
    if (module_globals) {
 
632
        static PyObject *get_source_name = NULL;
 
633
        static PyObject *splitlines_name = NULL;
 
634
        PyObject *loader;
 
635
        PyObject *module_name;
 
636
        PyObject *source;
 
637
        PyObject *source_list;
 
638
        PyObject *source_line;
 
639
        PyObject *returned;
 
640
 
 
641
        if (get_source_name == NULL) {
 
642
            get_source_name = PyUnicode_InternFromString("get_source");
 
643
            if (!get_source_name)
 
644
                return NULL;
 
645
        }
 
646
        if (splitlines_name == NULL) {
 
647
            splitlines_name = PyUnicode_InternFromString("splitlines");
 
648
            if (!splitlines_name)
 
649
                return NULL;
 
650
        }
 
651
 
 
652
        /* Check/get the requisite pieces needed for the loader. */
 
653
        loader = PyDict_GetItemString(module_globals, "__loader__");
 
654
        module_name = PyDict_GetItemString(module_globals, "__name__");
 
655
 
 
656
        if (loader == NULL || module_name == NULL)
 
657
            goto standard_call;
 
658
 
 
659
        /* Make sure the loader implements the optional get_source() method. */
 
660
        if (!PyObject_HasAttrString(loader, "get_source"))
 
661
                goto standard_call;
 
662
        /* Call get_source() to get the source code. */
 
663
        source = PyObject_CallMethodObjArgs(loader, get_source_name,
 
664
                                                module_name, NULL);
 
665
        if (!source)
 
666
            return NULL;
 
667
        else if (source == Py_None) {
 
668
            Py_DECREF(Py_None);
 
669
            goto standard_call;
 
670
        }
 
671
 
 
672
        /* Split the source into lines. */
 
673
        source_list = PyObject_CallMethodObjArgs(source, splitlines_name,
 
674
                                                    NULL);
 
675
        Py_DECREF(source);
 
676
        if (!source_list)
 
677
            return NULL;
 
678
 
 
679
        /* Get the source line. */
 
680
        source_line = PyList_GetItem(source_list, lineno-1);
 
681
        if (!source_line) {
 
682
            Py_DECREF(source_list);
 
683
            return NULL;
 
684
        }
 
685
 
 
686
        /* Handle the warning. */
 
687
        returned = warn_explicit(category, message, filename, lineno, module,
 
688
                            registry, source_line);
 
689
        Py_DECREF(source_list);
 
690
        return returned;
 
691
    }
 
692
 
 
693
 standard_call:
 
694
    return warn_explicit(category, message, filename, lineno, module,
 
695
                                registry, NULL);
 
696
}
 
697
 
 
698
 
 
699
/* Function to issue a warning message; may raise an exception. */
 
700
int
 
701
PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
 
702
{
 
703
    PyObject *res;
 
704
    PyObject *message = PyUnicode_FromString(text);
 
705
    if (message == NULL)
 
706
        return -1;
 
707
 
 
708
    if (category == NULL)
 
709
        category = PyExc_RuntimeWarning;
 
710
 
 
711
    res = do_warn(message, category, stack_level);
 
712
    Py_DECREF(message);
 
713
    if (res == NULL)
 
714
        return -1;
 
715
    Py_DECREF(res);
 
716
 
 
717
    return 0;
 
718
}
 
719
 
 
720
/* PyErr_Warn is only for backwards compatability and will be removed.
 
721
   Use PyErr_WarnEx instead. */
 
722
 
 
723
#undef PyErr_Warn
 
724
 
 
725
PyAPI_FUNC(int)
 
726
PyErr_Warn(PyObject *category, char *text)
 
727
{
 
728
    return PyErr_WarnEx(category, text, 1);
 
729
}
 
730
 
 
731
/* Warning with explicit origin */
 
732
int
 
733
PyErr_WarnExplicit(PyObject *category, const char *text,
 
734
                   const char *filename_str, int lineno,
 
735
                   const char *module_str, PyObject *registry)
 
736
{
 
737
    PyObject *res;
 
738
    PyObject *message = PyUnicode_FromString(text);
 
739
    PyObject *filename = PyUnicode_FromString(filename_str);
 
740
    PyObject *module = NULL;
 
741
    int ret = -1;
 
742
 
 
743
    if (message == NULL || filename == NULL)
 
744
        goto exit;
 
745
    if (module_str != NULL) {
 
746
        module = PyUnicode_FromString(module_str);
 
747
            if (module == NULL)
 
748
                goto exit;
 
749
    }
 
750
 
 
751
    if (category == NULL)
 
752
        category = PyExc_RuntimeWarning;
 
753
    res = warn_explicit(category, message, filename, lineno, module, registry,
 
754
                        NULL);
 
755
    if (res == NULL)
 
756
        goto exit;
 
757
    Py_DECREF(res);
 
758
    ret = 0;
 
759
 
 
760
 exit:
 
761
    Py_XDECREF(message);
 
762
    Py_XDECREF(module);
 
763
    Py_XDECREF(filename);
 
764
    return ret;
 
765
}
 
766
 
 
767
 
 
768
PyDoc_STRVAR(warn_doc,
 
769
"Issue a warning, or maybe ignore it or raise an exception.");
 
770
 
 
771
PyDoc_STRVAR(warn_explicit_doc,
 
772
"Low-level inferface to warnings functionality.");
 
773
 
 
774
static PyMethodDef warnings_functions[] = {
 
775
    {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
 
776
        warn_doc},
 
777
    {"warn_explicit", (PyCFunction)warnings_warn_explicit,
 
778
        METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
 
779
    /* XXX(brett.cannon): add showwarning? */
 
780
    /* XXX(brett.cannon): Reasonable to add formatwarning? */
 
781
    {NULL, NULL}                /* sentinel */
 
782
};
 
783
 
 
784
 
 
785
static PyObject *
 
786
create_filter(PyObject *category, const char *action)
 
787
{
 
788
    static PyObject *ignore_str = NULL;
 
789
    static PyObject *error_str = NULL;
 
790
    static PyObject *default_str = NULL;
 
791
    PyObject *action_obj = NULL;
 
792
    PyObject *lineno, *result;
 
793
 
 
794
    if (!strcmp(action, "ignore")) {
 
795
        if (ignore_str == NULL) {
 
796
            ignore_str = PyUnicode_InternFromString("ignore");
 
797
            if (ignore_str == NULL)
 
798
                return NULL;
 
799
        }
 
800
        action_obj = ignore_str;
 
801
    }
 
802
    else if (!strcmp(action, "error")) {
 
803
        if (error_str == NULL) {
 
804
            error_str = PyUnicode_InternFromString("error");
 
805
            if (error_str == NULL)
 
806
                return NULL;
 
807
        }
 
808
        action_obj = error_str;
 
809
    }
 
810
    else if (!strcmp(action, "default")) {
 
811
        if (default_str == NULL) {
 
812
            default_str = PyUnicode_InternFromString("default");
 
813
            if (default_str == NULL)
 
814
                return NULL;
 
815
        }
 
816
        action_obj = default_str;
 
817
    }
 
818
    else {
 
819
        Py_FatalError("unknown action");
 
820
    }
 
821
 
 
822
    /* This assumes the line number is zero for now. */
 
823
    lineno = PyLong_FromLong(0);
 
824
    if (lineno == NULL)
 
825
        return NULL;
 
826
    result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
 
827
    Py_DECREF(lineno);
 
828
    return result;
 
829
}
 
830
 
 
831
static PyObject *
 
832
init_filters(void)
 
833
{
 
834
    PyObject *filters = PyList_New(3);
 
835
    const char *bytes_action;
 
836
    if (filters == NULL)
 
837
        return NULL;
 
838
 
 
839
    PyList_SET_ITEM(filters, 0,
 
840
                    create_filter(PyExc_PendingDeprecationWarning, "ignore"));
 
841
    PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore"));
 
842
    if (Py_BytesWarningFlag > 1)
 
843
        bytes_action = "error";
 
844
    else if (Py_BytesWarningFlag)
 
845
        bytes_action = "default";
 
846
    else
 
847
        bytes_action = "ignore";
 
848
    PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning,
 
849
                    bytes_action));
 
850
 
 
851
    if (PyList_GET_ITEM(filters, 0) == NULL ||
 
852
        PyList_GET_ITEM(filters, 1) == NULL ||
 
853
        PyList_GET_ITEM(filters, 2) == NULL) {
 
854
        Py_DECREF(filters);
 
855
        return NULL;
 
856
    }
 
857
 
 
858
    return filters;
 
859
}
 
860
 
 
861
static struct PyModuleDef warningsmodule = {
 
862
        PyModuleDef_HEAD_INIT,
 
863
        MODULE_NAME,
 
864
        warnings__doc__,
 
865
        0,
 
866
        warnings_functions,
 
867
        NULL,
 
868
        NULL,
 
869
        NULL,
 
870
        NULL
 
871
};
 
872
 
 
873
 
 
874
PyMODINIT_FUNC
 
875
_PyWarnings_Init(void)
 
876
{
 
877
    PyObject *m, *default_action;
 
878
 
 
879
    m = PyModule_Create(&warningsmodule);
 
880
    if (m == NULL)
 
881
        return NULL;
 
882
 
 
883
    _filters = init_filters();
 
884
    if (_filters == NULL)
 
885
        return NULL;
 
886
    Py_INCREF(_filters);
 
887
    if (PyModule_AddObject(m, "filters", _filters) < 0)
 
888
        return NULL;
 
889
 
 
890
    _once_registry = PyDict_New();
 
891
    if (_once_registry == NULL)
 
892
        return NULL;
 
893
    Py_INCREF(_once_registry);
 
894
    if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
 
895
        return NULL;
 
896
 
 
897
    default_action = PyUnicode_InternFromString("default");
 
898
    if (default_action == NULL)
 
899
        return NULL;
 
900
    if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0)
 
901
        return NULL;
 
902
    return m;
 
903
}