Coverage Report

Created: 2025-11-11 06:44

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