Coverage Report

Created: 2025-07-04 06:49

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