Coverage Report

Created: 2025-07-18 06:09

/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
17.7k
{
30
17.7k
    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
17.7k
    return 1;
37
17.7k
}
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
17.7k
{
49
17.7k
    PyThreadState *tstate = _PyThreadState_GET();
50
17.7k
    if (tstate == NULL) {
51
0
        (void)check_interp(NULL);
52
0
        return NULL;
53
0
    }
54
17.7k
    return check_interp(tstate->interp) ? tstate : NULL;
55
17.7k
}
56
57
/* Given a module object, get its per-module state. */
58
static WarningsState *
59
warnings_get_state(PyInterpreterState *interp)
60
64.1k
{
61
64.1k
    return &interp->warnings;
62
64.1k
}
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
30.9k
{
176
30.9k
    PyObject *result;
177
30.9k
    int rc;
178
179
    /* A 'None' filter always matches */
180
30.9k
    if (obj == Py_None)
181
30.9k
        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
15.4k
    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
15.4k
{
212
15.4k
    PyObject *warnings_module, *obj;
213
214
    /* don't try to import after the start of the Python finallization */
215
15.4k
    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
15.4k
    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
15.4k
        if (!_PyImport_GetModules(interp)) {
232
0
            return NULL;
233
0
        }
234
15.4k
        warnings_module = PyImport_GetModule(&_Py_ID(warnings));
235
15.4k
        if (warnings_module == NULL)
236
0
            return NULL;
237
15.4k
    }
238
239
15.4k
    (void)PyObject_GetOptionalAttr(warnings_module, attr, &obj);
240
15.4k
    Py_DECREF(warnings_module);
241
15.4k
    return obj;
242
15.4k
}
243
244
static inline void
245
warnings_lock(PyInterpreterState *interp)
246
15.4k
{
247
15.4k
    WarningsState *st = warnings_get_state(interp);
248
15.4k
    assert(st != NULL);
249
15.4k
    _PyRecursiveMutex_Lock(&st->lock);
250
15.4k
}
251
252
static inline int
253
warnings_unlock(PyInterpreterState *interp)
254
15.4k
{
255
15.4k
    WarningsState *st = warnings_get_state(interp);
256
15.4k
    assert(st != NULL);
257
15.4k
    return _PyRecursiveMutex_TryUnlock(&st->lock);
258
15.4k
}
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
15.4k
{
269
15.4k
    WarningsState *st = warnings_get_state(interp);
270
15.4k
    assert(PyContextVar_CheckExact(st->context));
271
15.4k
    PyObject *ctx;
272
15.4k
    if (PyContextVar_Get(st->context, NULL, &ctx) < 0) {
273
0
        return NULL;
274
0
    }
275
15.4k
    if (ctx == NULL) {
276
15.4k
        Py_RETURN_NONE;
277
15.4k
    }
278
0
    return ctx;
279
15.4k
}
280
281
static PyObject *
282
get_warnings_context_filters(PyInterpreterState *interp)
283
15.4k
{
284
15.4k
    PyObject *ctx = get_warnings_context(interp);
285
15.4k
    if (ctx == NULL) {
286
0
        return NULL;
287
0
    }
288
15.4k
    if (ctx == Py_None) {
289
15.4k
        Py_RETURN_NONE;
290
15.4k
    }
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
15.4k
{
309
15.4k
    WarningsState *st = warnings_get_state(interp);
310
15.4k
    PyObject *warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
311
15.4k
    if (warnings_filters == NULL) {
312
0
        if (PyErr_Occurred())
313
0
            return NULL;
314
0
    }
315
15.4k
    else {
316
15.4k
        Py_SETREF(st->filters, warnings_filters);
317
15.4k
    }
318
319
15.4k
    PyObject *filters = st->filters;
320
15.4k
    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
15.4k
    return filters;
326
15.4k
}
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
15.4k
              PyObject **item, PyObject **matched_action) {
428
15.4k
    bool result = true;
429
15.4k
    *matched_action = NULL;
430
    /* Avoid the filters list changing while we iterate over it. */
431
15.4k
    Py_BEGIN_CRITICAL_SECTION(filters);
432
15.4k
    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(filters); i++) {
433
15.4k
        PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
434
15.4k
        Py_ssize_t ln;
435
15.4k
        int is_subclass, good_msg, good_mod;
436
437
15.4k
        tmp_item = PyList_GET_ITEM(filters, i);
438
15.4k
        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
15.4k
        Py_INCREF(tmp_item);
447
15.4k
        action = PyTuple_GET_ITEM(tmp_item, 0);
448
15.4k
        msg = PyTuple_GET_ITEM(tmp_item, 1);
449
15.4k
        cat = PyTuple_GET_ITEM(tmp_item, 2);
450
15.4k
        mod = PyTuple_GET_ITEM(tmp_item, 3);
451
15.4k
        ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
452
453
15.4k
        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
15.4k
        good_msg = check_matched(interp, msg, text);
463
15.4k
        if (good_msg == -1) {
464
0
            Py_DECREF(tmp_item);
465
0
            result = false;
466
0
            break;
467
0
        }
468
469
15.4k
        good_mod = check_matched(interp, mod, module);
470
15.4k
        if (good_mod == -1) {
471
0
            Py_DECREF(tmp_item);
472
0
            result = false;
473
0
            break;
474
0
        }
475
476
15.4k
        is_subclass = PyObject_IsSubclass(category, cat);
477
15.4k
        if (is_subclass == -1) {
478
0
            Py_DECREF(tmp_item);
479
0
            result = false;
480
0
            break;
481
0
        }
482
483
15.4k
        ln = PyLong_AsSsize_t(ln_obj);
484
15.4k
        if (ln == -1 && PyErr_Occurred()) {
485
0
            Py_DECREF(tmp_item);
486
0
            result = false;
487
0
            break;
488
0
        }
489
490
15.4k
        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
491
15.4k
            *item = tmp_item;
492
15.4k
            *matched_action = action;
493
15.4k
            result = true;
494
15.4k
            break;
495
15.4k
        }
496
497
0
        Py_DECREF(tmp_item);
498
0
    }
499
15.4k
    Py_END_CRITICAL_SECTION();
500
15.4k
    return result;
501
15.4k
}
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
15.4k
{
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
15.4k
    PyObject *context_filters = get_warnings_context_filters(interp);
517
15.4k
    if (context_filters == NULL) {
518
0
        return NULL;
519
0
    }
520
15.4k
    bool use_global_filters = false;
521
15.4k
    if (context_filters == Py_None) {
522
15.4k
        use_global_filters = true;
523
15.4k
    } 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
15.4k
    PyObject *action;
537
538
15.4k
    if (use_global_filters) {
539
        /* check warnings.filters list */
540
15.4k
        PyObject *filters = get_warnings_filters(interp);
541
15.4k
        if (filters == NULL) {
542
0
            return NULL;
543
0
        }
544
15.4k
        if (!filter_search(interp, category, text, lineno, module, "filters",
545
15.4k
                           filters, item, &action)) {
546
0
            return NULL;
547
0
        }
548
15.4k
        if (action != NULL) {
549
15.4k
            return action;
550
15.4k
        }
551
15.4k
    }
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.30k
{
567
2.30k
    PyObject *already_warned;
568
569
2.30k
    if (key == NULL)
570
0
        return -1;
571
572
2.30k
    WarningsState *st = warnings_get_state(interp);
573
2.30k
    assert(st != NULL);
574
2.30k
    assert(warnings_lock_held(st));
575
576
2.30k
    PyObject *version_obj;
577
2.30k
    if (PyDict_GetItemRef(registry, &_Py_ID(version), &version_obj) < 0) {
578
0
        return -1;
579
0
    }
580
2.30k
    bool should_update_version = (
581
2.30k
        version_obj == NULL
582
2.30k
        || !PyLong_CheckExact(version_obj)
583
2.30k
        || PyLong_AsLong(version_obj) != st->filters_version
584
2.30k
    );
585
2.30k
    Py_XDECREF(version_obj);
586
2.30k
    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.30k
    else {
598
2.30k
        if (PyDict_GetItemRef(registry, key, &already_warned) < 0) {
599
0
            return -1;
600
0
        }
601
2.30k
        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.30k
    }
608
609
    /* This warning wasn't found in the registry, set it. */
610
2.30k
    if (should_set)
611
0
        return PyDict_SetItem(registry, key, Py_True);
612
2.30k
    return 0;
613
2.30k
}
614
615
/* New reference. */
616
static PyObject *
617
normalize_module(PyObject *filename)
618
13.1k
{
619
13.1k
    PyObject *module;
620
13.1k
    int kind;
621
13.1k
    const void *data;
622
13.1k
    Py_ssize_t len;
623
624
13.1k
    len = PyUnicode_GetLength(filename);
625
13.1k
    if (len < 0)
626
0
        return NULL;
627
628
13.1k
    if (len == 0)
629
0
        return PyUnicode_FromString("<unknown>");
630
631
13.1k
    kind = PyUnicode_KIND(filename);
632
13.1k
    data = PyUnicode_DATA(filename);
633
634
    /* if filename.endswith(".py"): */
635
13.1k
    if (len >= 3 &&
636
13.1k
        PyUnicode_READ(kind, data, len-3) == '.' &&
637
13.1k
        PyUnicode_READ(kind, data, len-2) == 'p' &&
638
13.1k
        PyUnicode_READ(kind, data, len-1) == 'y')
639
0
    {
640
0
        module = PyUnicode_Substring(filename, 0, len-3);
641
0
    }
642
13.1k
    else {
643
13.1k
        module = Py_NewRef(filename);
644
13.1k
    }
645
13.1k
    return module;
646
13.1k
}
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
15.4k
{
797
15.4k
    PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
798
15.4k
    PyObject *item = NULL;
799
15.4k
    PyObject *action;
800
15.4k
    int rc;
801
15.4k
    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
15.4k
    if (module == Py_None)
808
0
        Py_RETURN_NONE;
809
810
15.4k
    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
15.4k
    if (module == NULL) {
817
13.1k
        module = normalize_module(filename);
818
13.1k
        if (module == NULL)
819
0
            return NULL;
820
13.1k
    }
821
2.30k
    else
822
2.30k
        Py_INCREF(module);
823
824
    /* Normalize message. */
825
15.4k
    Py_INCREF(message);  /* DECREF'ed in cleanup. */
826
15.4k
    rc = PyObject_IsInstance(message, PyExc_Warning);
827
15.4k
    if (rc == -1) {
828
0
        goto cleanup;
829
0
    }
830
15.4k
    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
15.4k
    else {
837
15.4k
        text = message;
838
15.4k
        message = PyObject_CallOneArg(category, message);
839
15.4k
        if (message == NULL)
840
0
            goto cleanup;
841
15.4k
    }
842
843
15.4k
    lineno_obj = PyLong_FromLong(lineno);
844
15.4k
    if (lineno_obj == NULL)
845
0
        goto cleanup;
846
847
15.4k
    if (source == Py_None) {
848
0
        source = NULL;
849
0
    }
850
851
    /* Create key. */
852
15.4k
    key = PyTuple_Pack(3, text, category, lineno_obj);
853
15.4k
    if (key == NULL)
854
0
        goto cleanup;
855
856
15.4k
    if ((registry != NULL) && (registry != Py_None)) {
857
2.30k
        rc = already_warned(interp, registry, key, 0);
858
2.30k
        if (rc == -1)
859
0
            goto cleanup;
860
2.30k
        else if (rc == 1)
861
0
            goto return_none;
862
        /* Else this warning hasn't been generated before. */
863
2.30k
    }
864
865
15.4k
    action = get_filter(interp, category, text, lineno, module, &item);
866
15.4k
    if (action == NULL)
867
0
        goto cleanup;
868
869
15.4k
    if (_PyUnicode_EqualToASCIIString(action, "error")) {
870
0
        PyErr_SetObject(category, message);
871
0
        goto cleanup;
872
0
    }
873
874
15.4k
    if (_PyUnicode_EqualToASCIIString(action, "ignore")) {
875
15.4k
        goto return_none;
876
15.4k
    }
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
15.4k
 return_none:
921
15.4k
    result = Py_NewRef(Py_None);
922
923
15.4k
 cleanup:
924
15.4k
    Py_XDECREF(item);
925
15.4k
    Py_XDECREF(key);
926
15.4k
    Py_XDECREF(text);
927
15.4k
    Py_XDECREF(lineno_obj);
928
15.4k
    Py_DECREF(module);
929
15.4k
    Py_XDECREF(message);
930
15.4k
    return result;  /* Py_None or NULL. */
931
15.4k
}
932
933
static PyObject *
934
get_frame_filename(PyFrameObject *frame)
935
2.30k
{
936
2.30k
    PyCodeObject *code = PyFrame_GetCode(frame);
937
2.30k
    PyObject *filename = code->co_filename;
938
2.30k
    Py_DECREF(code);
939
2.30k
    return filename;
940
2.30k
}
941
942
static bool
943
is_internal_filename(PyObject *filename)
944
2.30k
{
945
2.30k
    if (!PyUnicode_Check(filename)) {
946
0
        return false;
947
0
    }
948
949
2.30k
    int contains = PyUnicode_Contains(filename, &_Py_ID(importlib));
950
2.30k
    if (contains < 0) {
951
0
        return false;
952
0
    }
953
2.30k
    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.30k
    return false;
964
2.30k
}
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.30k
{
994
2.30k
    if (frame == NULL) {
995
0
        return false;
996
0
    }
997
998
2.30k
    PyObject *filename = get_frame_filename(frame);
999
2.30k
    if (filename == NULL) {
1000
0
        return false;
1001
0
    }
1002
1003
2.30k
    return is_internal_filename(filename);
1004
2.30k
}
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.30k
{
1029
2.30k
    PyObject *globals;
1030
1031
    /* Setup globals, filename and lineno. */
1032
2.30k
    PyThreadState *tstate = get_current_tstate();
1033
2.30k
    if (tstate == NULL) {
1034
0
        return 0;
1035
0
    }
1036
2.30k
    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.30k
    PyInterpreterState *interp = tstate->interp;
1052
2.30k
    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.30k
    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.30k
    else {
1062
2.30k
        while (--stack_level > 0 && f != NULL) {
1063
0
            f = next_external_frame(f, skip_file_prefixes);
1064
0
        }
1065
2.30k
    }
1066
1067
2.30k
    if (f == NULL) {
1068
0
        globals = interp->sysdict;
1069
0
        *filename = PyUnicode_FromString("<sys>");
1070
0
        *lineno = 0;
1071
0
    }
1072
2.30k
    else {
1073
2.30k
        globals = f->f_frame->f_globals;
1074
2.30k
        *filename = Py_NewRef(_PyFrame_GetCode(f->f_frame)->co_filename);
1075
2.30k
        *lineno = PyFrame_GetLineNumber(f);
1076
2.30k
        Py_DECREF(f);
1077
2.30k
    }
1078
1079
2.30k
    *module = NULL;
1080
1081
    /* Setup registry. */
1082
2.30k
    assert(globals != NULL);
1083
2.30k
    assert(PyDict_Check(globals));
1084
2.30k
    int rc = PyDict_GetItemRef(globals, &_Py_ID(__warningregistry__),
1085
2.30k
                               registry);
1086
2.30k
    if (rc < 0) {
1087
0
        goto handle_error;
1088
0
    }
1089
2.30k
    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.30k
    rc = PyDict_GetItemRef(globals, &_Py_ID(__name__), module);
1101
2.30k
    if (rc < 0) {
1102
0
        goto handle_error;
1103
0
    }
1104
2.30k
    if (rc > 0) {
1105
2.30k
        if (Py_IsNone(*module) || PyUnicode_Check(*module)) {
1106
2.30k
            return 1;
1107
2.30k
        }
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
15.4k
{
1463
15.4k
    PyObject *res;
1464
15.4k
    if (category == NULL)
1465
0
        category = PyExc_RuntimeWarning;
1466
15.4k
    PyThreadState *tstate = get_current_tstate();
1467
15.4k
    if (tstate == NULL) {
1468
0
        return -1;
1469
0
    }
1470
1471
15.4k
    warnings_lock(tstate->interp);
1472
15.4k
    res = warn_explicit(tstate, category, message, filename, lineno,
1473
15.4k
                        module, registry, NULL, NULL);
1474
15.4k
    warnings_unlock(tstate->interp);
1475
15.4k
    if (res == NULL)
1476
0
        return -1;
1477
15.4k
    Py_DECREF(res);
1478
15.4k
    return 0;
1479
15.4k
}
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.30k
{
1486
2.30k
    PyObject *unused_filename, *module, *registry;
1487
2.30k
    int unused_lineno;
1488
2.30k
    int stack_level = 1;
1489
1490
2.30k
    if (!setup_context(stack_level, NULL, &unused_filename, &unused_lineno,
1491
2.30k
                       &module, &registry)) {
1492
0
        return -1;
1493
0
    }
1494
1495
2.30k
    int rc = PyErr_WarnExplicitObject(category, message, filename, lineno,
1496
2.30k
                                      module, registry);
1497
2.30k
    Py_DECREF(unused_filename);
1498
2.30k
    Py_DECREF(registry);
1499
2.30k
    Py_DECREF(module);
1500
2.30k
    return rc;
1501
2.30k
}
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
}