Coverage Report

Created: 2025-08-26 06:26

/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
18.3k
{
30
18.3k
    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
18.3k
    return 1;
37
18.3k
}
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
18.2k
{
49
18.2k
    PyThreadState *tstate = _PyThreadState_GET();
50
18.2k
    if (tstate == NULL) {
51
0
        (void)check_interp(NULL);
52
0
        return NULL;
53
0
    }
54
18.2k
    return check_interp(tstate->interp) ? tstate : NULL;
55
18.2k
}
56
57
/* Given a module object, get its per-module state. */
58
static WarningsState *
59
warnings_get_state(PyInterpreterState *interp)
60
66.3k
{
61
66.3k
    return &interp->warnings;
62
66.3k
}
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
32.0k
{
176
32.0k
    PyObject *result;
177
32.0k
    int rc;
178
179
    /* A 'None' filter always matches */
180
32.0k
    if (obj == Py_None)
181
32.0k
        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
16.0k
    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
16.0k
{
212
16.0k
    PyObject *warnings_module, *obj;
213
214
    /* don't try to import after the start of the Python finallization */
215
16.0k
    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
16.0k
    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
16.0k
        if (!_PyImport_GetModules(interp)) {
232
0
            return NULL;
233
0
        }
234
16.0k
        warnings_module = PyImport_GetModule(&_Py_ID(warnings));
235
16.0k
        if (warnings_module == NULL)
236
0
            return NULL;
237
16.0k
    }
238
239
16.0k
    (void)PyObject_GetOptionalAttr(warnings_module, attr, &obj);
240
16.0k
    Py_DECREF(warnings_module);
241
16.0k
    return obj;
242
16.0k
}
243
244
static inline void
245
warnings_lock(PyInterpreterState *interp)
246
16.0k
{
247
16.0k
    WarningsState *st = warnings_get_state(interp);
248
16.0k
    assert(st != NULL);
249
16.0k
    _PyRecursiveMutex_Lock(&st->lock);
250
16.0k
}
251
252
static inline int
253
warnings_unlock(PyInterpreterState *interp)
254
16.0k
{
255
16.0k
    WarningsState *st = warnings_get_state(interp);
256
16.0k
    assert(st != NULL);
257
16.0k
    return _PyRecursiveMutex_TryUnlock(&st->lock);
258
16.0k
}
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
16.0k
{
269
16.0k
    WarningsState *st = warnings_get_state(interp);
270
16.0k
    assert(PyContextVar_CheckExact(st->context));
271
16.0k
    PyObject *ctx;
272
16.0k
    if (PyContextVar_Get(st->context, NULL, &ctx) < 0) {
273
0
        return NULL;
274
0
    }
275
16.0k
    if (ctx == NULL) {
276
16.0k
        Py_RETURN_NONE;
277
16.0k
    }
278
0
    return ctx;
279
16.0k
}
280
281
static PyObject *
282
get_warnings_context_filters(PyInterpreterState *interp)
283
16.0k
{
284
16.0k
    PyObject *ctx = get_warnings_context(interp);
285
16.0k
    if (ctx == NULL) {
286
0
        return NULL;
287
0
    }
288
16.0k
    if (ctx == Py_None) {
289
16.0k
        Py_RETURN_NONE;
290
16.0k
    }
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
16.0k
{
309
16.0k
    WarningsState *st = warnings_get_state(interp);
310
16.0k
    PyObject *warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
311
16.0k
    if (warnings_filters == NULL) {
312
0
        if (PyErr_Occurred())
313
0
            return NULL;
314
0
    }
315
16.0k
    else {
316
16.0k
        Py_SETREF(st->filters, warnings_filters);
317
16.0k
    }
318
319
16.0k
    PyObject *filters = st->filters;
320
16.0k
    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
16.0k
    return filters;
326
16.0k
}
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
16.0k
              PyObject **item, PyObject **matched_action) {
428
16.0k
    bool result = true;
429
16.0k
    *matched_action = NULL;
430
    /* Avoid the filters list changing while we iterate over it. */
431
16.0k
    Py_BEGIN_CRITICAL_SECTION(filters);
432
16.0k
    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(filters); i++) {
433
16.0k
        PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
434
16.0k
        Py_ssize_t ln;
435
16.0k
        int is_subclass, good_msg, good_mod;
436
437
16.0k
        tmp_item = PyList_GET_ITEM(filters, i);
438
16.0k
        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
16.0k
        Py_INCREF(tmp_item);
447
16.0k
        action = PyTuple_GET_ITEM(tmp_item, 0);
448
16.0k
        msg = PyTuple_GET_ITEM(tmp_item, 1);
449
16.0k
        cat = PyTuple_GET_ITEM(tmp_item, 2);
450
16.0k
        mod = PyTuple_GET_ITEM(tmp_item, 3);
451
16.0k
        ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
452
453
16.0k
        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
16.0k
        good_msg = check_matched(interp, msg, text);
463
16.0k
        if (good_msg == -1) {
464
0
            Py_DECREF(tmp_item);
465
0
            result = false;
466
0
            break;
467
0
        }
468
469
16.0k
        good_mod = check_matched(interp, mod, module);
470
16.0k
        if (good_mod == -1) {
471
0
            Py_DECREF(tmp_item);
472
0
            result = false;
473
0
            break;
474
0
        }
475
476
16.0k
        is_subclass = PyObject_IsSubclass(category, cat);
477
16.0k
        if (is_subclass == -1) {
478
0
            Py_DECREF(tmp_item);
479
0
            result = false;
480
0
            break;
481
0
        }
482
483
16.0k
        ln = PyLong_AsSsize_t(ln_obj);
484
16.0k
        if (ln == -1 && PyErr_Occurred()) {
485
0
            Py_DECREF(tmp_item);
486
0
            result = false;
487
0
            break;
488
0
        }
489
490
16.0k
        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
491
16.0k
            *item = tmp_item;
492
16.0k
            *matched_action = action;
493
16.0k
            result = true;
494
16.0k
            break;
495
16.0k
        }
496
497
0
        Py_DECREF(tmp_item);
498
0
    }
499
16.0k
    Py_END_CRITICAL_SECTION();
500
16.0k
    return result;
501
16.0k
}
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
16.0k
{
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
16.0k
    PyObject *context_filters = get_warnings_context_filters(interp);
517
16.0k
    if (context_filters == NULL) {
518
0
        return NULL;
519
0
    }
520
16.0k
    bool use_global_filters = false;
521
16.0k
    if (context_filters == Py_None) {
522
16.0k
        use_global_filters = true;
523
16.0k
    } 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
16.0k
    PyObject *action;
537
538
16.0k
    if (use_global_filters) {
539
        /* check warnings.filters list */
540
16.0k
        PyObject *filters = get_warnings_filters(interp);
541
16.0k
        if (filters == NULL) {
542
0
            return NULL;
543
0
        }
544
16.0k
        if (!filter_search(interp, category, text, lineno, module, "filters",
545
16.0k
                           filters, item, &action)) {
546
0
            return NULL;
547
0
        }
548
16.0k
        if (action != NULL) {
549
16.0k
            return action;
550
16.0k
        }
551
16.0k
    }
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.27k
{
567
2.27k
    PyObject *already_warned;
568
569
2.27k
    if (key == NULL)
570
0
        return -1;
571
572
2.27k
    WarningsState *st = warnings_get_state(interp);
573
2.27k
    assert(st != NULL);
574
2.27k
    assert(warnings_lock_held(st));
575
576
2.27k
    PyObject *version_obj;
577
2.27k
    if (PyDict_GetItemRef(registry, &_Py_ID(version), &version_obj) < 0) {
578
0
        return -1;
579
0
    }
580
2.27k
    bool should_update_version = (
581
2.27k
        version_obj == NULL
582
2.27k
        || !PyLong_CheckExact(version_obj)
583
2.27k
        || PyLong_AsLong(version_obj) != st->filters_version
584
2.27k
    );
585
2.27k
    Py_XDECREF(version_obj);
586
2.27k
    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.27k
    else {
598
2.27k
        if (PyDict_GetItemRef(registry, key, &already_warned) < 0) {
599
0
            return -1;
600
0
        }
601
2.27k
        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.27k
    }
608
609
    /* This warning wasn't found in the registry, set it. */
610
2.27k
    if (should_set)
611
0
        return PyDict_SetItem(registry, key, Py_True);
612
2.27k
    return 0;
613
2.27k
}
614
615
/* New reference. */
616
static PyObject *
617
normalize_module(PyObject *filename)
618
13.7k
{
619
13.7k
    PyObject *module;
620
13.7k
    int kind;
621
13.7k
    const void *data;
622
13.7k
    Py_ssize_t len;
623
624
13.7k
    len = PyUnicode_GetLength(filename);
625
13.7k
    if (len < 0)
626
0
        return NULL;
627
628
13.7k
    if (len == 0)
629
0
        return PyUnicode_FromString("<unknown>");
630
631
13.7k
    kind = PyUnicode_KIND(filename);
632
13.7k
    data = PyUnicode_DATA(filename);
633
634
    /* if filename.endswith(".py"): */
635
13.7k
    if (len >= 3 &&
636
13.7k
        PyUnicode_READ(kind, data, len-3) == '.' &&
637
13.7k
        PyUnicode_READ(kind, data, len-2) == 'p' &&
638
13.7k
        PyUnicode_READ(kind, data, len-1) == 'y')
639
0
    {
640
0
        module = PyUnicode_Substring(filename, 0, len-3);
641
0
    }
642
13.7k
    else {
643
13.7k
        module = Py_NewRef(filename);
644
13.7k
    }
645
13.7k
    return module;
646
13.7k
}
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
16.0k
{
797
16.0k
    PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
798
16.0k
    PyObject *item = NULL;
799
16.0k
    PyObject *action;
800
16.0k
    int rc;
801
16.0k
    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
16.0k
    if (module == Py_None)
808
0
        Py_RETURN_NONE;
809
810
16.0k
    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
16.0k
    if (module == NULL) {
817
13.7k
        module = normalize_module(filename);
818
13.7k
        if (module == NULL)
819
0
            return NULL;
820
13.7k
    }
821
2.27k
    else
822
2.27k
        Py_INCREF(module);
823
824
    /* Normalize message. */
825
16.0k
    Py_INCREF(message);  /* DECREF'ed in cleanup. */
826
16.0k
    if (PyObject_TypeCheck(message, (PyTypeObject *)PyExc_Warning)) {
827
0
        text = PyObject_Str(message);
828
0
        if (text == NULL)
829
0
            goto cleanup;
830
0
        category = (PyObject*)Py_TYPE(message);
831
0
    }
832
16.0k
    else {
833
16.0k
        text = message;
834
16.0k
        message = PyObject_CallOneArg(category, message);
835
16.0k
        if (message == NULL)
836
0
            goto cleanup;
837
16.0k
    }
838
839
16.0k
    lineno_obj = PyLong_FromLong(lineno);
840
16.0k
    if (lineno_obj == NULL)
841
0
        goto cleanup;
842
843
16.0k
    if (source == Py_None) {
844
0
        source = NULL;
845
0
    }
846
847
    /* Create key. */
848
16.0k
    key = PyTuple_Pack(3, text, category, lineno_obj);
849
16.0k
    if (key == NULL)
850
0
        goto cleanup;
851
852
16.0k
    if ((registry != NULL) && (registry != Py_None)) {
853
2.27k
        rc = already_warned(interp, registry, key, 0);
854
2.27k
        if (rc == -1)
855
0
            goto cleanup;
856
2.27k
        else if (rc == 1)
857
0
            goto return_none;
858
        /* Else this warning hasn't been generated before. */
859
2.27k
    }
860
861
16.0k
    action = get_filter(interp, category, text, lineno, module, &item);
862
16.0k
    if (action == NULL)
863
0
        goto cleanup;
864
865
16.0k
    if (_PyUnicode_EqualToASCIIString(action, "error")) {
866
0
        PyErr_SetObject(category, message);
867
0
        goto cleanup;
868
0
    }
869
870
16.0k
    if (_PyUnicode_EqualToASCIIString(action, "ignore")) {
871
16.0k
        goto return_none;
872
16.0k
    }
873
874
    /* Store in the registry that we've been here, *except* when the action
875
       is "always" or "all". */
876
0
    rc = 0;
877
0
    if (!_PyUnicode_EqualToASCIIString(action, "always") && !_PyUnicode_EqualToASCIIString(action, "all")) {
878
0
        if (registry != NULL && registry != Py_None &&
879
0
            PyDict_SetItem(registry, key, Py_True) < 0)
880
0
        {
881
0
            goto cleanup;
882
0
        }
883
884
0
        if (_PyUnicode_EqualToASCIIString(action, "once")) {
885
0
            if (registry == NULL || registry == Py_None) {
886
0
                registry = get_once_registry(interp);
887
0
                if (registry == NULL)
888
0
                    goto cleanup;
889
0
            }
890
            /* WarningsState.once_registry[(text, category)] = 1 */
891
0
            rc = update_registry(interp, registry, text, category, 0);
892
0
        }
893
0
        else if (_PyUnicode_EqualToASCIIString(action, "module")) {
894
            /* registry[(text, category, 0)] = 1 */
895
0
            if (registry != NULL && registry != Py_None)
896
0
                rc = update_registry(interp, registry, text, category, 0);
897
0
        }
898
0
        else if (!_PyUnicode_EqualToASCIIString(action, "default")) {
899
0
            PyErr_Format(PyExc_RuntimeError,
900
0
                        "Unrecognized action (%R) in warnings.filters:\n %R",
901
0
                        action, item);
902
0
            goto cleanup;
903
0
        }
904
0
    }
905
906
0
    if (rc == 1)  /* Already warned for this module. */
907
0
        goto return_none;
908
0
    if (rc == 0) {
909
0
        if (call_show_warning(tstate, category, text, message, filename,
910
0
                              lineno, lineno_obj, sourceline, source) < 0)
911
0
            goto cleanup;
912
0
    }
913
0
    else /* if (rc == -1) */
914
0
        goto cleanup;
915
916
16.0k
 return_none:
917
16.0k
    result = Py_NewRef(Py_None);
918
919
16.0k
 cleanup:
920
16.0k
    Py_XDECREF(item);
921
16.0k
    Py_XDECREF(key);
922
16.0k
    Py_XDECREF(text);
923
16.0k
    Py_XDECREF(lineno_obj);
924
16.0k
    Py_DECREF(module);
925
16.0k
    Py_XDECREF(message);
926
16.0k
    return result;  /* Py_None or NULL. */
927
16.0k
}
928
929
static PyObject *
930
get_frame_filename(PyFrameObject *frame)
931
2.27k
{
932
2.27k
    PyCodeObject *code = PyFrame_GetCode(frame);
933
2.27k
    PyObject *filename = code->co_filename;
934
2.27k
    Py_DECREF(code);
935
2.27k
    return filename;
936
2.27k
}
937
938
static bool
939
is_internal_filename(PyObject *filename)
940
2.27k
{
941
2.27k
    if (!PyUnicode_Check(filename)) {
942
0
        return false;
943
0
    }
944
945
2.27k
    int contains = PyUnicode_Contains(filename, &_Py_ID(importlib));
946
2.27k
    if (contains < 0) {
947
0
        return false;
948
0
    }
949
2.27k
    else if (contains > 0) {
950
0
        contains = PyUnicode_Contains(filename, &_Py_ID(_bootstrap));
951
0
        if (contains < 0) {
952
0
            return false;
953
0
        }
954
0
        else if (contains > 0) {
955
0
            return true;
956
0
        }
957
0
    }
958
959
2.27k
    return false;
960
2.27k
}
961
962
static bool
963
is_filename_to_skip(PyObject *filename, PyTupleObject *skip_file_prefixes)
964
0
{
965
0
    if (skip_file_prefixes) {
966
0
        if (!PyUnicode_Check(filename)) {
967
0
            return false;
968
0
        }
969
970
0
        Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
971
0
        for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
972
0
        {
973
0
            PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
974
0
            Py_ssize_t found = PyUnicode_Tailmatch(filename, prefix,
975
0
                                                   0, PY_SSIZE_T_MAX, -1);
976
0
            if (found == 1) {
977
0
                return true;
978
0
            }
979
0
            if (found < 0) {
980
0
                return false;
981
0
            }
982
0
        }
983
0
    }
984
0
    return false;
985
0
}
986
987
static bool
988
is_internal_frame(PyFrameObject *frame)
989
2.27k
{
990
2.27k
    if (frame == NULL) {
991
0
        return false;
992
0
    }
993
994
2.27k
    PyObject *filename = get_frame_filename(frame);
995
2.27k
    if (filename == NULL) {
996
0
        return false;
997
0
    }
998
999
2.27k
    return is_internal_filename(filename);
1000
2.27k
}
1001
1002
static PyFrameObject *
1003
next_external_frame(PyFrameObject *frame, PyTupleObject *skip_file_prefixes)
1004
0
{
1005
0
    PyObject *frame_filename;
1006
0
    do {
1007
0
        PyFrameObject *back = PyFrame_GetBack(frame);
1008
0
        Py_SETREF(frame, back);
1009
0
    } while (frame != NULL && (frame_filename = get_frame_filename(frame)) &&
1010
0
             (is_internal_filename(frame_filename) ||
1011
0
              is_filename_to_skip(frame_filename, skip_file_prefixes)));
1012
1013
0
    return frame;
1014
0
}
1015
1016
/* filename, module, and registry are new refs, globals is borrowed */
1017
/* skip_file_prefixes is either NULL or a tuple of strs. */
1018
/* Returns 0 on error (no new refs), 1 on success */
1019
static int
1020
setup_context(Py_ssize_t stack_level,
1021
              PyTupleObject *skip_file_prefixes,
1022
              PyObject **filename, int *lineno,
1023
              PyObject **module, PyObject **registry)
1024
2.27k
{
1025
2.27k
    PyObject *globals;
1026
1027
    /* Setup globals, filename and lineno. */
1028
2.27k
    PyThreadState *tstate = get_current_tstate();
1029
2.27k
    if (tstate == NULL) {
1030
0
        return 0;
1031
0
    }
1032
2.27k
    if (skip_file_prefixes) {
1033
        /* Type check our data structure up front. Later code that uses it
1034
         * isn't structured to report errors. */
1035
0
        Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
1036
0
        for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
1037
0
        {
1038
0
            PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
1039
0
            if (!PyUnicode_Check(prefix)) {
1040
0
                PyErr_Format(PyExc_TypeError,
1041
0
                             "Found non-str '%s' in skip_file_prefixes.",
1042
0
                             Py_TYPE(prefix)->tp_name);
1043
0
                return 0;
1044
0
            }
1045
0
        }
1046
0
    }
1047
2.27k
    PyInterpreterState *interp = tstate->interp;
1048
2.27k
    PyFrameObject *f = PyThreadState_GetFrame(tstate);
1049
    // Stack level comparisons to Python code is off by one as there is no
1050
    // warnings-related stack level to avoid.
1051
2.27k
    if (stack_level <= 0 || is_internal_frame(f)) {
1052
0
        while (--stack_level > 0 && f != NULL) {
1053
0
            PyFrameObject *back = PyFrame_GetBack(f);
1054
0
            Py_SETREF(f, back);
1055
0
        }
1056
0
    }
1057
2.27k
    else {
1058
2.27k
        while (--stack_level > 0 && f != NULL) {
1059
0
            f = next_external_frame(f, skip_file_prefixes);
1060
0
        }
1061
2.27k
    }
1062
1063
2.27k
    if (f == NULL) {
1064
0
        globals = interp->sysdict;
1065
0
        *filename = PyUnicode_FromString("<sys>");
1066
0
        *lineno = 0;
1067
0
    }
1068
2.27k
    else {
1069
2.27k
        globals = f->f_frame->f_globals;
1070
2.27k
        *filename = Py_NewRef(_PyFrame_GetCode(f->f_frame)->co_filename);
1071
2.27k
        *lineno = PyFrame_GetLineNumber(f);
1072
2.27k
        Py_DECREF(f);
1073
2.27k
    }
1074
1075
2.27k
    *module = NULL;
1076
1077
    /* Setup registry. */
1078
2.27k
    assert(globals != NULL);
1079
2.27k
    assert(PyDict_Check(globals));
1080
2.27k
    int rc = PyDict_GetItemRef(globals, &_Py_ID(__warningregistry__),
1081
2.27k
                               registry);
1082
2.27k
    if (rc < 0) {
1083
0
        goto handle_error;
1084
0
    }
1085
2.27k
    if (*registry == NULL) {
1086
1
        *registry = PyDict_New();
1087
1
        if (*registry == NULL)
1088
0
            goto handle_error;
1089
1090
1
         rc = PyDict_SetItem(globals, &_Py_ID(__warningregistry__), *registry);
1091
1
         if (rc < 0)
1092
0
            goto handle_error;
1093
1
    }
1094
1095
    /* Setup module. */
1096
2.27k
    rc = PyDict_GetItemRef(globals, &_Py_ID(__name__), module);
1097
2.27k
    if (rc < 0) {
1098
0
        goto handle_error;
1099
0
    }
1100
2.27k
    if (rc > 0) {
1101
2.27k
        if (Py_IsNone(*module) || PyUnicode_Check(*module)) {
1102
2.27k
            return 1;
1103
2.27k
        }
1104
0
        Py_DECREF(*module);
1105
0
    }
1106
0
    *module = PyUnicode_FromString("<string>");
1107
0
    if (*module == NULL) {
1108
0
        goto handle_error;
1109
0
    }
1110
1111
0
    return 1;
1112
1113
0
 handle_error:
1114
0
    Py_XDECREF(*registry);
1115
0
    Py_XDECREF(*module);
1116
0
    Py_DECREF(*filename);
1117
0
    return 0;
1118
0
}
1119
1120
static PyObject *
1121
get_category(PyObject *message, PyObject *category)
1122
0
{
1123
0
    if (PyObject_TypeCheck(message, (PyTypeObject *)PyExc_Warning)) {
1124
        /* Ignore the category argument. */
1125
0
        return (PyObject*)Py_TYPE(message);
1126
0
    }
1127
0
    if (category == NULL || category == Py_None) {
1128
0
        return PyExc_UserWarning;
1129
0
    }
1130
1131
    /* Validate category. */
1132
0
    if (!PyType_Check(category)) {
1133
0
        PyErr_Format(PyExc_TypeError,
1134
0
                     "category must be a Warning subclass, not '%T'",
1135
0
                     category);
1136
0
        return NULL;
1137
0
    }
1138
0
    if (!PyType_IsSubtype((PyTypeObject *)category, (PyTypeObject *)PyExc_Warning)) {
1139
0
        PyErr_Format(PyExc_TypeError,
1140
0
                     "category must be a Warning subclass, not class '%N'",
1141
0
                     (PyTypeObject *)category);
1142
0
        return NULL;
1143
0
    }
1144
1145
0
    return category;
1146
0
}
1147
1148
static PyObject *
1149
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
1150
        PyObject *source, PyTupleObject *skip_file_prefixes)
1151
0
{
1152
0
    PyObject *filename, *module, *registry, *res;
1153
0
    int lineno;
1154
1155
0
    PyThreadState *tstate = get_current_tstate();
1156
0
    if (tstate == NULL) {
1157
0
        return NULL;
1158
0
    }
1159
1160
0
    if (!setup_context(stack_level, skip_file_prefixes,
1161
0
                       &filename, &lineno, &module, &registry))
1162
0
        return NULL;
1163
1164
0
    warnings_lock(tstate->interp);
1165
0
    res = warn_explicit(tstate, category, message, filename, lineno, module, registry,
1166
0
                        NULL, source);
1167
0
    warnings_unlock(tstate->interp);
1168
0
    Py_DECREF(filename);
1169
0
    Py_DECREF(registry);
1170
0
    Py_DECREF(module);
1171
0
    return res;
1172
0
}
1173
1174
/*[clinic input]
1175
warn as warnings_warn
1176
1177
    message: object
1178
      Text of the warning message.
1179
    category: object = None
1180
      The Warning category subclass. Defaults to UserWarning.
1181
    stacklevel: Py_ssize_t = 1
1182
      How far up the call stack to make this warning appear. A value of 2 for
1183
      example attributes the warning to the caller of the code calling warn().
1184
    source: object = None
1185
      If supplied, the destroyed object which emitted a ResourceWarning
1186
    *
1187
    skip_file_prefixes: object(type='PyTupleObject *', subclass_of='&PyTuple_Type') = NULL
1188
      An optional tuple of module filename prefixes indicating frames to skip
1189
      during stacklevel computations for stack frame attribution.
1190
1191
Issue a warning, or maybe ignore it or raise an exception.
1192
[clinic start generated code]*/
1193
1194
static PyObject *
1195
warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
1196
                   Py_ssize_t stacklevel, PyObject *source,
1197
                   PyTupleObject *skip_file_prefixes)
1198
/*[clinic end generated code: output=a68e0f6906c65f80 input=eb37c6a18bec4ea1]*/
1199
0
{
1200
0
    category = get_category(message, category);
1201
0
    if (category == NULL)
1202
0
        return NULL;
1203
0
    if (skip_file_prefixes) {
1204
0
        if (PyTuple_GET_SIZE(skip_file_prefixes) > 0) {
1205
0
            if (stacklevel < 2) {
1206
0
                stacklevel = 2;
1207
0
            }
1208
0
        } else {
1209
0
            Py_DECREF((PyObject *)skip_file_prefixes);
1210
0
            skip_file_prefixes = NULL;
1211
0
        }
1212
0
    }
1213
0
    return do_warn(message, category, stacklevel, source, skip_file_prefixes);
1214
0
}
1215
1216
static PyObject *
1217
get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno)
1218
0
{
1219
0
    PyObject *loader;
1220
0
    PyObject *module_name;
1221
0
    PyObject *get_source;
1222
0
    PyObject *source;
1223
0
    PyObject *source_list;
1224
0
    PyObject *source_line;
1225
1226
    /* stolen from import.c */
1227
0
    loader = _PyImport_BlessMyLoader(interp, module_globals);
1228
0
    if (loader == NULL) {
1229
0
        return NULL;
1230
0
    }
1231
1232
0
    int rc = PyDict_GetItemRef(module_globals, &_Py_ID(__name__),
1233
0
                               &module_name);
1234
0
    if (rc < 0 || rc == 0) {
1235
0
        Py_DECREF(loader);
1236
0
        return NULL;
1237
0
    }
1238
1239
    /* Make sure the loader implements the optional get_source() method. */
1240
0
    (void)PyObject_GetOptionalAttr(loader, &_Py_ID(get_source), &get_source);
1241
0
    Py_DECREF(loader);
1242
0
    if (!get_source) {
1243
0
        Py_DECREF(module_name);
1244
0
        return NULL;
1245
0
    }
1246
    /* Call get_source() to get the source code. */
1247
0
    source = PyObject_CallOneArg(get_source, module_name);
1248
0
    Py_DECREF(get_source);
1249
0
    Py_DECREF(module_name);
1250
0
    if (!source) {
1251
0
        return NULL;
1252
0
    }
1253
0
    if (source == Py_None) {
1254
0
        Py_DECREF(source);
1255
0
        return NULL;
1256
0
    }
1257
1258
    /* Split the source into lines. */
1259
0
    source_list = PyUnicode_Splitlines(source, 0);
1260
0
    Py_DECREF(source);
1261
0
    if (!source_list) {
1262
0
        return NULL;
1263
0
    }
1264
1265
    /* Get the source line. */
1266
0
    source_line = PyList_GetItem(source_list, lineno-1);
1267
0
    Py_XINCREF(source_line);
1268
0
    Py_DECREF(source_list);
1269
0
    return source_line;
1270
0
}
1271
1272
/*[clinic input]
1273
warn_explicit as warnings_warn_explicit
1274
1275
    message: object
1276
    category: object
1277
    filename: unicode
1278
    lineno: int
1279
    module as mod: object = NULL
1280
    registry: object = None
1281
    module_globals: object = None
1282
    source as sourceobj: object = None
1283
1284
Issue a warning, or maybe ignore it or raise an exception.
1285
[clinic start generated code]*/
1286
1287
static PyObject *
1288
warnings_warn_explicit_impl(PyObject *module, PyObject *message,
1289
                            PyObject *category, PyObject *filename,
1290
                            int lineno, PyObject *mod, PyObject *registry,
1291
                            PyObject *module_globals, PyObject *sourceobj)
1292
/*[clinic end generated code: output=c49c62b15a49a186 input=df6eeb8b45e712f1]*/
1293
0
{
1294
0
    PyObject *source_line = NULL;
1295
0
    PyObject *returned;
1296
1297
0
    PyThreadState *tstate = get_current_tstate();
1298
0
    if (tstate == NULL) {
1299
0
        return NULL;
1300
0
    }
1301
1302
0
    if (module_globals && module_globals != Py_None) {
1303
0
        if (!PyDict_Check(module_globals)) {
1304
0
            PyErr_Format(PyExc_TypeError,
1305
0
                         "module_globals must be a dict, not '%.200s'",
1306
0
                         Py_TYPE(module_globals)->tp_name);
1307
0
            return NULL;
1308
0
        }
1309
1310
0
        source_line = get_source_line(tstate->interp, module_globals, lineno);
1311
0
        if (source_line == NULL && PyErr_Occurred()) {
1312
0
            return NULL;
1313
0
        }
1314
0
    }
1315
1316
0
    warnings_lock(tstate->interp);
1317
0
    returned = warn_explicit(tstate, category, message, filename, lineno,
1318
0
                             mod, registry, source_line, sourceobj);
1319
0
    warnings_unlock(tstate->interp);
1320
0
    Py_XDECREF(source_line);
1321
0
    return returned;
1322
0
}
1323
1324
/*[clinic input]
1325
_filters_mutated_lock_held as warnings_filters_mutated_lock_held
1326
1327
[clinic start generated code]*/
1328
1329
static PyObject *
1330
warnings_filters_mutated_lock_held_impl(PyObject *module)
1331
/*[clinic end generated code: output=df5c84f044e856ec input=34208bf03d70e432]*/
1332
2
{
1333
2
    PyInterpreterState *interp = get_current_interp();
1334
2
    if (interp == NULL) {
1335
0
        return NULL;
1336
0
    }
1337
1338
2
    WarningsState *st = warnings_get_state(interp);
1339
2
    assert(st != NULL);
1340
1341
    // Note that the lock must be held by the caller.
1342
2
    if (!warnings_lock_held(st)) {
1343
0
        PyErr_SetString(PyExc_RuntimeError, "warnings lock is not held");
1344
0
        return NULL;
1345
0
    }
1346
1347
2
    st->filters_version++;
1348
1349
2
    Py_RETURN_NONE;
1350
2
}
1351
1352
/* Function to issue a warning message; may raise an exception. */
1353
1354
static int
1355
warn_unicode(PyObject *category, PyObject *message,
1356
             Py_ssize_t stack_level, PyObject *source)
1357
0
{
1358
0
    PyObject *res;
1359
1360
0
    if (category == NULL)
1361
0
        category = PyExc_RuntimeWarning;
1362
1363
0
    res = do_warn(message, category, stack_level, source, NULL);
1364
0
    if (res == NULL)
1365
0
        return -1;
1366
0
    Py_DECREF(res);
1367
1368
0
    return 0;
1369
0
}
1370
1371
static int
1372
_PyErr_WarnFormatV(PyObject *source,
1373
                   PyObject *category, Py_ssize_t stack_level,
1374
                   const char *format, va_list vargs)
1375
0
{
1376
0
    PyObject *message;
1377
0
    int res;
1378
1379
0
    message = PyUnicode_FromFormatV(format, vargs);
1380
0
    if (message == NULL)
1381
0
        return -1;
1382
1383
0
    res = warn_unicode(category, message, stack_level, source);
1384
0
    Py_DECREF(message);
1385
0
    return res;
1386
0
}
1387
1388
int
1389
PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
1390
                 const char *format, ...)
1391
0
{
1392
0
    int res;
1393
0
    va_list vargs;
1394
1395
0
    va_start(vargs, format);
1396
0
    res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
1397
0
    va_end(vargs);
1398
0
    return res;
1399
0
}
1400
1401
static int
1402
_PyErr_WarnFormat(PyObject *source, PyObject *category, Py_ssize_t stack_level,
1403
                  const char *format, ...)
1404
0
{
1405
0
    int res;
1406
0
    va_list vargs;
1407
1408
0
    va_start(vargs, format);
1409
0
    res = _PyErr_WarnFormatV(source, category, stack_level, format, vargs);
1410
0
    va_end(vargs);
1411
0
    return res;
1412
0
}
1413
1414
int
1415
PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
1416
                      const char *format, ...)
1417
0
{
1418
0
    int res;
1419
0
    va_list vargs;
1420
1421
0
    va_start(vargs, format);
1422
0
    res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
1423
0
                             stack_level, format, vargs);
1424
0
    va_end(vargs);
1425
0
    return res;
1426
0
}
1427
1428
1429
int
1430
PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
1431
0
{
1432
0
    int ret;
1433
0
    PyObject *message = PyUnicode_FromString(text);
1434
0
    if (message == NULL)
1435
0
        return -1;
1436
0
    ret = warn_unicode(category, message, stack_level, NULL);
1437
0
    Py_DECREF(message);
1438
0
    return ret;
1439
0
}
1440
1441
/* PyErr_Warn is only for backwards compatibility and will be removed.
1442
   Use PyErr_WarnEx instead. */
1443
1444
#undef PyErr_Warn
1445
1446
int
1447
PyErr_Warn(PyObject *category, const char *text)
1448
0
{
1449
0
    return PyErr_WarnEx(category, text, 1);
1450
0
}
1451
1452
/* Warning with explicit origin */
1453
int
1454
PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
1455
                         PyObject *filename, int lineno,
1456
                         PyObject *module, PyObject *registry)
1457
16.0k
{
1458
16.0k
    PyObject *res;
1459
16.0k
    if (category == NULL)
1460
0
        category = PyExc_RuntimeWarning;
1461
16.0k
    PyThreadState *tstate = get_current_tstate();
1462
16.0k
    if (tstate == NULL) {
1463
0
        return -1;
1464
0
    }
1465
1466
16.0k
    warnings_lock(tstate->interp);
1467
16.0k
    res = warn_explicit(tstate, category, message, filename, lineno,
1468
16.0k
                        module, registry, NULL, NULL);
1469
16.0k
    warnings_unlock(tstate->interp);
1470
16.0k
    if (res == NULL)
1471
0
        return -1;
1472
16.0k
    Py_DECREF(res);
1473
16.0k
    return 0;
1474
16.0k
}
1475
1476
/* Like PyErr_WarnExplicitObject, but automatically sets up context */
1477
int
1478
_PyErr_WarnExplicitObjectWithContext(PyObject *category, PyObject *message,
1479
                                     PyObject *filename, int lineno)
1480
2.27k
{
1481
2.27k
    PyObject *unused_filename, *module, *registry;
1482
2.27k
    int unused_lineno;
1483
2.27k
    int stack_level = 1;
1484
1485
2.27k
    if (!setup_context(stack_level, NULL, &unused_filename, &unused_lineno,
1486
2.27k
                       &module, &registry)) {
1487
0
        return -1;
1488
0
    }
1489
1490
2.27k
    int rc = PyErr_WarnExplicitObject(category, message, filename, lineno,
1491
2.27k
                                      module, registry);
1492
2.27k
    Py_DECREF(unused_filename);
1493
2.27k
    Py_DECREF(registry);
1494
2.27k
    Py_DECREF(module);
1495
2.27k
    return rc;
1496
2.27k
}
1497
1498
int
1499
PyErr_WarnExplicit(PyObject *category, const char *text,
1500
                   const char *filename_str, int lineno,
1501
                   const char *module_str, PyObject *registry)
1502
0
{
1503
0
    PyObject *message = PyUnicode_FromString(text);
1504
0
    if (message == NULL) {
1505
0
        return -1;
1506
0
    }
1507
0
    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1508
0
    if (filename == NULL) {
1509
0
        Py_DECREF(message);
1510
0
        return -1;
1511
0
    }
1512
0
    PyObject *module = NULL;
1513
0
    if (module_str != NULL) {
1514
0
        module = PyUnicode_FromString(module_str);
1515
0
        if (module == NULL) {
1516
0
            Py_DECREF(filename);
1517
0
            Py_DECREF(message);
1518
0
            return -1;
1519
0
        }
1520
0
    }
1521
1522
0
    int ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
1523
0
                                       module, registry);
1524
0
    Py_XDECREF(module);
1525
0
    Py_DECREF(filename);
1526
0
    Py_DECREF(message);
1527
0
    return ret;
1528
0
}
1529
1530
int
1531
PyErr_WarnExplicitFormat(PyObject *category,
1532
                         const char *filename_str, int lineno,
1533
                         const char *module_str, PyObject *registry,
1534
                         const char *format, ...)
1535
0
{
1536
0
    PyObject *message;
1537
0
    PyObject *module = NULL;
1538
0
    PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1539
0
    int ret = -1;
1540
0
    va_list vargs;
1541
1542
0
    if (filename == NULL)
1543
0
        goto exit;
1544
0
    if (module_str != NULL) {
1545
0
        module = PyUnicode_FromString(module_str);
1546
0
        if (module == NULL)
1547
0
            goto exit;
1548
0
    }
1549
1550
0
    va_start(vargs, format);
1551
0
    message = PyUnicode_FromFormatV(format, vargs);
1552
0
    if (message != NULL) {
1553
0
        PyObject *res;
1554
0
        PyThreadState *tstate = get_current_tstate();
1555
0
        if (tstate != NULL) {
1556
0
            warnings_lock(tstate->interp);
1557
0
            res = warn_explicit(tstate, category, message, filename, lineno,
1558
0
                                module, registry, NULL, NULL);
1559
0
            warnings_unlock(tstate->interp);
1560
0
            Py_DECREF(message);
1561
0
            if (res != NULL) {
1562
0
                Py_DECREF(res);
1563
0
                ret = 0;
1564
0
            }
1565
0
        }
1566
0
    }
1567
0
    va_end(vargs);
1568
0
exit:
1569
0
    Py_XDECREF(module);
1570
0
    Py_XDECREF(filename);
1571
0
    return ret;
1572
0
}
1573
1574
void
1575
_PyErr_WarnUnawaitedAgenMethod(PyAsyncGenObject *agen, PyObject *method)
1576
0
{
1577
0
    PyObject *exc = PyErr_GetRaisedException();
1578
0
    if (_PyErr_WarnFormat((PyObject *)agen, PyExc_RuntimeWarning, 1,
1579
0
                          "coroutine method %R of %R was never awaited",
1580
0
                          method, agen->ag_qualname) < 0)
1581
0
    {
1582
0
        PyErr_FormatUnraisable("Exception ignored while "
1583
0
                               "finalizing async generator %R", agen);
1584
0
    }
1585
0
    PyErr_SetRaisedException(exc);
1586
0
}
1587
1588
1589
void
1590
_PyErr_WarnUnawaitedCoroutine(PyObject *coro)
1591
0
{
1592
    /* First, we attempt to funnel the warning through
1593
       warnings._warn_unawaited_coroutine.
1594
1595
       This could raise an exception, due to:
1596
       - a bug
1597
       - some kind of shutdown-related brokenness
1598
       - succeeding, but with an "error" warning filter installed, so the
1599
         warning is converted into a RuntimeWarning exception
1600
1601
       In the first two cases, we want to print the error (so we know what it
1602
       is!), and then print a warning directly as a fallback. In the last
1603
       case, we want to print the error (since it's the warning!), but *not*
1604
       do a fallback. And after we print the error we can't check for what
1605
       type of error it was (because PyErr_WriteUnraisable clears it), so we
1606
       need a flag to keep track.
1607
1608
       Since this is called from __del__ context, it's careful to never raise
1609
       an exception.
1610
    */
1611
0
    int warned = 0;
1612
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
1613
0
    assert(interp != NULL);
1614
0
    PyObject *fn = GET_WARNINGS_ATTR(interp, _warn_unawaited_coroutine, 1);
1615
0
    if (fn) {
1616
0
        PyObject *res = PyObject_CallOneArg(fn, coro);
1617
0
        Py_DECREF(fn);
1618
0
        if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
1619
0
            warned = 1;
1620
0
        }
1621
0
        Py_XDECREF(res);
1622
0
    }
1623
1624
0
    if (PyErr_Occurred()) {
1625
0
        PyErr_FormatUnraisable("Exception ignored while "
1626
0
                               "finalizing coroutine %R", coro);
1627
0
    }
1628
1629
0
    if (!warned) {
1630
0
        if (_PyErr_WarnFormat(coro, PyExc_RuntimeWarning, 1,
1631
0
                              "coroutine '%S' was never awaited",
1632
0
                              ((PyCoroObject *)coro)->cr_qualname) < 0)
1633
0
        {
1634
0
            PyErr_FormatUnraisable("Exception ignored while "
1635
0
                                   "finalizing coroutine %R", coro);
1636
0
        }
1637
0
    }
1638
0
}
1639
1640
static PyMethodDef warnings_functions[] = {
1641
    WARNINGS_WARN_METHODDEF
1642
    WARNINGS_WARN_EXPLICIT_METHODDEF
1643
    WARNINGS_FILTERS_MUTATED_LOCK_HELD_METHODDEF
1644
    WARNINGS_ACQUIRE_LOCK_METHODDEF
1645
    WARNINGS_RELEASE_LOCK_METHODDEF
1646
    /* XXX(brett.cannon): add showwarning? */
1647
    /* XXX(brett.cannon): Reasonable to add formatwarning? */
1648
    {NULL, NULL}                /* sentinel */
1649
};
1650
1651
1652
static int
1653
warnings_module_exec(PyObject *module)
1654
16
{
1655
16
    PyInterpreterState *interp = get_current_interp();
1656
16
    if (interp == NULL) {
1657
0
        return -1;
1658
0
    }
1659
16
    WarningsState *st = warnings_get_state(interp);
1660
16
    if (st == NULL) {
1661
0
        return -1;
1662
0
    }
1663
16
    if (PyModule_AddObjectRef(module, "filters", st->filters) < 0) {
1664
0
        return -1;
1665
0
    }
1666
16
    if (PyModule_AddObjectRef(module, "_onceregistry", st->once_registry) < 0) {
1667
0
        return -1;
1668
0
    }
1669
16
    if (PyModule_AddObjectRef(module, "_defaultaction", st->default_action) < 0) {
1670
0
        return -1;
1671
0
    }
1672
16
    if (PyModule_AddObjectRef(module, "_warnings_context", st->context) < 0) {
1673
0
        return -1;
1674
0
    }
1675
16
    return 0;
1676
16
}
1677
1678
1679
static PyModuleDef_Slot warnings_slots[] = {
1680
    {Py_mod_exec, warnings_module_exec},
1681
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
1682
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
1683
    {0, NULL}
1684
};
1685
1686
static struct PyModuleDef warnings_module = {
1687
    PyModuleDef_HEAD_INIT,
1688
    .m_name = MODULE_NAME,
1689
    .m_doc = warnings__doc__,
1690
    .m_size = 0,
1691
    .m_methods = warnings_functions,
1692
    .m_slots = warnings_slots,
1693
};
1694
1695
1696
PyMODINIT_FUNC
1697
_PyWarnings_Init(void)
1698
16
{
1699
16
    return PyModuleDef_Init(&warnings_module);
1700
16
}
1701
1702
// We need this to ensure that warnings still work until late in finalization.
1703
void
1704
_PyWarnings_Fini(PyInterpreterState *interp)
1705
0
{
1706
0
    warnings_clear_state(&interp->warnings);
1707
0
}