gh-109179: Fix traceback display for SyntaxErrors with notes (#109197)

This commit is contained in:
Irit Katriel 2023-09-11 19:18:34 +01:00 committed by GitHub
parent de5f8f7d13
commit ecd21a629a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 30 deletions

View File

@ -1599,27 +1599,28 @@ class BaseExceptionReportingTests:
err_msg = "b'please do not show me as numbers'" err_msg = "b'please do not show me as numbers'"
self.assertEqual(self.get_report(e), vanilla + err_msg + '\n') self.assertEqual(self.get_report(e), vanilla + err_msg + '\n')
def test_exception_with_note_with_multiple_notes(self): def test_exception_with_multiple_notes(self):
e = ValueError(42) for e in [ValueError(42), SyntaxError('bad syntax')]:
vanilla = self.get_report(e) with self.subTest(e=e):
vanilla = self.get_report(e)
e.add_note('Note 1') e.add_note('Note 1')
e.add_note('Note 2') e.add_note('Note 2')
e.add_note('Note 3') e.add_note('Note 3')
self.assertEqual( self.assertEqual(
self.get_report(e), self.get_report(e),
vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n') vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n')
del e.__notes__ del e.__notes__
e.add_note('Note 4') e.add_note('Note 4')
del e.__notes__ del e.__notes__
e.add_note('Note 5') e.add_note('Note 5')
e.add_note('Note 6') e.add_note('Note 6')
self.assertEqual( self.assertEqual(
self.get_report(e), self.get_report(e),
vanilla + 'Note 5\n' + 'Note 6\n') vanilla + 'Note 5\n' + 'Note 6\n')
def test_exception_qualname(self): def test_exception_qualname(self):
class A: class A:

View File

@ -0,0 +1 @@
Fix bug where the C traceback display drops notes from :exc:`SyntaxError`.

View File

@ -1125,21 +1125,16 @@ error:
} }
static int 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; PyObject *f = ctx->file;
if (!PyExceptionInstance_Check(value)) { if (notes == NULL) {
return 0; 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)) { if (!PySequence_Check(notes) || PyUnicode_Check(notes) || PyBytes_Check(notes)) {
res = 0; int res = 0;
if (write_indented_margin(ctx, f) < 0) { if (write_indented_margin(ctx, f) < 0) {
res = -1; res = -1;
} }
@ -1152,7 +1147,6 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
res = PyFile_WriteObject(s, f, Py_PRINT_RAW); res = PyFile_WriteObject(s, f, Py_PRINT_RAW);
Py_DECREF(s); Py_DECREF(s);
} }
Py_DECREF(notes);
if (PyFile_WriteString("\n", f) < 0) { if (PyFile_WriteString("\n", f) < 0) {
res = -1; res = -1;
} }
@ -1197,17 +1191,16 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
} }
} }
Py_DECREF(notes);
return 0; return 0;
error: error:
Py_XDECREF(lines); Py_XDECREF(lines);
Py_DECREF(notes);
return -1; return -1;
} }
static int static int
print_exception(struct exception_print_context *ctx, PyObject *value) print_exception(struct exception_print_context *ctx, PyObject *value)
{ {
PyObject *notes = NULL;
PyObject *f = ctx->file; PyObject *f = ctx->file;
if (!PyExceptionInstance_Check(value)) { if (!PyExceptionInstance_Check(value)) {
@ -1221,8 +1214,11 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
goto error; 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); 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) { if (print_exception_file_and_line(ctx, &value) < 0) {
goto error; goto error;
@ -1236,14 +1232,16 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
if (PyFile_WriteString("\n", f) < 0) { if (PyFile_WriteString("\n", f) < 0) {
goto error; goto error;
} }
if (print_exception_notes(ctx, value) < 0) { if (print_exception_notes(ctx, notes) < 0) {
goto error; goto error;
} }
Py_XDECREF(notes);
Py_DECREF(value); Py_DECREF(value);
assert(!PyErr_Occurred()); assert(!PyErr_Occurred());
return 0; return 0;
error: error:
Py_XDECREF(notes);
Py_DECREF(value); Py_DECREF(value);
return -1; return -1;
} }