Coverage Report

Created: 2026-05-16 06:46

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.21M
{
31
2.21M
    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.21M
    return 1;
38
2.21M
}
39
40
static inline PyInterpreterState *
41
get_current_interp(void)
42
76.7k
{
43
76.7k
    PyInterpreterState *interp = _PyInterpreterState_GET();
44
76.7k
    return check_interp(interp) ? interp : NULL;
45
76.7k
}
46
47
static inline PyThreadState *
48
get_current_tstate(void)
49
2.14M
{
50
2.14M
    PyThreadState *tstate = _PyThreadState_GET();
51
2.14M
    if (tstate == NULL) {
52
0
        (void)check_interp(NULL);
53
0
        return NULL;
54
0
    }
55
2.14M
    return check_interp(tstate->interp) ? tstate : NULL;
56
2.14M
}
57
58
/* Given a module object, get its per-module state. */
59
static WarningsState *
60
warnings_get_state(PyInterpreterState *interp)
61
4.10M
{
62
4.10M
    return &interp->warnings;
63
4.10M
}
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
185
{
79
185
    PyObject *modname_obj = NULL;
80
81
    /* Default to "no module name" for initial filter set */
82
185
    if (modname != NULL) {
83
37
        modname_obj = PyUnicode_InternFromString(modname);
84
37
        if (modname_obj == NULL) {
85
0
            return NULL;
86
0
        }
87
148
    } else {
88
148
        modname_obj = Py_NewRef(Py_None);
89
148
    }
90
91
    /* This assumes the line number is zero for now. */
92
185
    PyObject *filter = PyTuple_Pack(5, action_str, Py_None,
93
185
                                    category, modname_obj, _PyLong_GetZero());
94
185
    Py_DECREF(modname_obj);
95
185
    return filter;
96
185
}
97
#endif
98
99
static PyObject *
100
init_filters(PyInterpreterState *interp)
101
37
{
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
37
    PyObject *filters = PyList_New(5);
108
37
    if (filters == NULL) {
109
0
        return NULL;
110
0
    }
111
112
37
    size_t pos = 0;  /* Post-incremented in each use. */
113
37
#define ADD(TYPE, ACTION, MODNAME) \
114
185
    PyList_SET_ITEM(filters, pos++, \
115
185
                    create_filter(TYPE, &_Py_ID(ACTION), MODNAME));
116
37
    ADD(PyExc_DeprecationWarning, default, "__main__");
117
37
    ADD(PyExc_DeprecationWarning, ignore, NULL);
118
37
    ADD(PyExc_PendingDeprecationWarning, ignore, NULL);
119
37
    ADD(PyExc_ImportWarning, ignore, NULL);
120
37
    ADD(PyExc_ResourceWarning, ignore, NULL);
121
37
#undef ADD
122
123
222
    for (size_t x = 0; x < pos; x++) {
124
185
        if (PyList_GET_ITEM(filters, x) == NULL) {
125
0
            Py_DECREF(filters);
126
0
            return NULL;
127
0
        }
128
185
    }
129
37
    return filters;
130
37
#endif
131
37
}
132
133
/* Initialize the given warnings module state. */
134
int
135
_PyWarnings_InitState(PyInterpreterState *interp)
136
37
{
137
37
    WarningsState *st = &interp->warnings;
138
139
37
    if (st->filters == NULL) {
140
37
        st->filters = init_filters(interp);
141
37
        if (st->filters == NULL) {
142
0
            return -1;
143
0
        }
144
37
    }
145
146
37
    if (st->once_registry == NULL) {
147
37
        st->once_registry = PyDict_New();
148
37
        if (st->once_registry == NULL) {
149
0
            return -1;
150
0
        }
151
37
    }
152
153
37
    if (st->default_action == NULL) {
154
37
        st->default_action = PyUnicode_FromString("default");
155
37
        if (st->default_action == NULL) {
156
0
            return -1;
157
0
        }
158
37
    }
159
160
37
    if (st->context == NULL) {
161
37
        st->context = PyContextVar_New("_warnings_context", NULL);
162
37
        if (st->context == NULL) {
163
0
            return -1;
164
0
        }
165
37
    }
166
167
37
    st->filters_version = 0;
168
37
    return 0;
169
37
}
170
171
172
/*************************************************************************/
173
174
static int
175
check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg, PyObject *arg2)
176
2.63M
{
177
2.63M
    PyObject *result;
178
2.63M
    int rc;
179
180
    /* A 'None' filter always matches */
181
2.63M
    if (obj == Py_None)
182
2.37M
        return 1;
183
184
    /* An internal plain text default filter must match exactly */
185
262k
    if (PyUnicode_CheckExact(obj)) {
186
262k
        if (arg == NULL) {
187
0
            return 0;
188
0
        }
189
262k
        int cmp_result = PyUnicode_Compare(obj, arg);
190
262k
        if (cmp_result == -1 && PyErr_Occurred()) {
191
0
            return -1;
192
0
        }
193
262k
        return !cmp_result;
194
262k
    }
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.05M
    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.05M
{
225
1.05M
    PyObject *warnings_module, *obj;
226
227
    /* don't try to import after the start of the Python finallization */
228
1.05M
    if (try_import && !_Py_IsInterpreterFinalizing(interp)) {
229
259k
        warnings_module = PyImport_Import(&_Py_ID(warnings));
230
259k
        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
259k
    }
239
794k
    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
794k
        if (!_PyImport_GetModules(interp)) {
245
0
            return NULL;
246
0
        }
247
794k
        warnings_module = PyImport_GetModule(&_Py_ID(warnings));
248
794k
        if (warnings_module == NULL)
249
303
            return NULL;
250
794k
    }
251
252
1.05M
    (void)PyObject_GetOptionalAttr(warnings_module, attr, &obj);
253
1.05M
    Py_DECREF(warnings_module);
254
1.05M
    return obj;
255
1.05M
}
256
257
static inline void
258
warnings_lock(PyInterpreterState *interp)
259
1.10M
{
260
1.10M
    WarningsState *st = warnings_get_state(interp);
261
1.10M
    assert(st != NULL);
262
1.10M
    _PyRecursiveMutex_Lock(&st->lock);
263
1.10M
}
264
265
static inline int
266
warnings_unlock(PyInterpreterState *interp)
267
1.10M
{
268
1.10M
    WarningsState *st = warnings_get_state(interp);
269
1.10M
    assert(st != NULL);
270
1.10M
    return _PyRecursiveMutex_TryUnlock(&st->lock);
271
1.10M
}
272
273
static inline bool
274
warnings_lock_held(WarningsState *st)
275
25.5k
{
276
25.5k
    return PyMutex_IsLocked(&st->lock.mutex);
277
25.5k
}
278
279
static PyObject *
280
get_warnings_context(PyInterpreterState *interp)
281
275k
{
282
275k
    WarningsState *st = warnings_get_state(interp);
283
275k
    assert(PyContextVar_CheckExact(st->context));
284
275k
    PyObject *ctx;
285
275k
    if (PyContextVar_Get(st->context, NULL, &ctx) < 0) {
286
0
        return NULL;
287
0
    }
288
275k
    if (ctx == NULL) {
289
275k
        Py_RETURN_NONE;
290
275k
    }
291
0
    return ctx;
292
275k
}
293
294
static PyObject *
295
get_warnings_context_filters(PyInterpreterState *interp)
296
275k
{
297
275k
    PyObject *ctx = get_warnings_context(interp);
298
275k
    if (ctx == NULL) {
299
0
        return NULL;
300
0
    }
301
275k
    if (ctx == Py_None) {
302
275k
        Py_RETURN_NONE;
303
275k
    }
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
275k
{
322
275k
    WarningsState *st = warnings_get_state(interp);
323
275k
    PyObject *warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
324
275k
    if (warnings_filters == NULL) {
325
303
        if (PyErr_Occurred())
326
0
            return NULL;
327
303
    }
328
274k
    else {
329
274k
        Py_SETREF(st->filters, warnings_filters);
330
274k
    }
331
332
275k
    PyObject *filters = st->filters;
333
275k
    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
275k
    return filters;
339
275k
}
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
25.5k
{
350
25.5k
    PyInterpreterState *interp = get_current_interp();
351
25.5k
    if (interp == NULL) {
352
0
        return NULL;
353
0
    }
354
25.5k
    warnings_lock(interp);
355
25.5k
    Py_RETURN_NONE;
356
25.5k
}
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
25.5k
{
367
25.5k
    PyInterpreterState *interp = get_current_interp();
368
25.5k
    if (interp == NULL) {
369
0
        return NULL;
370
0
    }
371
25.5k
    if (warnings_unlock(interp) < 0) {
372
0
        PyErr_SetString(PyExc_RuntimeError, "cannot release un-acquired lock");
373
0
        return NULL;
374
0
    }
375
25.5k
    Py_RETURN_NONE;
376
25.5k
}
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
259k
{
409
259k
    WarningsState *st = warnings_get_state(interp);
410
259k
    assert(st != NULL);
411
412
259k
    assert(warnings_lock_held(st));
413
414
259k
    PyObject *default_action = GET_WARNINGS_ATTR(interp, defaultaction, 0);
415
259k
    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
259k
    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
259k
    Py_SETREF(st->default_action, default_action);
431
259k
    return default_action;
432
259k
}
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
275k
              PyObject **item, PyObject **matched_action) {
441
275k
    bool result = true;
442
275k
    *matched_action = NULL;
443
    /* Avoid the filters list changing while we iterate over it. */
444
275k
    Py_BEGIN_CRITICAL_SECTION(filters);
445
1.57M
    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(filters); i++) {
446
1.31M
        PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
447
1.31M
        Py_ssize_t ln;
448
1.31M
        int is_subclass, good_msg, good_mod;
449
450
1.31M
        tmp_item = PyList_GET_ITEM(filters, i);
451
1.31M
        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.31M
        Py_INCREF(tmp_item);
460
1.31M
        action = PyTuple_GET_ITEM(tmp_item, 0);
461
1.31M
        msg = PyTuple_GET_ITEM(tmp_item, 1);
462
1.31M
        cat = PyTuple_GET_ITEM(tmp_item, 2);
463
1.31M
        mod = PyTuple_GET_ITEM(tmp_item, 3);
464
1.31M
        ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
465
466
1.31M
        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.31M
        good_msg = check_matched(interp, msg, text, NULL);
476
1.31M
        if (good_msg == -1) {
477
0
            Py_DECREF(tmp_item);
478
0
            result = false;
479
0
            break;
480
0
        }
481
482
1.31M
        good_mod = check_matched(interp, mod, module, filename);
483
1.31M
        if (good_mod == -1) {
484
0
            Py_DECREF(tmp_item);
485
0
            result = false;
486
0
            break;
487
0
        }
488
489
1.31M
        is_subclass = PyObject_IsSubclass(category, cat);
490
1.31M
        if (is_subclass == -1) {
491
0
            Py_DECREF(tmp_item);
492
0
            result = false;
493
0
            break;
494
0
        }
495
496
1.31M
        ln = PyLong_AsSsize_t(ln_obj);
497
1.31M
        if (ln == -1 && PyErr_Occurred()) {
498
0
            Py_DECREF(tmp_item);
499
0
            result = false;
500
0
            break;
501
0
        }
502
503
1.31M
        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
504
15.1k
            *item = tmp_item;
505
15.1k
            *matched_action = action;
506
15.1k
            result = true;
507
15.1k
            break;
508
15.1k
        }
509
510
1.30M
        Py_DECREF(tmp_item);
511
1.30M
    }
512
275k
    Py_END_CRITICAL_SECTION();
513
275k
    return result;
514
275k
}
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
275k
{
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
275k
    PyObject *context_filters = get_warnings_context_filters(interp);
530
275k
    if (context_filters == NULL) {
531
0
        return NULL;
532
0
    }
533
275k
    bool use_global_filters = false;
534
275k
    if (context_filters == Py_None) {
535
275k
        use_global_filters = true;
536
275k
    } 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
275k
    PyObject *action;
550
551
275k
    if (use_global_filters) {
552
        /* check warnings.filters list */
553
275k
        PyObject *filters = get_warnings_filters(interp);
554
275k
        if (filters == NULL) {
555
0
            return NULL;
556
0
        }
557
275k
        if (!filter_search(interp, category, text, lineno, module, filename, "filters",
558
275k
                           filters, item, &action)) {
559
0
            return NULL;
560
0
        }
561
275k
        if (action != NULL) {
562
15.1k
            return action;
563
15.1k
        }
564
275k
    }
565
566
259k
    action = get_default_action(interp);
567
259k
    if (action != NULL) {
568
259k
        *item = Py_NewRef(Py_None);
569
259k
        return action;
570
259k
    }
571
572
0
    return NULL;
573
259k
}
574
575
576
static int
577
already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,
578
               int should_set)
579
1.06M
{
580
1.06M
    PyObject *already_warned;
581
582
1.06M
    if (key == NULL)
583
0
        return -1;
584
585
1.06M
    WarningsState *st = warnings_get_state(interp);
586
1.06M
    assert(st != NULL);
587
1.06M
    assert(warnings_lock_held(st));
588
589
1.06M
    PyObject *version_obj;
590
1.06M
    if (PyDict_GetItemRef(registry, &_Py_ID(version), &version_obj) < 0) {
591
0
        return -1;
592
0
    }
593
1.06M
    bool should_update_version = (
594
1.06M
        version_obj == NULL
595
1.06M
        || !PyLong_CheckExact(version_obj)
596
1.06M
        || PyLong_AsLong(version_obj) != st->filters_version
597
1.06M
    );
598
1.06M
    Py_XDECREF(version_obj);
599
1.06M
    if (should_update_version) {
600
4.42k
        PyDict_Clear(registry);
601
4.42k
        version_obj = PyLong_FromLong(st->filters_version);
602
4.42k
        if (version_obj == NULL)
603
0
            return -1;
604
4.42k
        if (PyDict_SetItem(registry, &_Py_ID(version), version_obj) < 0) {
605
0
            Py_DECREF(version_obj);
606
0
            return -1;
607
0
        }
608
4.42k
        Py_DECREF(version_obj);
609
4.42k
    }
610
1.05M
    else {
611
1.05M
        if (PyDict_GetItemRef(registry, key, &already_warned) < 0) {
612
0
            return -1;
613
0
        }
614
1.05M
        if (already_warned != NULL) {
615
801k
            int rc = PyObject_IsTrue(already_warned);
616
801k
            Py_DECREF(already_warned);
617
801k
            if (rc != 0)
618
801k
                return rc;
619
801k
        }
620
1.05M
    }
621
622
    /* This warning wasn't found in the registry, set it. */
623
262k
    if (should_set)
624
0
        return PyDict_SetItem(registry, key, Py_True);
625
262k
    return 0;
626
262k
}
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
259k
{
721
259k
    PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;
722
259k
    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
259k
    show_fn = GET_WARNINGS_ATTR(interp, _showwarnmsg, 1);
727
259k
    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
259k
    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
259k
    warnmsg_cls = GET_WARNINGS_ATTR(interp, WarningMessage, 0);
741
259k
    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
259k
    msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category,
750
259k
            filename, lineno_obj, Py_None, Py_None,
751
259k
            source ? source : Py_None, module,
752
259k
            NULL);
753
259k
    Py_DECREF(warnmsg_cls);
754
259k
    if (msg == NULL)
755
0
        goto error;
756
757
259k
    res = PyObject_CallOneArg(show_fn, msg);
758
259k
    Py_DECREF(show_fn);
759
259k
    Py_DECREF(msg);
760
761
259k
    if (res == NULL)
762
0
        return -1;
763
764
259k
    Py_DECREF(res);
765
259k
    return 0;
766
767
0
error:
768
0
    Py_XDECREF(show_fn);
769
0
    return -1;
770
259k
}
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
1.07M
{
778
1.07M
    PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
779
1.07M
    PyObject *item = NULL;
780
1.07M
    PyObject *action;
781
1.07M
    int rc;
782
1.07M
    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
1.07M
    if (module == Py_None)
789
0
        Py_RETURN_NONE;
790
791
1.07M
    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
1.07M
    Py_INCREF(message);  /* DECREF'ed in cleanup. */
798
1.07M
    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
1.07M
    else {
805
1.07M
        text = message;
806
1.07M
        message = PyObject_CallOneArg(category, message);
807
1.07M
        if (message == NULL)
808
0
            goto cleanup;
809
1.07M
    }
810
811
1.07M
    lineno_obj = PyLong_FromLong(lineno);
812
1.07M
    if (lineno_obj == NULL)
813
0
        goto cleanup;
814
815
1.07M
    if (source == Py_None) {
816
1.06M
        source = NULL;
817
1.06M
    }
818
819
    /* Create key. */
820
1.07M
    key = PyTuple_Pack(3, text, category, lineno_obj);
821
1.07M
    if (key == NULL)
822
0
        goto cleanup;
823
824
1.07M
    if ((registry != NULL) && (registry != Py_None)) {
825
1.06M
        rc = already_warned(interp, registry, key, 0);
826
1.06M
        if (rc == -1)
827
0
            goto cleanup;
828
1.06M
        else if (rc == 1)
829
801k
            goto return_none;
830
        /* Else this warning hasn't been generated before. */
831
1.06M
    }
832
833
275k
    action = get_filter(interp, category, text, lineno, module, filename, &item);
834
275k
    if (action == NULL)
835
0
        goto cleanup;
836
837
275k
    if (_PyUnicode_EqualToASCIIString(action, "error")) {
838
0
        PyErr_SetObject(category, message);
839
0
        goto cleanup;
840
0
    }
841
842
275k
    if (_PyUnicode_EqualToASCIIString(action, "ignore")) {
843
15.1k
        goto return_none;
844
15.1k
    }
845
846
    /* Store in the registry that we've been here, *except* when the action
847
       is "always" or "all". */
848
259k
    rc = 0;
849
259k
    if (!_PyUnicode_EqualToASCIIString(action, "always") && !_PyUnicode_EqualToASCIIString(action, "all")) {
850
259k
        if (registry != NULL && registry != Py_None &&
851
259k
            PyDict_SetItem(registry, key, Py_True) < 0)
852
0
        {
853
0
            goto cleanup;
854
0
        }
855
856
259k
        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
259k
        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
259k
        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
259k
    }
877
878
259k
    if (rc == 1)  /* Already warned for this module. */
879
0
        goto return_none;
880
259k
    if (rc == 0) {
881
259k
        if (call_show_warning(tstate, category, text, message, filename,
882
259k
                              lineno, lineno_obj, sourceline, source, module) < 0)
883
0
            goto cleanup;
884
259k
    }
885
0
    else /* if (rc == -1) */
886
0
        goto cleanup;
887
888
1.07M
 return_none:
889
1.07M
    result = Py_NewRef(Py_None);
890
891
1.07M
 cleanup:
892
1.07M
    Py_XDECREF(item);
893
1.07M
    Py_XDECREF(key);
894
1.07M
    Py_XDECREF(text);
895
1.07M
    Py_XDECREF(lineno_obj);
896
1.07M
    Py_XDECREF(message);
897
1.07M
    return result;  /* Py_None or NULL. */
898
1.07M
}
899
900
static PyObject *
901
get_frame_filename(PyFrameObject *frame)
902
20.7M
{
903
20.7M
    PyCodeObject *code = PyFrame_GetCode(frame);
904
20.7M
    PyObject *filename = code->co_filename;
905
20.7M
    Py_DECREF(code);
906
20.7M
    return filename;
907
20.7M
}
908
909
static bool
910
is_internal_filename(PyObject *filename)
911
20.7M
{
912
20.7M
    if (!PyUnicode_Check(filename)) {
913
0
        return false;
914
0
    }
915
916
20.7M
    int contains = PyUnicode_Contains(filename, &_Py_ID(importlib));
917
20.7M
    if (contains < 0) {
918
0
        return false;
919
0
    }
920
20.7M
    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
20.7M
    return false;
931
20.7M
}
932
933
static bool
934
is_filename_to_skip(PyObject *filename, PyTupleObject *skip_file_prefixes)
935
19.6M
{
936
19.6M
    if (skip_file_prefixes) {
937
264
        if (!PyUnicode_Check(filename)) {
938
0
            return false;
939
0
        }
940
941
264
        Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
942
352
        for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
943
264
        {
944
264
            PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
945
264
            Py_ssize_t found = PyUnicode_Tailmatch(filename, prefix,
946
264
                                                   0, PY_SSIZE_T_MAX, -1);
947
264
            if (found == 1) {
948
176
                return true;
949
176
            }
950
88
            if (found < 0) {
951
0
                return false;
952
0
            }
953
88
        }
954
264
    }
955
19.6M
    return false;
956
19.6M
}
957
958
static bool
959
is_internal_frame(PyFrameObject *frame)
960
1.06M
{
961
1.06M
    if (frame == NULL) {
962
0
        return false;
963
0
    }
964
965
1.06M
    PyObject *filename = get_frame_filename(frame);
966
1.06M
    if (filename == NULL) {
967
0
        return false;
968
0
    }
969
970
1.06M
    return is_internal_filename(filename);
971
1.06M
}
972
973
static PyFrameObject *
974
next_external_frame(PyFrameObject *frame, PyTupleObject *skip_file_prefixes)
975
19.6M
{
976
19.6M
    PyObject *frame_filename;
977
19.6M
    do {
978
19.6M
        PyFrameObject *back = PyFrame_GetBack(frame);
979
19.6M
        Py_SETREF(frame, back);
980
19.6M
    } while (frame != NULL && (frame_filename = get_frame_filename(frame)) &&
981
19.6M
             (is_internal_filename(frame_filename) ||
982
19.6M
              is_filename_to_skip(frame_filename, skip_file_prefixes)));
983
984
19.6M
    return frame;
985
19.6M
}
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
1.06M
{
996
1.06M
    PyObject *globals;
997
998
    /* Setup globals, filename and lineno. */
999
1.06M
    PyThreadState *tstate = get_current_tstate();
1000
1.06M
    if (tstate == NULL) {
1001
0
        return 0;
1002
0
    }
1003
1.06M
    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
88
        Py_ssize_t prefixes = PyTuple_GET_SIZE(skip_file_prefixes);
1007
176
        for (Py_ssize_t idx = 0; idx < prefixes; ++idx)
1008
88
        {
1009
88
            PyObject *prefix = PyTuple_GET_ITEM(skip_file_prefixes, idx);
1010
88
            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
88
        }
1017
88
    }
1018
1.06M
    PyInterpreterState *interp = tstate->interp;
1019
1.06M
    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
1.06M
    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
1.06M
    else {
1029
20.7M
        while (--stack_level > 0 && f != NULL) {
1030
19.6M
            f = next_external_frame(f, skip_file_prefixes);
1031
19.6M
        }
1032
1.06M
    }
1033
1034
1.06M
    if (f == NULL) {
1035
0
        globals = interp->sysdict;
1036
0
        *filename = PyUnicode_FromString("<sys>");
1037
0
        *lineno = 0;
1038
0
    }
1039
1.06M
    else {
1040
1.06M
        globals = f->f_frame->f_globals;
1041
1.06M
        *filename = Py_NewRef(_PyFrame_GetCode(f->f_frame)->co_filename);
1042
1.06M
        *lineno = PyFrame_GetLineNumber(f);
1043
1.06M
        Py_DECREF(f);
1044
1.06M
    }
1045
1046
1.06M
    *module = NULL;
1047
1048
    /* Setup registry. */
1049
1.06M
    assert(globals != NULL);
1050
1.06M
    assert(PyAnyDict_Check(globals));
1051
1.06M
    int rc = PyDict_GetItemRef(globals, &_Py_ID(__warningregistry__),
1052
1.06M
                               registry);
1053
1.06M
    if (rc < 0) {
1054
0
        goto handle_error;
1055
0
    }
1056
1.06M
    if (*registry == NULL) {
1057
7
        *registry = PyDict_New();
1058
7
        if (*registry == NULL)
1059
0
            goto handle_error;
1060
1061
7
         rc = PyDict_SetItem(globals, &_Py_ID(__warningregistry__), *registry);
1062
7
         if (rc < 0)
1063
0
            goto handle_error;
1064
7
    }
1065
1066
    /* Setup module. */
1067
1.06M
    rc = PyDict_GetItemRef(globals, &_Py_ID(__name__), module);
1068
1.06M
    if (rc < 0) {
1069
0
        goto handle_error;
1070
0
    }
1071
1.06M
    if (rc > 0) {
1072
1.06M
        if (Py_IsNone(*module) || PyUnicode_Check(*module)) {
1073
1.06M
            return 1;
1074
1.06M
        }
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
1.06M
{
1094
1.06M
    if (PyObject_TypeCheck(message, (PyTypeObject *)PyExc_Warning)) {
1095
        /* Ignore the category argument. */
1096
0
        return (PyObject*)Py_TYPE(message);
1097
0
    }
1098
1.06M
    if (category == NULL || category == Py_None) {
1099
4.53k
        return PyExc_UserWarning;
1100
4.53k
    }
1101
1102
    /* Validate category. */
1103
1.05M
    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
1.05M
    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
1.05M
    return category;
1117
1.05M
}
1118
1119
static PyObject *
1120
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
1121
        PyObject *source, PyTupleObject *skip_file_prefixes)
1122
1.06M
{
1123
1.06M
    PyObject *filename, *module, *registry, *res;
1124
1.06M
    int lineno;
1125
1126
1.06M
    PyThreadState *tstate = get_current_tstate();
1127
1.06M
    if (tstate == NULL) {
1128
0
        return NULL;
1129
0
    }
1130
1131
1.06M
    if (!setup_context(stack_level, skip_file_prefixes,
1132
1.06M
                       &filename, &lineno, &module, &registry))
1133
0
        return NULL;
1134
1135
1.06M
    warnings_lock(tstate->interp);
1136
1.06M
    res = warn_explicit(tstate, category, message, filename, lineno, module, registry,
1137
1.06M
                        NULL, source);
1138
1.06M
    warnings_unlock(tstate->interp);
1139
1.06M
    Py_DECREF(filename);
1140
1.06M
    Py_DECREF(registry);
1141
1.06M
    Py_DECREF(module);
1142
1.06M
    return res;
1143
1.06M
}
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
1.06M
{
1171
1.06M
    category = get_category(message, category);
1172
1.06M
    if (category == NULL)
1173
0
        return NULL;
1174
1.06M
    if (skip_file_prefixes) {
1175
88
        if (PyTuple_GET_SIZE(skip_file_prefixes) > 0) {
1176
88
            if (stacklevel < 2) {
1177
88
                stacklevel = 2;
1178
88
            }
1179
88
        } else {
1180
0
            Py_DECREF((PyObject *)skip_file_prefixes);
1181
0
            skip_file_prefixes = NULL;
1182
0
        }
1183
88
    }
1184
1.06M
    return do_warn(message, category, stacklevel, source, skip_file_prefixes);
1185
1.06M
}
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
25.5k
{
1305
25.5k
    PyInterpreterState *interp = get_current_interp();
1306
25.5k
    if (interp == NULL) {
1307
0
        return NULL;
1308
0
    }
1309
1310
25.5k
    WarningsState *st = warnings_get_state(interp);
1311
25.5k
    assert(st != NULL);
1312
1313
    // Note that the lock must be held by the caller.
1314
25.5k
    if (!warnings_lock_held(st)) {
1315
0
        PyErr_SetString(PyExc_RuntimeError, "warnings lock is not held");
1316
0
        return NULL;
1317
0
    }
1318
1319
25.5k
    st->filters_version++;
1320
1321
25.5k
    Py_RETURN_NONE;
1322
25.5k
}
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
303
{
1330
303
    PyObject *res;
1331
1332
303
    if (category == NULL)
1333
0
        category = PyExc_RuntimeWarning;
1334
1335
303
    res = do_warn(message, category, stack_level, source, NULL);
1336
303
    if (res == NULL)
1337
0
        return -1;
1338
303
    Py_DECREF(res);
1339
1340
303
    return 0;
1341
303
}
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
303
{
1348
303
    PyObject *message;
1349
303
    int res;
1350
1351
303
    message = PyUnicode_FromFormatV(format, vargs);
1352
303
    if (message == NULL)
1353
0
        return -1;
1354
1355
303
    res = warn_unicode(category, message, stack_level, source);
1356
303
    Py_DECREF(message);
1357
303
    return res;
1358
303
}
1359
1360
int
1361
PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
1362
                 const char *format, ...)
1363
303
{
1364
303
    int res;
1365
303
    va_list vargs;
1366
1367
303
    va_start(vargs, format);
1368
303
    res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
1369
303
    va_end(vargs);
1370
303
    return res;
1371
303
}
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
12.6k
{
1430
12.6k
    PyObject *res;
1431
12.6k
    if (category == NULL)
1432
0
        category = PyExc_RuntimeWarning;
1433
12.6k
    PyThreadState *tstate = get_current_tstate();
1434
12.6k
    if (tstate == NULL) {
1435
0
        return -1;
1436
0
    }
1437
1438
12.6k
    warnings_lock(tstate->interp);
1439
12.6k
    res = warn_explicit(tstate, category, message, filename, lineno,
1440
12.6k
                        module, registry, NULL, NULL);
1441
12.6k
    warnings_unlock(tstate->interp);
1442
12.6k
    if (res == NULL)
1443
0
        return -1;
1444
12.6k
    Py_DECREF(res);
1445
12.6k
    return 0;
1446
12.6k
}
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
37
{
1605
37
    PyInterpreterState *interp = get_current_interp();
1606
37
    if (interp == NULL) {
1607
0
        return -1;
1608
0
    }
1609
37
    WarningsState *st = warnings_get_state(interp);
1610
37
    if (st == NULL) {
1611
0
        return -1;
1612
0
    }
1613
37
    if (PyModule_AddObjectRef(module, "filters", st->filters) < 0) {
1614
0
        return -1;
1615
0
    }
1616
37
    if (PyModule_AddObjectRef(module, "_onceregistry", st->once_registry) < 0) {
1617
0
        return -1;
1618
0
    }
1619
37
    if (PyModule_AddObjectRef(module, "_defaultaction", st->default_action) < 0) {
1620
0
        return -1;
1621
0
    }
1622
37
    if (PyModule_AddObjectRef(module, "_warnings_context", st->context) < 0) {
1623
0
        return -1;
1624
0
    }
1625
37
    return 0;
1626
37
}
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
37
{
1650
37
    return PyModuleDef_Init(&warnings_module);
1651
37
}
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
}