Coverage Report

Created: 2026-03-08 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/_warnings.c
Line
Count
Source
1
#include "Python.h"
2
#include "pycore_frame.h"         // PyFrameObject
3
#include "pycore_genobject.h"     // PyAsyncGenObject
4
#include "pycore_import.h"        // _PyImport_GetModules()
5
#include "pycore_interpframe.h"   // _PyFrame_GetCode()
6
#include "pycore_long.h"          // _PyLong_GetZero()
7
#include "pycore_pylifecycle.h"   // _Py_IsInterpreterFinalizing()
8
#include "pycore_pystate.h"       // _PyThreadState_GET()
9
#include "pycore_traceback.h"     // _Py_DisplaySourceLine()
10
#include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString()
11
12
#include <stdbool.h>
13
#include "clinic/_warnings.c.h"
14
15
16
0
#define MODULE_NAME "_warnings"
17
18
PyDoc_STRVAR(warnings__doc__,
19
MODULE_NAME " provides basic warning filtering support.\n"
20
"It is a helper module to speed up interpreter start-up.");
21
22
23
/*************************************************************************/
24
25
typedef struct _warnings_runtime_state WarningsState;
26
27
static inline int
28
check_interp(PyInterpreterState *interp)
29
2.17M
{
30
2.17M
    if (interp == NULL) {
31
0
        PyErr_SetString(PyExc_RuntimeError,
32
0
                        "warnings_get_state: could not identify "
33
0
                        "current interpreter");
34
0
        return 0;
35
0
    }
36
2.17M
    return 1;
37
2.17M
}
38
39
static inline PyInterpreterState *
40
get_current_interp(void)
41
127k
{
42
127k
    PyInterpreterState *interp = _PyInterpreterState_GET();
43
127k
    return check_interp(interp) ? interp : NULL;
44
127k
}
45
46
static inline PyThreadState *
47
get_current_tstate(void)
48
2.05M
{
49
2.05M
    PyThreadState *tstate = _PyThreadState_GET();
50
2.05M
    if (tstate == NULL) {
51
0
        (void)check_interp(NULL);
52
0
        return NULL;
53
0
    }
54
2.05M
    return check_interp(tstate->interp) ? tstate : NULL;
55
2.05M
}
56
57
/* Given a module object, get its per-module state. */
58
static WarningsState *
59
warnings_get_state(PyInterpreterState *interp)
60
3.86M
{
61
3.86M
    return &interp->warnings;
62
3.86M
}
63
64
/* Clear the given warnings module state. */
65
static void
66
warnings_clear_state(WarningsState *st)
67
0
{
68
0
    Py_CLEAR(st->filters);
69
0
    Py_CLEAR(st->once_registry);
70
0
    Py_CLEAR(st->default_action);
71
0
    Py_CLEAR(st->context);
72
0
}
73
74
#ifndef Py_DEBUG
75
static PyObject *
76
create_filter(PyObject *category, PyObject *action_str, const char *modname)
77
170
{
78
170
    PyObject *modname_obj = NULL;
79
80
    /* Default to "no module name" for initial filter set */
81
170
    if (modname != NULL) {
82
34
        modname_obj = PyUnicode_InternFromString(modname);
83
34
        if (modname_obj == NULL) {
84
0
            return NULL;
85
0
        }
86
136
    } else {
87
136
        modname_obj = Py_NewRef(Py_None);
88
136
    }
89
90
    /* This assumes the line number is zero for now. */
91
170
    PyObject *filter = PyTuple_Pack(5, action_str, Py_None,
92
170
                                    category, modname_obj, _PyLong_GetZero());
93
170
    Py_DECREF(modname_obj);
94
170
    return filter;
95
170
}
96
#endif
97
98
static PyObject *
99
init_filters(PyInterpreterState *interp)
100
34
{
101
#ifdef Py_DEBUG
102
    /* Py_DEBUG builds show all warnings by default */
103
    return PyList_New(0);
104
#else
105
    /* Other builds ignore a number of warning categories by default */
106
34
    PyObject *filters = PyList_New(5);
107
34
    if (filters == NULL) {
108
0
        return NULL;
109
0
    }
110
111
34
    size_t pos = 0;  /* Post-incremented in each use. */
112
34
#define ADD(TYPE, ACTION, MODNAME) \
113
170
    PyList_SET_ITEM(filters, pos++, \
114
170
                    create_filter(TYPE, &_Py_ID(ACTION), MODNAME));
115
34
    ADD(PyExc_DeprecationWarning, default, "__main__");
116
34
    ADD(PyExc_DeprecationWarning, ignore, NULL);
117
34
    ADD(PyExc_PendingDeprecationWarning, ignore, NULL);
118
34
    ADD(PyExc_ImportWarning, ignore, NULL);
119
34
    ADD(PyExc_ResourceWarning, ignore, NULL);
120
34
#undef ADD
121
122
204
    for (size_t x = 0; x < pos; x++) {
123
170
        if (PyList_GET_ITEM(filters, x) == NULL) {
124
0
            Py_DECREF(filters);
125
0
            return NULL;
126
0
        }
127
170
    }
128
34
    return filters;
129
34
#endif
130
34
}
131
132
/* Initialize the given warnings module state. */
133
int
134
_PyWarnings_InitState(PyInterpreterState *interp)
135
34
{
136
34
    WarningsState *st = &interp->warnings;
137
138
34
    if (st->filters == NULL) {
139
34
        st->filters = init_filters(interp);
140
34
        if (st->filters == NULL) {
141
0
            return -1;
142
0
        }
143
34
    }
144
145
34
    if (st->once_registry == NULL) {
146
34
        st->once_registry = PyDict_New();
147
34
        if (st->once_registry == NULL) {
148
0
            return -1;
149
0
        }
150
34
    }
151
152
34
    if (st->default_action == NULL) {
153
34
        st->default_action = PyUnicode_FromString("default");
154
34
        if (st->default_action == NULL) {
155
0
            return -1;
156
0
        }
157
34
    }
158
159
34
    if (st->context == NULL) {
160
34
        st->context = PyContextVar_New("_warnings_context", NULL);
161
34
        if (st->context == NULL) {
162
0
            return -1;
163
0
        }
164
34
    }
165
166
34
    st->filters_version = 0;
167
34
    return 0;
168
34
}
169
170
171
/*************************************************************************/
172
173
static int
174
check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg, PyObject *arg2)
175
2.10M
{
176
2.10M
    PyObject *result;
177
2.10M
    int rc;
178
179
    /* A 'None' filter always matches */
180
2.10M
    if (obj == Py_None)
181
1.89M
        return 1;
182
183
    /* An internal plain text default filter must match exactly */
184
212k
    if (PyUnicode_CheckExact(obj)) {
185
212k
        if (arg == NULL) {
186
0
            return 0;
187
0
        }
188
212k
        int cmp_result = PyUnicode_Compare(obj, arg);
189
212k
        if (cmp_result == -1 && PyErr_Occurred()) {
190
0
            return -1;
191
0
        }
192
212k
        return !cmp_result;
193
212k
    }
194
195
    /* Otherwise assume a regex filter and call its match() method */
196
0
    if (arg != NULL) {
197
0
        result = PyObject_CallMethodOneArg(obj, &_Py_ID(match), arg);
198
0
    }
199
0
    else {
200
0
        PyObject *match = PyImport_ImportModuleAttrString("_py_warnings", "_match_filename");
201
0
        if (match == NULL) {
202
0
            return -1;
203
0
        }
204
0
        result = PyObject_CallFunctionObjArgs(match, obj, arg2, NULL);
205
0
        Py_DECREF(match);
206
0
    }
207
0
    if (result == NULL)
208
0
        return -1;
209
0
    rc = PyObject_IsTrue(result);
210
0
    Py_DECREF(result);
211
0
    return rc;
212
0
}
213
214
#define GET_WARNINGS_ATTR(interp, ATTR, try_import) \
215
841k
    get_warnings_attr(interp, &_Py_ID(ATTR), try_import)
216
217
/*
218
   Returns a new reference.
219
   A NULL return value can mean false or an error.
220
*/
221
static PyObject *
222
get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import)
223
841k
{
224
841k
    PyObject *warnings_module, *obj;
225
226
    /* don't try to import after the start of the Python finallization */
227
841k
    if (try_import && !_Py_IsInterpreterFinalizing(interp)) {
228
205k
        warnings_module = PyImport_Import(&_Py_ID(warnings));
229
205k
        if (warnings_module == NULL) {
230
            /* Fallback to the C implementation if we cannot get
231
               the Python implementation */
232
0
            if (PyErr_ExceptionMatches(PyExc_ImportError)) {
233
0
                PyErr_Clear();
234
0
            }
235
0
            return NULL;
236
0
        }
237
205k
    }
238
635k
    else {
239
        /* if we're so late into Python finalization that the module dict is
240
           gone, then we can't even use PyImport_GetModule without triggering
241
           an interpreter abort.
242
        */
243
635k
        if (!_PyImport_GetModules(interp)) {
244
0
            return NULL;
245
0
        }
246
635k
        warnings_module = PyImport_GetModule(&_Py_ID(warnings));
247
635k
        if (warnings_module == NULL)
248
0
            return NULL;
249
635k
    }
250
251
841k
    (void)PyObject_GetOptionalAttr(warnings_module, attr, &obj);
252
841k
    Py_DECREF(warnings_module);
253
841k
    return obj;
254
841k
}
255
256
static inline void
257
warnings_lock(PyInterpreterState *interp)
258
1.07M
{
259
1.07M
    WarningsState *st = warnings_get_state(interp);
260
1.07M
    assert(st != NULL);
261
1.07M
    _PyRecursiveMutex_Lock(&st->lock);
262
1.07M
}
263
264
static inline int
265
warnings_unlock(PyInterpreterState *interp)
266
1.07M
{
267
1.07M
    WarningsState *st = warnings_get_state(interp);
268
1.07M
    assert(st != NULL);
269
1.07M
    return _PyRecursiveMutex_TryUnlock(&st->lock);
270
1.07M
}
271
272
static inline bool
273
warnings_lock_held(WarningsState *st)
274
42.4k
{
275
42.4k
    return PyMutex_IsLocked(&st->lock.mutex);
276
42.4k
}
277
278
static PyObject *
279
get_warnings_context(PyInterpreterState *interp)
280
223k
{
281
223k
    WarningsState *st = warnings_get_state(interp);
282
223k
    assert(PyContextVar_CheckExact(st->context));
283
223k
    PyObject *ctx;
284
223k
    if (PyContextVar_Get(st->context, NULL, &ctx) < 0) {
285
0
        return NULL;
286
0
    }
287
223k
    if (ctx == NULL) {
288
223k
        Py_RETURN_NONE;
289
223k
    }
290
0
    return ctx;
291
223k
}
292
293
static PyObject *
294
get_warnings_context_filters(PyInterpreterState *interp)
295
223k
{
296
223k
    PyObject *ctx = get_warnings_context(interp);
297
223k
    if (ctx == NULL) {
298
0
        return NULL;
299
0
    }
300
223k
    if (ctx == Py_None) {
301
223k
        Py_RETURN_NONE;
302
223k
    }
303
0
    PyObject *context_filters = PyObject_GetAttr(ctx, &_Py_ID(_filters));
304
0
    Py_DECREF(ctx);
305
0
    if (context_filters == NULL) {
306
0
        return NULL;
307
0
    }
308
0
    if (!PyList_Check(context_filters)) {
309
0
        PyErr_SetString(PyExc_ValueError,
310
0
                        "_filters of warnings._warnings_context must be a list");
311
0
        Py_DECREF(context_filters);
312
0
        return NULL;
313
0
    }
314
0
    return context_filters;
315
0
}
316
317
// Returns a borrowed reference to the list.
318
static PyObject *
319
get_warnings_filters(PyInterpreterState *interp)
320
223k
{
321
223k
    WarningsState *st = warnings_get_state(interp);
322
223k
    PyObject *warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
323
223k
    if (warnings_filters == NULL) {
324
0
        if (PyErr_Occurred())
325
0
            return NULL;
326
0
    }
327
223k
    else {
328
223k
        Py_SETREF(st->filters, warnings_filters);
329
223k
    }
330
331
223k
    PyObject *filters = st->filters;
332
223k
    if (filters == NULL || !PyList_Check(filters)) {
333
0
        PyErr_SetString(PyExc_ValueError,
334
0
                        MODULE_NAME ".filters must be a list");
335
0
        return NULL;
336
0
    }
337
223k
    return filters;
338
223k
}
339
340
/*[clinic input]
341
_acquire_lock as warnings_acquire_lock
342
343
[clinic start generated code]*/
344
345
static PyObject *
346
warnings_acquire_lock_impl(PyObject *module)
347
/*[clinic end generated code: output=594313457d1bf8e1 input=46ec20e55acca52f]*/
348
42.4k
{
349
42.4k
    PyInterpreterState *interp = get_current_interp();
350
42.4k
    if (interp == NULL) {
351
0
        return NULL;
352
0
    }
353
42.4k
    warnings_lock(interp);
354
42.4k
    Py_RETURN_NONE;
355
42.4k
}
356
357
/*[clinic input]
358
_release_lock as warnings_release_lock
359
360
[clinic start generated code]*/
361
362
static PyObject *
363
warnings_release_lock_impl(PyObject *module)
364
/*[clinic end generated code: output=d73d5a8789396750 input=ea01bb77870c5693]*/
365
42.4k
{
366
42.4k
    PyInterpreterState *interp = get_current_interp();
367
42.4k
    if (interp == NULL) {
368
0
        return NULL;
369
0
    }
370
42.4k
    if (warnings_unlock(interp) < 0) {
371
0
        PyErr_SetString(PyExc_RuntimeError, "cannot release un-acquired lock");
372
0
        return NULL;
373
0
    }
374
42.4k
    Py_RETURN_NONE;
375
42.4k
}
376
377
static PyObject *
378
get_once_registry(PyInterpreterState *interp)
379
0
{
380
0
    WarningsState *st = warnings_get_state(interp);
381
0
    assert(st != NULL);
382
383
0
    assert(warnings_lock_held(st));
384
385
0
    PyObject *registry = GET_WARNINGS_ATTR(interp, onceregistry, 0);
386
0
    if (registry == NULL) {
387
0
        if (PyErr_Occurred())
388
0
            return NULL;
389
0
        assert(st->once_registry);
390
0
        return st->once_registry;
391
0
    }
392
0
    if (!PyDict_Check(registry)) {
393
0
        PyErr_Format(PyExc_TypeError,
394
0
                     MODULE_NAME ".onceregistry must be a dict, "
395
0
                     "not '%.200s'",
396
0
                     Py_TYPE(registry)->tp_name);
397
0
        Py_DECREF(registry);
398
0
        return NULL;
399
0
    }
400
0
    Py_SETREF(st->once_registry, registry);
401
0
    return registry;
402
0
}
403
404
405
static PyObject *
406
get_default_action(PyInterpreterState *interp)
407
205k
{
408
205k
    WarningsState *st = warnings_get_state(interp);
409
205k
    assert(st != NULL);
410
411
205k
    assert(warnings_lock_held(st));
412
413
205k
    PyObject *default_action = GET_WARNINGS_ATTR(interp, defaultaction, 0);
414
205k
    if (default_action == NULL) {
415
0
        if (PyErr_Occurred()) {
416
0
            return NULL;
417
0
        }
418
0
        assert(st->default_action);
419
0
        return st->default_action;
420
0
    }
421
205k
    if (!PyUnicode_Check(default_action)) {
422
0
        PyErr_Format(PyExc_TypeError,
423
0
                     MODULE_NAME ".defaultaction must be a string, "
424
0
                     "not '%.200s'",
425
0
                     Py_TYPE(default_action)->tp_name);
426
0
        Py_DECREF(default_action);
427
0
        return NULL;
428
0
    }
429
205k
    Py_SETREF(st->default_action, default_action);
430
205k
    return default_action;
431
205k
}
432
433
/* Search filters list of match, returns false on error.  If no match
434
 * then 'matched_action' is NULL.  */
435
static bool
436
filter_search(PyInterpreterState *interp, PyObject *category,
437
              PyObject *text, Py_ssize_t lineno,
438
              PyObject *module, PyObject *filename, char *list_name, PyObject *filters,
439
223k
              PyObject **item, PyObject **matched_action) {
440
223k
    bool result = true;
441
223k
    *matched_action = NULL;
442
    /* Avoid the filters list changing while we iterate over it. */
443
223k
    Py_BEGIN_CRITICAL_SECTION(filters);
444
1.25M
    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(filters); i++) {
445
1.05M
        PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
446
1.05M
        Py_ssize_t ln;
447
1.05M
        int is_subclass, good_msg, good_mod;
448
449
1.05M
        tmp_item = PyList_GET_ITEM(filters, i);
450
1.05M
        if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {
451
0
            PyErr_Format(PyExc_ValueError,
452
0
                         "warnings.%s item %zd isn't a 5-tuple", list_name, i);
453
0
            result = false;
454
0
            break;
455
0
        }
456
457
        /* Python code: action, msg, cat, mod, ln = item */
458
1.05M
        Py_INCREF(tmp_item);
459
1.05M
        action = PyTuple_GET_ITEM(tmp_item, 0);
460
1.05M
        msg = PyTuple_GET_ITEM(tmp_item, 1);
461
1.05M
        cat = PyTuple_GET_ITEM(tmp_item, 2);
462
1.05M
        mod = PyTuple_GET_ITEM(tmp_item, 3);
463
1.05M
        ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
464
465
1.05M
        if (!PyUnicode_Check(action)) {
466
0
            PyErr_Format(PyExc_TypeError,
467
0
                         "action must be a string, not '%.200s'",
468
0
                         Py_TYPE(action)->tp_name);
469
0
            Py_DECREF(tmp_item);
470
0
            result = false;
471
0
            break;
472
0
        }
473
474
1.05M
        good_msg = check_matched(interp, msg, text, NULL);
475
1.05M
        if (good_msg == -1) {
476
0
            Py_DECREF(tmp_item);
477
0
            result = false;
478
0
            break;
479
0
        }
480
481
1.05M
        good_mod = check_matched(interp, mod, module, filename);
482
1.05M
        if (good_mod == -1) {
483
0
            Py_DECREF(tmp_item);
484
0
            result = false;
485
0
            break;
486
0
        }
487
488
1.05M
        is_subclass = PyObject_IsSubclass(category, cat);
489
1.05M
        if (is_subclass == -1) {
490
0
            Py_DECREF(tmp_item);
491
0
            result = false;
492
0
            break;
493
0
        }
494
495
1.05M
        ln = PyLong_AsSsize_t(ln_obj);
496
1.05M
        if (ln == -1 && PyErr_Occurred()) {
497
0
            Py_DECREF(tmp_item);
498
0
            result = false;
499
0
            break;
500
0
        }
501
502
1.05M
        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
503
17.3k
            *item = tmp_item;
504
17.3k
            *matched_action = action;
505
17.3k
            result = true;
506
17.3k
            break;
507
17.3k
        }
508
509
1.03M
        Py_DECREF(tmp_item);
510
1.03M
    }
511
223k
    Py_END_CRITICAL_SECTION();
512
223k
    return result;
513
223k
}
514
515
/* The item is a new reference. */
516
static PyObject*
517
get_filter(PyInterpreterState *interp, PyObject *category,
518
           PyObject *text, Py_ssize_t lineno,
519
           PyObject *module, PyObject *filename, PyObject **item)
520
223k
{
521
#ifdef Py_DEBUG
522
    WarningsState *st = warnings_get_state(interp);
523
    assert(st != NULL);
524
    assert(warnings_lock_held(st));
525
#endif
526
527
    /* check _warning_context _filters list */
528
223k
    PyObject *context_filters = get_warnings_context_filters(interp);
529
223k
    if (context_filters == NULL) {
530
0
        return NULL;
531
0
    }
532
223k
    bool use_global_filters = false;
533
223k
    if (context_filters == Py_None) {
534
223k
        use_global_filters = true;
535
223k
    } else {
536
0
        PyObject *context_action = NULL;
537
0
        if (!filter_search(interp, category, text, lineno, module, filename, "_warnings_context _filters",
538
0
                           context_filters, item, &context_action)) {
539
0
            Py_DECREF(context_filters);
540
0
            return NULL;
541
0
        }
542
0
        Py_DECREF(context_filters);
543
0
        if (context_action != NULL) {
544
0
            return context_action;
545
0
        }
546
0
    }
547
548
223k
    PyObject *action;
549
550
223k
    if (use_global_filters) {
551
        /* check warnings.filters list */
552
223k
        PyObject *filters = get_warnings_filters(interp);
553
223k
        if (filters == NULL) {
554
0
            return NULL;
555
0
        }
556
223k
        if (!filter_search(interp, category, text, lineno, module, filename, "filters",
557
223k
                           filters, item, &action)) {
558
0
            return NULL;
559
0
        }
560
223k
        if (action != NULL) {
561
17.3k
            return action;
562
17.3k
        }
563
223k
    }
564
565
205k
    action = get_default_action(interp);
566
205k
    if (action != NULL) {
567
205k
        *item = Py_NewRef(Py_None);
568
205k
        return action;
569
205k
    }
570
571
0
    return NULL;
572
205k
}
573
574
575
static int
576
already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,
577
               int should_set)
578
1.02M
{
579
1.02M
    PyObject *already_warned;
580
581
1.02M
    if (key == NULL)
582
0
        return -1;
583
584
1.02M
    WarningsState *st = warnings_get_state(interp);
585
1.02M
    assert(st != NULL);
586
1.02M
    assert(warnings_lock_held(st));
587
588
1.02M
    PyObject *version_obj;
589
1.02M
    if (PyDict_GetItemRef(registry, &_Py_ID(version), &version_obj) < 0) {
590
0
        return -1;
591
0
    }
592
1.02M
    bool should_update_version = (
593
1.02M
        version_obj == NULL
594
1.02M
        || !PyLong_CheckExact(version_obj)
595
1.02M
        || PyLong_AsLong(version_obj) != st->filters_version
596
1.02M
    );
597
1.02M
    Py_XDECREF(version_obj);
598
1.02M
    if (should_update_version) {
599
6.27k
        PyDict_Clear(registry);
600
6.27k
        version_obj = PyLong_FromLong(st->filters_version);
601
6.27k
        if (version_obj == NULL)
602
0
            return -1;
603
6.27k
        if (PyDict_SetItem(registry, &_Py_ID(version), version_obj) < 0) {
604
0
            Py_DECREF(version_obj);
605
0
            return -1;
606
0
        }
607
6.27k
        Py_DECREF(version_obj);
608
6.27k
    }
609
1.01M
    else {
610
1.01M
        if (PyDict_GetItemRef(registry, key, &already_warned) < 0) {
611
0
            return -1;
612
0
        }
613
1.01M
        if (already_warned != NULL) {
614
808k
            int rc = PyObject_IsTrue(already_warned);
615
808k
            Py_DECREF(already_warned);
616
808k
            if (rc != 0)
617
808k
                return rc;
618
808k
        }
619
1.01M
    }
620
621
    /* This warning wasn't found in the registry, set it. */
622
212k
    if (should_set)
623
0
        return PyDict_SetItem(registry, key, Py_True);
624
212k
    return 0;
625
212k
}
626
627
static int
628
update_registry(PyInterpreterState *interp, PyObject *registry, PyObject *text,
629
                PyObject *category, int add_zero)
630
0
{
631
0
    PyObject *altkey;
632
0
    int rc;
633
634
0
    if (add_zero)
635
0
        altkey = PyTuple_Pack(3, text, category, _PyLong_GetZero());
636
0
    else
637
0
        altkey = PyTuple_Pack(2, text, category);
638
639
0
    rc = already_warned(interp, registry, altkey, 1);
640
0
    Py_XDECREF(altkey);
641
0
    return rc;
642
0
}
643
644
static void
645
show_warning(PyThreadState *tstate, PyObject *filename, int lineno,
646
             PyObject *text, PyObject *category, PyObject *sourceline)
647
0
{
648
0
    PyObject *f_stderr = NULL;
649
0
    PyObject *name;
650
0
    char lineno_str[128];
651
652
0
    PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
653
654
0
    name = PyObject_GetAttr(category, &_Py_ID(__name__));
655
0
    if (name == NULL) {
656
0
        goto error;
657
0
    }
658
659
0
    if (PySys_GetOptionalAttr(&_Py_ID(stderr), &f_stderr) <= 0) {
660
0
        fprintf(stderr, "lost sys.stderr\n");
661
0
        goto error;
662
0
    }
663
664
    /* Print "filename:lineno: category: text\n" */
665
0
    if (PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW) < 0)
666
0
        goto error;
667
0
    if (PyFile_WriteString(lineno_str, f_stderr) < 0)
668
0
        goto error;
669
0
    if (PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW) < 0)
670
0
        goto error;
671
0
    if (PyFile_WriteString(": ", f_stderr) < 0)
672
0
        goto error;
673
0
    if (PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW) < 0)
674
0
        goto error;
675
0
    if (PyFile_WriteString("\n", f_stderr) < 0)
676
0
        goto error;
677
0
    Py_CLEAR(name);
678
679
    /* Print "  source_line\n" */
680
0
    if (sourceline) {
681
0
        int kind;
682
0
        const void *data;
683
0
        Py_ssize_t i, len;
684
0
        Py_UCS4 ch;
685
0
        PyObject *truncated;
686
687
0
        kind = PyUnicode_KIND(sourceline);
688
0
        data = PyUnicode_DATA(sourceline);
689
0
        len = PyUnicode_GET_LENGTH(sourceline);
690
0
        for (i=0; i<len; i++) {
691
0
            ch = PyUnicode_READ(kind, data, i);
692
0
            if (ch != ' ' && ch != '\t' && ch != '\014')
693
0
                break;
694
0
        }
695
696
0
        truncated = PyUnicode_Substring(sourceline, i, len);
697
0
        if (truncated == NULL)
698
0
            goto error;
699
700
0
        PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW);
701
0
        Py_DECREF(truncated);
702
0
        PyFile_WriteString("\n", f_stderr);
703
0
    }
704
0
    else {
705
0
        _Py_DisplaySourceLine(f_stderr, filename, lineno, 2, NULL, NULL);
706
0
    }
707
708
0
error:
709
0
    Py_XDECREF(f_stderr);
710
0
    Py_XDECREF(name);
711
0
    PyErr_Clear();
712
0
}
713
714
static int
715
call_show_warning(PyThreadState *tstate, PyObject *category,
716
                  PyObject *text, PyObject *message,
717
                  PyObject *filename, int lineno, PyObject *lineno_obj,
718
                  PyObject *sourceline, PyObject *source)
719
205k
{
720
205k
    PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;
721
205k
    PyInterpreterState *interp = tstate->interp;
722
723
    /* The Python implementation is able to log the traceback where the source
724
       was allocated, whereas the C implementation doesn't. */
725
205k
    show_fn = GET_WARNINGS_ATTR(interp, _showwarnmsg, 1);
726
205k
    if (show_fn == NULL) {
727
0
        if (PyErr_Occurred())
728
0
            return -1;
729
0
        show_warning(tstate, filename, lineno, text, category, sourceline);
730
0
        return 0;
731
0
    }
732
733
205k
    if (!PyCallable_Check(show_fn)) {
734
0
        PyErr_SetString(PyExc_TypeError,
735
0
                "warnings._showwarnmsg() must be set to a callable");
736
0
        goto error;
737
0
    }
738
739
205k
    warnmsg_cls = GET_WARNINGS_ATTR(interp, WarningMessage, 0);
740
205k
    if (warnmsg_cls == NULL) {
741
0
        if (!PyErr_Occurred()) {
742
0
            PyErr_SetString(PyExc_RuntimeError,
743
0
                    "unable to get warnings.WarningMessage");
744
0
        }
745
0
        goto error;
746
0
    }
747
748
205k
    msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category,
749
205k
            filename, lineno_obj, Py_None, Py_None, source,
750
205k
            NULL);
751
205k
    Py_DECREF(warnmsg_cls);
752
205k
    if (msg == NULL)
753
0
        goto error;
754
755
205k
    res = PyObject_CallOneArg(show_fn, msg);
756
205k
    Py_DECREF(show_fn);
757
205k
    Py_DECREF(msg);
758
759
205k
    if (res == NULL)
760
0
        return -1;
761
762
205k
    Py_DECREF(res);
763
205k
    return 0;
764
765
0
error:
766
0
    Py_XDECREF(show_fn);
767
0
    return -1;
768
205k
}
769
770
static PyObject *
771
warn_explicit(PyThreadState *tstate, PyObject *category, PyObject *message,
772
              PyObject *filename, int lineno,
773
              PyObject *module, PyObject *registry, PyObject *sourceline,
774
              PyObject *source)
775
1.03M
{
776
1.03M
    PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
777
1.03M
    PyObject *item = NULL;
778
1.03M
    PyObject *action;
779
1.03M
    int rc;
780
1.03M
    PyInterpreterState *interp = tstate->interp;
781
782
    /* module can be None if a warning is emitted late during Python shutdown.
783
       In this case, the Python warnings module was probably unloaded, filters
784
       are no more available to choose as action. It is safer to ignore the
785
       warning and do nothing. */
786
1.03M
    if (module == Py_None)
787
0
        Py_RETURN_NONE;
788
789
1.03M
    if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
790
0
        PyErr_SetString(PyExc_TypeError, "'registry' must be a dict or None");
791
0
        return NULL;
792
0
    }
793
794
    /* Normalize message. */
795
1.03M
    Py_INCREF(message);  /* DECREF'ed in cleanup. */
796
1.03M
    if (PyObject_TypeCheck(message, (PyTypeObject *)PyExc_Warning)) {
797
0
        text = PyObject_Str(message);
798
0
        if (text == NULL)
799
0
            goto cleanup;
800
0
        category = (PyObject*)Py_TYPE(message);
801
0
    }
802
1.03M
    else {
803
1.03M
        text = message;
804
1.03M
        message = PyObject_CallOneArg(category, message);
805
1.03M
        if (message == NULL)
806
0
            goto cleanup;
807
1.03M
    }
808
809
1.03M
    lineno_obj = PyLong_FromLong(lineno);
810
1.03M
    if (lineno_obj == NULL)
811
0
        goto cleanup;
812
813
1.03M
    if (source == Py_None) {
814
1.02M
        source = NULL;
815
1.02M
    }
816
817
    /* Create key. */
818
1.03M
    key = PyTuple_Pack(3, text, category, lineno_obj);
819
1.03M
    if (key == NULL)
820
0
        goto cleanup;
821
822
1.03M
    if ((registry != NULL) && (registry != Py_None)) {
823
1.02M
        rc = already_warned(interp, registry, key, 0);
824
1.02M
        if (rc == -1)
825
0
            goto cleanup;
826
1.02M
        else if (rc == 1)
827
808k
            goto return_none;
828
        /* Else this warning hasn't been generated before. */
829
1.02M
    }
830
831
223k
    action = get_filter(interp, category, text, lineno, module, filename, &item);
832
223k
    if (action == NULL)
833
0
        goto cleanup;
834
835
223k
    if (_PyUnicode_EqualToASCIIString(action, "error")) {
836
0
        PyErr_SetObject(category, message);
837
0
        goto cleanup;
838
0
    }
839
840
223k
    if (_PyUnicode_EqualToASCIIString(action, "ignore")) {
841
17.3k
        goto return_none;
842
17.3k
    }
843
844
    /* Store in the registry that we've been here, *except* when the action
845
       is "always" or "all". */
846
205k
    rc = 0;
847
205k
    if (!_PyUnicode_EqualToASCIIString(action, "always") && !_PyUnicode_EqualToASCIIString(action, "all")) {
848
205k
        if (registry != NULL && registry != Py_None &&
849
205k
            PyDict_SetItem(registry, key, Py_True) < 0)
850
0
        {
851
0
            goto cleanup;
852
0
        }
853
854
205k
        if (_PyUnicode_EqualToASCIIString(action, "once")) {
855
0
            if (registry == NULL || registry == Py_None) {
856
0
                registry = get_once_registry(interp);
857
0
                if (registry == NULL)
858
0
                    goto cleanup;
859
0
            }
860
            /* WarningsState.once_registry[(text, category)] = 1 */
861
0
            rc = update_registry(interp, registry, text, category, 0);
862
0
        }
863
205k
        else if (_PyUnicode_EqualToASCIIString(action, "module")) {
864
            /* registry[(text, category, 0)] = 1 */
865
0
            if (registry != NULL && registry != Py_None)
866
0
                rc = update_registry(interp, registry, text, category, 0);
867
0
        }
868
205k
        else if (!_PyUnicode_EqualToASCIIString(action, "default")) {
869
0
            PyErr_Format(PyExc_RuntimeError,
870
0
                        "Unrecognized action (%R) in warnings.filters:\n %R",
871
0
                        action, item);
872
0
            goto cleanup;
873
0
        }
874
205k
    }
875
876
205k
    if (rc == 1)  /* Already warned for this module. */
877
0
        goto return_none;
878
205k
    if (rc == 0) {
879
205k
        if (call_show_warning(tstate, category, text, message, filename,
880
205k
                              lineno, lineno_obj, sourceline, source) < 0)
881
0
            goto cleanup;
882
205k
    }
883
0
    else /* if (rc == -1) */
884
0
        goto cleanup;
885
886
1.03M
 return_none:
887
1.03M
    result = Py_NewRef(Py_None);
888
889
1.03M
 cleanup:
890
1.03M
    Py_XDECREF(item);
891
1.03M
    Py_XDECREF(key);
892
1.03M
    Py_XDECREF(text);
893
1.03M
    Py_XDECREF(lineno_obj);
894
1.03M
    Py_XDECREF(message);
895
1.03M
    return result;  /* Py_None or NULL. */
896
1.03M
}
897
898
static PyObject *
899
get_frame_filename(PyFrameObject *frame)
900
13.3M
{
901
13.3M
    PyCodeObject *code = PyFrame_GetCode(frame);
902
13.3M
    PyObject *filename = code->co_filename;
903
13.3M
    Py_DECREF(code);
904
13.3M
    return filename;
905
13.3M
}
906
907
static bool
908
is_internal_filename(PyObject *filename)
909
13.3M
{
910
13.3M
    if (!PyUnicode_Check(filename)) {
911
0
        return false;
912
0
    }
913
914
13.3M
    int contains = PyUnicode_Contains(filename, &_Py_ID(importlib));
915
13.3M
    if (contains < 0) {
916
0
        return false;
917
0
    }
918
13.3M
    else if (contains > 0) {
919
0
        contains = PyUnicode_Contains(filename, &_Py_ID(_bootstrap));
920
0
        if (contains < 0) {
921
0
            return false;
922
0
        }
923
0
        else if (contains > 0) {
924
0
            return true;
925
0
        }
926
0
    }
927
928
13.3M
    return false;
929
13.3M
}
930
931
static bool
932
is_filename_to_skip(PyObject *filename, PyTupleObject *skip_file_prefixes)
933
12.2M
{
934
12.2M
    if (skip_file_prefixes) {
935
135
        if (!PyUnicode_Check(filename)) {
936
0
            return false;
937
0
        }
938
939
135
        Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
940
180
        for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
941
135
        {
942
135
            PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
943
135
            Py_ssize_t found = PyUnicode_Tailmatch(filename, prefix,
944
135
                                                   0, PY_SSIZE_T_MAX, -1);
945
135
            if (found == 1) {
946
90
                return true;
947
90
            }
948
45
            if (found < 0) {
949
0
                return false;
950
0
            }
951
45
        }
952
135
    }
953
12.2M
    return false;
954
12.2M
}
955
956
static bool
957
is_internal_frame(PyFrameObject *frame)
958
1.02M
{
959
1.02M
    if (frame == NULL) {
960
0
        return false;
961
0
    }
962
963
1.02M
    PyObject *filename = get_frame_filename(frame);
964
1.02M
    if (filename == NULL) {
965
0
        return false;
966
0
    }
967
968
1.02M
    return is_internal_filename(filename);
969
1.02M
}
970
971
static PyFrameObject *
972
next_external_frame(PyFrameObject *frame, PyTupleObject *skip_file_prefixes)
973
12.2M
{
974
12.2M
    PyObject *frame_filename;
975
12.2M
    do {
976
12.2M
        PyFrameObject *back = PyFrame_GetBack(frame);
977
12.2M
        Py_SETREF(frame, back);
978
12.2M
    } while (frame != NULL && (frame_filename = get_frame_filename(frame)) &&
979
12.2M
             (is_internal_filename(frame_filename) ||
980
12.2M
              is_filename_to_skip(frame_filename, skip_file_prefixes)));
981
982
12.2M
    return frame;
983
12.2M
}
984
985
/* filename, module, and registry are new refs, globals is borrowed */
986
/* skip_file_prefixes is either NULL or a tuple of strs. */
987
/* Returns 0 on error (no new refs), 1 on success */
988
static int
989
setup_context(Py_ssize_t stack_level,
990
              PyTupleObject *skip_file_prefixes,
991
              PyObject **filename, int *lineno,
992
              PyObject **module, PyObject **registry)
993
1.02M
{
994
1.02M
    PyObject *globals;
995
996
    /* Setup globals, filename and lineno. */
997
1.02M
    PyThreadState *tstate = get_current_tstate();
998
1.02M
    if (tstate == NULL) {
999
0
        return 0;
1000
0
    }
1001
1.02M
    if (skip_file_prefixes) {
1002
        /* Type check our data structure up front. Later code that uses it
1003
         * isn't structured to report errors. */
1004
45
        Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
1005
90
        for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
1006
45
        {
1007
45
            PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
1008
45
            if (!PyUnicode_Check(prefix)) {
1009
0
                PyErr_Format(PyExc_TypeError,
1010
0
                             "Found non-str '%s' in skip_file_prefixes.",
1011
0
                             Py_TYPE(prefix)->tp_name);
1012
0
                return 0;
1013
0
            }
1014
45
        }
1015
45
    }
1016
1.02M
    PyInterpreterState *interp = tstate->interp;
1017
1.02M
    PyFrameObject *f = PyThreadState_GetFrame(tstate);
1018
    // Stack level comparisons to Python code is off by one as there is no
1019
    // warnings-related stack level to avoid.
1020
1.02M
    if (stack_level <= 0 || is_internal_frame(f)) {
1021
0
        while (--stack_level > 0 && f != NULL) {
1022
0
            PyFrameObject *back = PyFrame_GetBack(f);
1023
0
            Py_SETREF(f, back);
1024
0
        }
1025
0
    }
1026
1.02M
    else {
1027
13.3M
        while (--stack_level > 0 && f != NULL) {
1028
12.2M
            f = next_external_frame(f, skip_file_prefixes);
1029
12.2M
        }
1030
1.02M
    }
1031
1032
1.02M
    if (f == NULL) {
1033
0
        globals = interp->sysdict;
1034
0
        *filename = PyUnicode_FromString("<sys>");
1035
0
        *lineno = 0;
1036
0
    }
1037
1.02M
    else {
1038
1.02M
        globals = f->f_frame->f_globals;
1039
1.02M
        *filename = Py_NewRef(_PyFrame_GetCode(f->f_frame)->co_filename);
1040
1.02M
        *lineno = PyFrame_GetLineNumber(f);
1041
1.02M
        Py_DECREF(f);
1042
1.02M
    }
1043
1044
1.02M
    *module = NULL;
1045
1046
    /* Setup registry. */
1047
1.02M
    assert(globals != NULL);
1048
1.02M
    assert(PyAnyDict_Check(globals));
1049
1.02M
    int rc = PyDict_GetItemRef(globals, &_Py_ID(__warningregistry__),
1050
1.02M
                               registry);
1051
1.02M
    if (rc < 0) {
1052
0
        goto handle_error;
1053
0
    }
1054
1.02M
    if (*registry == NULL) {
1055
6
        *registry = PyDict_New();
1056
6
        if (*registry == NULL)
1057
0
            goto handle_error;
1058
1059
6
         rc = PyDict_SetItem(globals, &_Py_ID(__warningregistry__), *registry);
1060
6
         if (rc < 0)
1061
0
            goto handle_error;
1062
6
    }
1063
1064
    /* Setup module. */
1065
1.02M
    rc = PyDict_GetItemRef(globals, &_Py_ID(__name__), module);
1066
1.02M
    if (rc < 0) {
1067
0
        goto handle_error;
1068
0
    }
1069
1.02M
    if (rc > 0) {
1070
1.02M
        if (Py_IsNone(*module) || PyUnicode_Check(*module)) {
1071
1.02M
            return 1;
1072
1.02M
        }
1073
0
        Py_DECREF(*module);
1074
0
    }
1075
0
    *module = PyUnicode_FromString("<string>");
1076
0
    if (*module == NULL) {
1077
0
        goto handle_error;
1078
0
    }
1079
1080
0
    return 1;
1081
1082
0
 handle_error:
1083
0
    Py_XDECREF(*registry);
1084
0
    Py_XDECREF(*module);
1085
0
    Py_DECREF(*filename);
1086
0
    return 0;
1087
0
}
1088
1089
static PyObject *
1090
get_category(PyObject *message, PyObject *category)
1091
1.02M
{
1092
1.02M
    if (PyObject_TypeCheck(message, (PyTypeObject *)PyExc_Warning)) {
1093
        /* Ignore the category argument. */
1094
0
        return (PyObject*)Py_TYPE(message);
1095
0
    }
1096
1.02M
    if (category == NULL || category == Py_None) {
1097
6.31k
        return PyExc_UserWarning;
1098
6.31k
    }
1099
1100
    /* Validate category. */
1101
1.01M
    if (!PyType_Check(category)) {
1102
0
        PyErr_Format(PyExc_TypeError,
1103
0
                     "category must be a Warning subclass, not '%T'",
1104
0
                     category);
1105
0
        return NULL;
1106
0
    }
1107
1.01M
    if (!PyType_IsSubtype((PyTypeObject *)category, (PyTypeObject *)PyExc_Warning)) {
1108
0
        PyErr_Format(PyExc_TypeError,
1109
0
                     "category must be a Warning subclass, not class '%N'",
1110
0
                     (PyTypeObject *)category);
1111
0
        return NULL;
1112
0
    }
1113
1114
1.01M
    return category;
1115
1.01M
}
1116
1117
static PyObject *
1118
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
1119
        PyObject *source, PyTupleObject *skip_file_prefixes)
1120
1.02M
{
1121
1.02M
    PyObject *filename, *module, *registry, *res;
1122
1.02M
    int lineno;
1123
1124
1.02M
    PyThreadState *tstate = get_current_tstate();
1125
1.02M
    if (tstate == NULL) {
1126
0
        return NULL;
1127
0
    }
1128
1129
1.02M
    if (!setup_context(stack_level, skip_file_prefixes,
1130
1.02M
                       &filename, &lineno, &module, &registry))
1131
0
        return NULL;
1132
1133
1.02M
    warnings_lock(tstate->interp);
1134
1.02M
    res = warn_explicit(tstate, category, message, filename, lineno, module, registry,
1135
1.02M
                        NULL, source);
1136
1.02M
    warnings_unlock(tstate->interp);
1137
1.02M
    Py_DECREF(filename);
1138
1.02M
    Py_DECREF(registry);
1139
1.02M
    Py_DECREF(module);
1140
1.02M
    return res;
1141
1.02M
}
1142
1143
/*[clinic input]
1144
warn as warnings_warn
1145
1146
    message: object
1147
      Text of the warning message.
1148
    category: object = None
1149
      The Warning category subclass. Defaults to UserWarning.
1150
    stacklevel: Py_ssize_t = 1
1151
      How far up the call stack to make this warning appear. A value of 2 for
1152
      example attributes the warning to the caller of the code calling warn().
1153
    source: object = None
1154
      If supplied, the destroyed object which emitted a ResourceWarning
1155
    *
1156
    skip_file_prefixes: object(type='PyTupleObject *', subclass_of='&PyTuple_Type') = NULL
1157
      An optional tuple of module filename prefixes indicating frames to skip
1158
      during stacklevel computations for stack frame attribution.
1159
1160
Issue a warning, or maybe ignore it or raise an exception.
1161
[clinic start generated code]*/
1162
1163
static PyObject *
1164
warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
1165
                   Py_ssize_t stacklevel, PyObject *source,
1166
                   PyTupleObject *skip_file_prefixes)
1167
/*[clinic end generated code: output=a68e0f6906c65f80 input=eb37c6a18bec4ea1]*/
1168
1.02M
{
1169
1.02M
    category = get_category(message, category);
1170
1.02M
    if (category == NULL)
1171
0
        return NULL;
1172
1.02M
    if (skip_file_prefixes) {
1173
45
        if (PyTuple_GET_SIZE(skip_file_prefixes) > 0) {
1174
45
            if (stacklevel < 2) {
1175
45
                stacklevel = 2;
1176
45
            }
1177
45
        } else {
1178
0
            Py_DECREF((PyObject *)skip_file_prefixes);
1179
0
            skip_file_prefixes = NULL;
1180
0
        }
1181
45
    }
1182
1.02M
    return do_warn(message, category, stacklevel, source, skip_file_prefixes);
1183
1.02M
}
1184
1185
static PyObject *
1186
get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno)
1187
0
{
1188
0
    PyObject *loader;
1189
0
    PyObject *module_name;
1190
0
    PyObject *get_source;
1191
0
    PyObject *source;
1192
0
    PyObject *source_list;
1193
0
    PyObject *source_line;
1194
1195
    /* stolen from import.c */
1196
0
    loader = _PyImport_BlessMyLoader(interp, module_globals);
1197
0
    if (loader == NULL) {
1198
0
        return NULL;
1199
0
    }
1200
1201
0
    int rc = PyDict_GetItemRef(module_globals, &_Py_ID(__name__),
1202
0
                               &module_name);
1203
0
    if (rc < 0 || rc == 0) {
1204
0
        Py_DECREF(loader);
1205
0
        return NULL;
1206
0
    }
1207
1208
    /* Make sure the loader implements the optional get_source() method. */
1209
0
    (void)PyObject_GetOptionalAttr(loader, &_Py_ID(get_source), &get_source);
1210
0
    Py_DECREF(loader);
1211
0
    if (!get_source) {
1212
0
        Py_DECREF(module_name);
1213
0
        return NULL;
1214
0
    }
1215
    /* Call get_source() to get the source code. */
1216
0
    source = PyObject_CallOneArg(get_source, module_name);
1217
0
    Py_DECREF(get_source);
1218
0
    Py_DECREF(module_name);
1219
0
    if (!source) {
1220
0
        return NULL;
1221
0
    }
1222
0
    if (source == Py_None) {
1223
0
        Py_DECREF(source);
1224
0
        return NULL;
1225
0
    }
1226
1227
    /* Split the source into lines. */
1228
0
    source_list = PyUnicode_Splitlines(source, 0);
1229
0
    Py_DECREF(source);
1230
0
    if (!source_list) {
1231
0
        return NULL;
1232
0
    }
1233
1234
    /* Get the source line. */
1235
0
    source_line = PyList_GetItem(source_list, lineno-1);
1236
0
    Py_XINCREF(source_line);
1237
0
    Py_DECREF(source_list);
1238
0
    return source_line;
1239
0
}
1240
1241
/*[clinic input]
1242
warn_explicit as warnings_warn_explicit
1243
1244
    message: object
1245
    category: object
1246
    filename: unicode
1247
    lineno: int
1248
    module as mod: object = NULL
1249
    registry: object = None
1250
    module_globals: object = None
1251
    source as sourceobj: object = None
1252
1253
Issue a warning, or maybe ignore it or raise an exception.
1254
[clinic start generated code]*/
1255
1256
static PyObject *
1257
warnings_warn_explicit_impl(PyObject *module, PyObject *message,
1258
                            PyObject *category, PyObject *filename,
1259
                            int lineno, PyObject *mod, PyObject *registry,
1260
                            PyObject *module_globals, PyObject *sourceobj)
1261
/*[clinic end generated code: output=c49c62b15a49a186 input=df6eeb8b45e712f1]*/
1262
0
{
1263
0
    PyObject *source_line = NULL;
1264
0
    PyObject *returned;
1265
1266
0
    PyThreadState *tstate = get_current_tstate();
1267
0
    if (tstate == NULL) {
1268
0
        return NULL;
1269
0
    }
1270
1271
0
    if (module_globals && module_globals != Py_None) {
1272
0
        if (!PyAnyDict_Check(module_globals)) {
1273
0
            PyErr_Format(PyExc_TypeError,
1274
0
                         "module_globals must be a dict or a frozendict, "
1275
0
                         "not %T",
1276
0
                         module_globals);
1277
0
            return NULL;
1278
0
        }
1279
1280
0
        source_line = get_source_line(tstate->interp, module_globals, lineno);
1281
0
        if (source_line == NULL && PyErr_Occurred()) {
1282
0
            return NULL;
1283
0
        }
1284
0
    }
1285
1286
0
    warnings_lock(tstate->interp);
1287
0
    returned = warn_explicit(tstate, category, message, filename, lineno,
1288
0
                             mod, registry, source_line, sourceobj);
1289
0
    warnings_unlock(tstate->interp);
1290
0
    Py_XDECREF(source_line);
1291
0
    return returned;
1292
0
}
1293
1294
/*[clinic input]
1295
_filters_mutated_lock_held as warnings_filters_mutated_lock_held
1296
1297
[clinic start generated code]*/
1298
1299
static PyObject *
1300
warnings_filters_mutated_lock_held_impl(PyObject *module)
1301
/*[clinic end generated code: output=df5c84f044e856ec input=34208bf03d70e432]*/
1302
42.4k
{
1303
42.4k
    PyInterpreterState *interp = get_current_interp();
1304
42.4k
    if (interp == NULL) {
1305
0
        return NULL;
1306
0
    }
1307
1308
42.4k
    WarningsState *st = warnings_get_state(interp);
1309
42.4k
    assert(st != NULL);
1310
1311
    // Note that the lock must be held by the caller.
1312
42.4k
    if (!warnings_lock_held(st)) {
1313
0
        PyErr_SetString(PyExc_RuntimeError, "warnings lock is not held");
1314
0
        return NULL;
1315
0
    }
1316
1317
42.4k
    st->filters_version++;
1318
1319
42.4k
    Py_RETURN_NONE;
1320
42.4k
}
1321
1322
/* Function to issue a warning message; may raise an exception. */
1323
1324
static int
1325
warn_unicode(PyObject *category, PyObject *message,
1326
             Py_ssize_t stack_level, PyObject *source)
1327
0
{
1328
0
    PyObject *res;
1329
1330
0
    if (category == NULL)
1331
0
        category = PyExc_RuntimeWarning;
1332
1333
0
    res = do_warn(message, category, stack_level, source, NULL);
1334
0
    if (res == NULL)
1335
0
        return -1;
1336
0
    Py_DECREF(res);
1337
1338
0
    return 0;
1339
0
}
1340
1341
static int
1342
_PyErr_WarnFormatV(PyObject *source,
1343
                   PyObject *category, Py_ssize_t stack_level,
1344
                   const char *format, va_list vargs)
1345
0
{
1346
0
    PyObject *message;
1347
0
    int res;
1348
1349
0
    message = PyUnicode_FromFormatV(format, vargs);
1350
0
    if (message == NULL)
1351
0
        return -1;
1352
1353
0
    res = warn_unicode(category, message, stack_level, source);
1354
0
    Py_DECREF(message);
1355
0
    return res;
1356
0
}
1357
1358
int
1359
PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
1360
                 const char *format, ...)
1361
0
{
1362
0
    int res;
1363
0
    va_list vargs;
1364
1365
0
    va_start(vargs, format);
1366
0
    res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
1367
0
    va_end(vargs);
1368
0
    return res;
1369
0
}
1370
1371
static int
1372
_PyErr_WarnFormat(PyObject *source, PyObject *category, Py_ssize_t stack_level,
1373
                  const char *format, ...)
1374
0
{
1375
0
    int res;
1376
0
    va_list vargs;
1377
1378
0
    va_start(vargs, format);
1379
0
    res = _PyErr_WarnFormatV(source, category, stack_level, format, vargs);
1380
0
    va_end(vargs);
1381
0
    return res;
1382
0
}
1383
1384
int
1385
PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
1386
                      const char *format, ...)
1387
0
{
1388
0
    int res;
1389
0
    va_list vargs;
1390
1391
0
    va_start(vargs, format);
1392
0
    res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
1393
0
                             stack_level, format, vargs);
1394
0
    va_end(vargs);
1395
0
    return res;
1396
0
}
1397
1398
1399
int
1400
PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
1401
0
{
1402
0
    int ret;
1403
0
    PyObject *message = PyUnicode_FromString(text);
1404
0
    if (message == NULL)
1405
0
        return -1;
1406
0
    ret = warn_unicode(category, message, stack_level, NULL);
1407
0
    Py_DECREF(message);
1408
0
    return ret;
1409
0
}
1410
1411
/* PyErr_Warn is only for backwards compatibility and will be removed.
1412
   Use PyErr_WarnEx instead. */
1413
1414
#undef PyErr_Warn
1415
1416
int
1417
PyErr_Warn(PyObject *category, const char *text)
1418
0
{
1419
0
    return PyErr_WarnEx(category, text, 1);
1420
0
}
1421
1422
/* Warning with explicit origin */
1423
int
1424
PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
1425
                         PyObject *filename, int lineno,
1426
                         PyObject *module, PyObject *registry)
1427
11.1k
{
1428
11.1k
    PyObject *res;
1429
11.1k
    if (category == NULL)
1430
0
        category = PyExc_RuntimeWarning;
1431
11.1k
    PyThreadState *tstate = get_current_tstate();
1432
11.1k
    if (tstate == NULL) {
1433
0
        return -1;
1434
0
    }
1435
1436
11.1k
    warnings_lock(tstate->interp);
1437
11.1k
    res = warn_explicit(tstate, category, message, filename, lineno,
1438
11.1k
                        module, registry, NULL, NULL);
1439
11.1k
    warnings_unlock(tstate->interp);
1440
11.1k
    if (res == NULL)
1441
0
        return -1;
1442
11.1k
    Py_DECREF(res);
1443
11.1k
    return 0;
1444
11.1k
}
1445
1446
int
1447
PyErr_WarnExplicit(PyObject *category, const char *text,
1448
                   const char *filename_str, int lineno,
1449
                   const char *module_str, PyObject *registry)
1450
0
{
1451
0
    PyObject *message = PyUnicode_FromString(text);
1452
0
    if (message == NULL) {
1453
0
        return -1;
1454
0
    }
1455
0
    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1456
0
    if (filename == NULL) {
1457
0
        Py_DECREF(message);
1458
0
        return -1;
1459
0
    }
1460
0
    PyObject *module = NULL;
1461
0
    if (module_str != NULL) {
1462
0
        module = PyUnicode_FromString(module_str);
1463
0
        if (module == NULL) {
1464
0
            Py_DECREF(filename);
1465
0
            Py_DECREF(message);
1466
0
            return -1;
1467
0
        }
1468
0
    }
1469
1470
0
    int ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
1471
0
                                       module, registry);
1472
0
    Py_XDECREF(module);
1473
0
    Py_DECREF(filename);
1474
0
    Py_DECREF(message);
1475
0
    return ret;
1476
0
}
1477
1478
int
1479
PyErr_WarnExplicitFormat(PyObject *category,
1480
                         const char *filename_str, int lineno,
1481
                         const char *module_str, PyObject *registry,
1482
                         const char *format, ...)
1483
0
{
1484
0
    PyObject *message;
1485
0
    PyObject *module = NULL;
1486
0
    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1487
0
    int ret = -1;
1488
0
    va_list vargs;
1489
1490
0
    if (filename == NULL)
1491
0
        goto exit;
1492
0
    if (module_str != NULL) {
1493
0
        module = PyUnicode_FromString(module_str);
1494
0
        if (module == NULL)
1495
0
            goto exit;
1496
0
    }
1497
1498
0
    va_start(vargs, format);
1499
0
    message = PyUnicode_FromFormatV(format, vargs);
1500
0
    if (message != NULL) {
1501
0
        PyObject *res;
1502
0
        PyThreadState *tstate = get_current_tstate();
1503
0
        if (tstate != NULL) {
1504
0
            warnings_lock(tstate->interp);
1505
0
            res = warn_explicit(tstate, category, message, filename, lineno,
1506
0
                                module, registry, NULL, NULL);
1507
0
            warnings_unlock(tstate->interp);
1508
0
            Py_DECREF(message);
1509
0
            if (res != NULL) {
1510
0
                Py_DECREF(res);
1511
0
                ret = 0;
1512
0
            }
1513
0
        }
1514
0
    }
1515
0
    va_end(vargs);
1516
0
exit:
1517
0
    Py_XDECREF(module);
1518
0
    Py_XDECREF(filename);
1519
0
    return ret;
1520
0
}
1521
1522
void
1523
_PyErr_WarnUnawaitedAgenMethod(PyAsyncGenObject *agen, PyObject *method)
1524
0
{
1525
0
    PyObject *exc = PyErr_GetRaisedException();
1526
0
    if (_PyErr_WarnFormat((PyObject *)agen, PyExc_RuntimeWarning, 1,
1527
0
                          "coroutine method %R of %R was never awaited",
1528
0
                          method, agen->ag_qualname) < 0)
1529
0
    {
1530
0
        PyErr_FormatUnraisable("Exception ignored while "
1531
0
                               "finalizing async generator %R", agen);
1532
0
    }
1533
0
    PyErr_SetRaisedException(exc);
1534
0
}
1535
1536
1537
void
1538
_PyErr_WarnUnawaitedCoroutine(PyObject *coro)
1539
0
{
1540
    /* First, we attempt to funnel the warning through
1541
       warnings._warn_unawaited_coroutine.
1542
1543
       This could raise an exception, due to:
1544
       - a bug
1545
       - some kind of shutdown-related brokenness
1546
       - succeeding, but with an "error" warning filter installed, so the
1547
         warning is converted into a RuntimeWarning exception
1548
1549
       In the first two cases, we want to print the error (so we know what it
1550
       is!), and then print a warning directly as a fallback. In the last
1551
       case, we want to print the error (since it's the warning!), but *not*
1552
       do a fallback. And after we print the error we can't check for what
1553
       type of error it was (because PyErr_WriteUnraisable clears it), so we
1554
       need a flag to keep track.
1555
1556
       Since this is called from __del__ context, it's careful to never raise
1557
       an exception.
1558
    */
1559
0
    int warned = 0;
1560
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
1561
0
    assert(interp != NULL);
1562
0
    PyObject *fn = GET_WARNINGS_ATTR(interp, _warn_unawaited_coroutine, 1);
1563
0
    if (fn) {
1564
0
        PyObject *res = PyObject_CallOneArg(fn, coro);
1565
0
        Py_DECREF(fn);
1566
0
        if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
1567
0
            warned = 1;
1568
0
        }
1569
0
        Py_XDECREF(res);
1570
0
    }
1571
1572
0
    if (PyErr_Occurred()) {
1573
0
        PyErr_FormatUnraisable("Exception ignored while "
1574
0
                               "finalizing coroutine %R", coro);
1575
0
    }
1576
1577
0
    if (!warned) {
1578
0
        if (_PyErr_WarnFormat(coro, PyExc_RuntimeWarning, 1,
1579
0
                              "coroutine '%S' was never awaited",
1580
0
                              ((PyCoroObject *)coro)->cr_qualname) < 0)
1581
0
        {
1582
0
            PyErr_FormatUnraisable("Exception ignored while "
1583
0
                                   "finalizing coroutine %R", coro);
1584
0
        }
1585
0
    }
1586
0
}
1587
1588
static PyMethodDef warnings_functions[] = {
1589
    WARNINGS_WARN_METHODDEF
1590
    WARNINGS_WARN_EXPLICIT_METHODDEF
1591
    WARNINGS_FILTERS_MUTATED_LOCK_HELD_METHODDEF
1592
    WARNINGS_ACQUIRE_LOCK_METHODDEF
1593
    WARNINGS_RELEASE_LOCK_METHODDEF
1594
    /* XXX(brett.cannon): add showwarning? */
1595
    /* XXX(brett.cannon): Reasonable to add formatwarning? */
1596
    {NULL, NULL}                /* sentinel */
1597
};
1598
1599
1600
static int
1601
warnings_module_exec(PyObject *module)
1602
34
{
1603
34
    PyInterpreterState *interp = get_current_interp();
1604
34
    if (interp == NULL) {
1605
0
        return -1;
1606
0
    }
1607
34
    WarningsState *st = warnings_get_state(interp);
1608
34
    if (st == NULL) {
1609
0
        return -1;
1610
0
    }
1611
34
    if (PyModule_AddObjectRef(module, "filters", st->filters) < 0) {
1612
0
        return -1;
1613
0
    }
1614
34
    if (PyModule_AddObjectRef(module, "_onceregistry", st->once_registry) < 0) {
1615
0
        return -1;
1616
0
    }
1617
34
    if (PyModule_AddObjectRef(module, "_defaultaction", st->default_action) < 0) {
1618
0
        return -1;
1619
0
    }
1620
34
    if (PyModule_AddObjectRef(module, "_warnings_context", st->context) < 0) {
1621
0
        return -1;
1622
0
    }
1623
34
    return 0;
1624
34
}
1625
1626
1627
static PyModuleDef_Slot warnings_slots[] = {
1628
    {Py_mod_exec, warnings_module_exec},
1629
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
1630
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
1631
    {0, NULL}
1632
};
1633
1634
static struct PyModuleDef warnings_module = {
1635
    PyModuleDef_HEAD_INIT,
1636
    .m_name = MODULE_NAME,
1637
    .m_doc = warnings__doc__,
1638
    .m_size = 0,
1639
    .m_methods = warnings_functions,
1640
    .m_slots = warnings_slots,
1641
};
1642
1643
1644
PyMODINIT_FUNC
1645
_PyWarnings_Init(void)
1646
34
{
1647
34
    return PyModuleDef_Init(&warnings_module);
1648
34
}
1649
1650
// We need this to ensure that warnings still work until late in finalization.
1651
void
1652
_PyWarnings_Fini(PyInterpreterState *interp)
1653
0
{
1654
0
    warnings_clear_state(&interp->warnings);
1655
0
}