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