]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-109179: Fix traceback display for SyntaxErrors with notes (#109197)
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Mon, 11 Sep 2023 18:18:34 +0000 (19:18 +0100)
committerGitHub <noreply@github.com>
Mon, 11 Sep 2023 18:18:34 +0000 (19:18 +0100)
Lib/test/test_traceback.py
Misc/NEWS.d/next/Core and Builtins/2023-09-09-21-17-18.gh-issue-109179.ZR8qs2.rst [new file with mode: 0644]
Python/pythonrun.c

index be81082bb194725b1326633d52c09bde77872ac4..aa8405bd25d120cc245488fc52ba935a771d6a86 100644 (file)
@@ -1599,27 +1599,28 @@ class BaseExceptionReportingTests:
         err_msg = "b'please do not show me as numbers'"
         self.assertEqual(self.get_report(e), vanilla + err_msg + '\n')
 
-    def test_exception_with_note_with_multiple_notes(self):
-        e = ValueError(42)
-        vanilla = self.get_report(e)
-
-        e.add_note('Note 1')
-        e.add_note('Note 2')
-        e.add_note('Note 3')
-
-        self.assertEqual(
-            self.get_report(e),
-            vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n')
-
-        del e.__notes__
-        e.add_note('Note 4')
-        del e.__notes__
-        e.add_note('Note 5')
-        e.add_note('Note 6')
-
-        self.assertEqual(
-            self.get_report(e),
-            vanilla + 'Note 5\n' + 'Note 6\n')
+    def test_exception_with_multiple_notes(self):
+        for e in [ValueError(42), SyntaxError('bad syntax')]:
+            with self.subTest(e=e):
+                vanilla = self.get_report(e)
+
+                e.add_note('Note 1')
+                e.add_note('Note 2')
+                e.add_note('Note 3')
+
+                self.assertEqual(
+                    self.get_report(e),
+                    vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n')
+
+                del e.__notes__
+                e.add_note('Note 4')
+                del e.__notes__
+                e.add_note('Note 5')
+                e.add_note('Note 6')
+
+                self.assertEqual(
+                    self.get_report(e),
+                    vanilla + 'Note 5\n' + 'Note 6\n')
 
     def test_exception_qualname(self):
         class A:
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-09-09-21-17-18.gh-issue-109179.ZR8qs2.rst b/Misc/NEWS.d/next/Core and Builtins/2023-09-09-21-17-18.gh-issue-109179.ZR8qs2.rst
new file mode 100644 (file)
index 0000000..dd95a8e
--- /dev/null
@@ -0,0 +1 @@
+Fix bug where the C traceback display drops notes from :exc:`SyntaxError`.
index ddd8951cedb1f15dca8749b906f099c3dc8383e3..e3d03a8c95d767ada9dd706da21f99f440d8ead4 100644 (file)
@@ -1125,21 +1125,16 @@ error:
 }
 
 static int
-print_exception_notes(struct exception_print_context *ctx, PyObject *value)
+print_exception_notes(struct exception_print_context *ctx, PyObject *notes)
 {
     PyObject *f = ctx->file;
 
-    if (!PyExceptionInstance_Check(value)) {
+    if (notes == NULL) {
         return 0;
     }
 
-    PyObject *notes;
-    int res = PyObject_GetOptionalAttr(value, &_Py_ID(__notes__), &notes);
-    if (res <= 0) {
-        return res;
-    }
     if (!PySequence_Check(notes) || PyUnicode_Check(notes) || PyBytes_Check(notes)) {
-        res = 0;
+        int res = 0;
         if (write_indented_margin(ctx, f) < 0) {
             res = -1;
         }
@@ -1152,7 +1147,6 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
             res = PyFile_WriteObject(s, f, Py_PRINT_RAW);
             Py_DECREF(s);
         }
-        Py_DECREF(notes);
         if (PyFile_WriteString("\n", f) < 0) {
             res = -1;
         }
@@ -1197,17 +1191,16 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
         }
     }
 
-    Py_DECREF(notes);
     return 0;
 error:
     Py_XDECREF(lines);
-    Py_DECREF(notes);
     return -1;
 }
 
 static int
 print_exception(struct exception_print_context *ctx, PyObject *value)
 {
+    PyObject *notes = NULL;
     PyObject *f = ctx->file;
 
     if (!PyExceptionInstance_Check(value)) {
@@ -1221,8 +1214,11 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
         goto error;
     }
 
-    /* grab the type now because value can change below */
+    /* grab the type and notes now because value can change below */
     PyObject *type = (PyObject *) Py_TYPE(value);
+    if (PyObject_GetOptionalAttr(value, &_Py_ID(__notes__), &notes) < 0) {
+        goto error;
+    }
 
     if (print_exception_file_and_line(ctx, &value) < 0) {
         goto error;
@@ -1236,14 +1232,16 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
     if (PyFile_WriteString("\n", f) < 0) {
         goto error;
     }
-    if (print_exception_notes(ctx, value) < 0) {
+    if (print_exception_notes(ctx, notes) < 0) {
         goto error;
     }
 
+    Py_XDECREF(notes);
     Py_DECREF(value);
     assert(!PyErr_Occurred());
     return 0;
 error:
+    Py_XDECREF(notes);
     Py_DECREF(value);
     return -1;
 }