Coverage Report

Created: 2026-07-14 06:16

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