diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index bfb43025de11405..521d2f64583720a 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -1109,6 +1109,21 @@ def test_showwarnmsg_missing(self): self.module._showwarnmsg = show self.assertIn(text, result) + @support.cpython_only + def test_showwarnmsg_missing_source_line(self): + # gh-143201: the C fallback must strip the source line like Python. + lineno = sys._getframe().f_lineno + with self.module.catch_warnings(), \ + support.swap_attr(self.module, '_showwarnmsg', None), \ + support.captured_stderr() as stream: + self.module.simplefilter("always") + del self.module._showwarnmsg # use the C fallback + self.module.warn_explicit('eggs', UserWarning, __file__, lineno, + module_globals=globals()) + self.assertEqual(stream.getvalue(), py_warnings.formatwarning( + 'eggs', UserWarning, __file__, lineno, + linecache.getline(__file__, lineno))) + def test_showwarning_not_callable(self): orig = self.module.showwarning try: diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-26-17-18-18.gh-issue-143201.UbXuX4.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-26-17-18-18.gh-issue-143201.UbXuX4.rst new file mode 100644 index 000000000000000..b2d25a6dc821a98 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-26-17-18-18.gh-issue-143201.UbXuX4.rst @@ -0,0 +1,2 @@ +Fix the C implementation of :mod:`warnings` to strip the indentation of the +source line like the Python implementation. diff --git a/Python/_warnings.c b/Python/_warnings.c index 86eae5deb859691..58196c5ec646903 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -666,6 +666,7 @@ show_warning(PyThreadState *tstate, PyObject *filename, int lineno, { PyObject *f_stderr = NULL; PyObject *name; + PyObject *truncated = NULL; char lineno_str[128]; PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno); @@ -701,7 +702,6 @@ show_warning(PyThreadState *tstate, PyObject *filename, int lineno, const void *data; Py_ssize_t i, len; Py_UCS4 ch; - PyObject *truncated; kind = PyUnicode_KIND(sourceline); data = PyUnicode_DATA(sourceline); @@ -716,9 +716,15 @@ show_warning(PyThreadState *tstate, PyObject *filename, int lineno, if (truncated == NULL) goto error; - PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW); - Py_DECREF(truncated); - PyFile_WriteString("\n", f_stderr); + if (PyFile_WriteString(" ", f_stderr) < 0) { + goto error; + } + if (PyFile_WriteObject(truncated, f_stderr, Py_PRINT_RAW) < 0) { + goto error; + } + if (PyFile_WriteString("\n", f_stderr) < 0) { + goto error; + } } else { _Py_DisplaySourceLine(f_stderr, filename, lineno, 2, NULL, NULL); @@ -727,6 +733,7 @@ show_warning(PyThreadState *tstate, PyObject *filename, int lineno, error: Py_XDECREF(f_stderr); Py_XDECREF(name); + Py_XDECREF(truncated); PyErr_Clear(); }