Coverage Report

Created: 2026-06-01 06:14

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