Coverage Report

Created: 2026-10-17 06:15

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