summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Podoprigora <kirill.bast9@mail.ru>2024-05-16 20:27:59 (GMT)
committerGitHub <noreply@github.com>2024-05-16 20:27:59 (GMT)
commit100c7ab00ab66a8c0d54582f35e38d8eb691743c (patch)
tree64dc41a7a3be5a41790d7c8c197eeedf294ab4fb
parent4702b7b5bdc07d046576b4126cf4e4f5f7145abb (diff)
downloadcpython-100c7ab00ab66a8c0d54582f35e38d8eb691743c.zip
cpython-100c7ab00ab66a8c0d54582f35e38d8eb691743c.tar.gz
cpython-100c7ab00ab66a8c0d54582f35e38d8eb691743c.tar.bz2
gh-119049: Fix incorrect display of warning which is constructed by C API (GH-119063)
The source line was not displayed if the warnings module had not yet been imported.
-rw-r--r--Lib/test/test_capi/test_exceptions.py44
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-05-16-23-02-03.gh-issue-119049.qpd_S-.rst2
-rw-r--r--Modules/_testcapimodule.c10
-rw-r--r--Python/_warnings.c5
4 files changed, 57 insertions, 4 deletions
diff --git a/Lib/test/test_capi/test_exceptions.py b/Lib/test/test_capi/test_exceptions.py
index 1d158e3..c475b6d 100644
--- a/Lib/test/test_capi/test_exceptions.py
+++ b/Lib/test/test_capi/test_exceptions.py
@@ -3,11 +3,12 @@ import os
import re
import sys
import unittest
+import textwrap
from test import support
from test.support import import_helper
from test.support.os_helper import TESTFN, TESTFN_UNDECODABLE
-from test.support.script_helper import assert_python_failure
+from test.support.script_helper import assert_python_failure, assert_python_ok
from test.support.testcase import ExceptionIsLikeMixin
from .test_misc import decode_stderr
@@ -68,6 +69,47 @@ class Test_Exceptions(unittest.TestCase):
else:
self.assertTrue(False)
+ def test_warn_with_stacklevel(self):
+ code = textwrap.dedent('''\
+ import _testcapi
+
+ def foo():
+ _testcapi.function_set_warning()
+
+ foo() # line 6
+
+
+ foo() # line 9
+ ''')
+ proc = assert_python_ok("-c", code)
+ warnings = proc.err.splitlines()
+ self.assertEqual(warnings, [
+ b'<string>:6: RuntimeWarning: Testing PyErr_WarnEx',
+ b' foo() # line 6',
+ b'<string>:9: RuntimeWarning: Testing PyErr_WarnEx',
+ b' foo() # line 9',
+ ])
+
+ def test_warn_during_finalization(self):
+ code = textwrap.dedent('''\
+ import _testcapi
+
+ class Foo:
+ def foo(self):
+ _testcapi.function_set_warning()
+ def __del__(self):
+ self.foo()
+
+ ref = Foo()
+ ''')
+ proc = assert_python_ok("-c", code)
+ warnings = proc.err.splitlines()
+ # Due to the finalization of the interpreter, the source will be ommited
+ # because the ``warnings`` module cannot be imported at this time
+ self.assertEqual(warnings, [
+ b'<string>:7: RuntimeWarning: Testing PyErr_WarnEx',
+ ])
+
class Test_FatalError(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-16-23-02-03.gh-issue-119049.qpd_S-.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-16-23-02-03.gh-issue-119049.qpd_S-.rst
new file mode 100644
index 0000000..1d7aad8
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-16-23-02-03.gh-issue-119049.qpd_S-.rst
@@ -0,0 +1,2 @@
+Fix displaying the source line for warnings created by the C API if the
+:mod:`warnings` module had not yet been imported.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index ff31724..f99ebf0 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3303,6 +3303,15 @@ failed:
return NULL;
}
+static PyObject *
+function_set_warning(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+ if (PyErr_WarnEx(PyExc_RuntimeWarning, "Testing PyErr_WarnEx", 2)) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
static PyMethodDef TestMethods[] = {
{"set_errno", set_errno, METH_VARARGS},
{"test_config", test_config, METH_NOARGS},
@@ -3444,6 +3453,7 @@ static PyMethodDef TestMethods[] = {
{"function_set_closure", function_set_closure, METH_VARARGS, NULL},
{"check_pyimport_addmodule", check_pyimport_addmodule, METH_VARARGS},
{"test_weakref_capi", test_weakref_capi, METH_NOARGS},
+ {"function_set_warning", function_set_warning, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
diff --git a/Python/_warnings.c b/Python/_warnings.c
index 793cbc6..17404d3 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -569,10 +569,9 @@ call_show_warning(PyThreadState *tstate, PyObject *category,
PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;
PyInterpreterState *interp = tstate->interp;
- /* If the source parameter is set, try to get the Python implementation.
- The Python implementation is able to log the traceback where the source
+ /* The Python implementation is able to log the traceback where the source
was allocated, whereas the C implementation doesn't. */
- show_fn = GET_WARNINGS_ATTR(interp, _showwarnmsg, source != NULL);
+ show_fn = GET_WARNINGS_ATTR(interp, _showwarnmsg, 1);
if (show_fn == NULL) {
if (PyErr_Occurred())
return -1;