Coverage Report

Created: 2026-04-12 06:54

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