Skip to content

Commit 1e86961

Browse files
authored
[3.11] gh-109179: Fix traceback display for SyntaxErrors with notes (#109197) (#109283)
gh-109179: Fix traceback display for SyntaxErrors with notes (#109197) (cherry picked from commit ecd21a6)
1 parent 0e2d674 commit 1e86961

File tree

3 files changed

+34
-34
lines changed

3 files changed

+34
-34
lines changed

Lib/test/test_traceback.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,27 +1546,28 @@ def __repr__(self):
15461546
err_msg = '<note str() failed>'
15471547
self.assertEqual(self.get_report(e), vanilla + err_msg + '\nFinal Note\n')
15481548

1549-
def test_exception_with_note_with_multiple_notes(self):
1550-
e = ValueError(42)
1551-
vanilla = self.get_report(e)
1552-
1553-
e.add_note('Note 1')
1554-
e.add_note('Note 2')
1555-
e.add_note('Note 3')
1556-
1557-
self.assertEqual(
1558-
self.get_report(e),
1559-
vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n')
1560-
1561-
del e.__notes__
1562-
e.add_note('Note 4')
1563-
del e.__notes__
1564-
e.add_note('Note 5')
1565-
e.add_note('Note 6')
1566-
1567-
self.assertEqual(
1568-
self.get_report(e),
1569-
vanilla + 'Note 5\n' + 'Note 6\n')
1549+
def test_exception_with_multiple_notes(self):
1550+
for e in [ValueError(42), SyntaxError('bad syntax')]:
1551+
with self.subTest(e=e):
1552+
vanilla = self.get_report(e)
1553+
1554+
e.add_note('Note 1')
1555+
e.add_note('Note 2')
1556+
e.add_note('Note 3')
1557+
1558+
self.assertEqual(
1559+
self.get_report(e),
1560+
vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n')
1561+
1562+
del e.__notes__
1563+
e.add_note('Note 4')
1564+
del e.__notes__
1565+
e.add_note('Note 5')
1566+
e.add_note('Note 6')
1567+
1568+
self.assertEqual(
1569+
self.get_report(e),
1570+
vanilla + 'Note 5\n' + 'Note 6\n')
15701571

15711572
def test_exception_qualname(self):
15721573
class A:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix bug where the C traceback display drops notes from :exc:`SyntaxError`.

Python/pythonrun.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,21 +1130,16 @@ print_exception_suggestions(struct exception_print_context *ctx,
11301130
}
11311131

11321132
static int
1133-
print_exception_notes(struct exception_print_context *ctx, PyObject *value)
1133+
print_exception_notes(struct exception_print_context *ctx, PyObject *notes)
11341134
{
11351135
PyObject *f = ctx->file;
11361136

1137-
if (!PyExceptionInstance_Check(value)) {
1137+
if (notes == NULL) {
11381138
return 0;
11391139
}
11401140

1141-
PyObject *notes;
1142-
int res = _PyObject_LookupAttr(value, &_Py_ID(__notes__), &notes);
1143-
if (res <= 0) {
1144-
return res;
1145-
}
11461141
if (!PySequence_Check(notes)) {
1147-
res = 0;
1142+
int res = 0;
11481143
if (write_indented_margin(ctx, f) < 0) {
11491144
res = -1;
11501145
}
@@ -1157,7 +1152,6 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
11571152
res = PyFile_WriteObject(s, f, Py_PRINT_RAW);
11581153
Py_DECREF(s);
11591154
}
1160-
Py_DECREF(notes);
11611155
return res;
11621156
}
11631157
Py_ssize_t num_notes = PySequence_Length(notes);
@@ -1199,17 +1193,16 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
11991193
}
12001194
}
12011195

1202-
Py_DECREF(notes);
12031196
return 0;
12041197
error:
12051198
Py_XDECREF(lines);
1206-
Py_DECREF(notes);
12071199
return -1;
12081200
}
12091201

12101202
static int
12111203
print_exception(struct exception_print_context *ctx, PyObject *value)
12121204
{
1205+
PyObject *notes = NULL;
12131206
PyObject *f = ctx->file;
12141207

12151208
if (!PyExceptionInstance_Check(value)) {
@@ -1223,8 +1216,11 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
12231216
goto error;
12241217
}
12251218

1226-
/* grab the type now because value can change below */
1219+
/* grab the type and notes now because value can change below */
12271220
PyObject *type = (PyObject *) Py_TYPE(value);
1221+
if (_PyObject_LookupAttr(value, &_Py_ID(__notes__), &notes) < 0) {
1222+
goto error;
1223+
}
12281224

12291225
if (print_exception_file_and_line(ctx, &value) < 0) {
12301226
goto error;
@@ -1238,14 +1234,16 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
12381234
if (PyFile_WriteString("\n", f) < 0) {
12391235
goto error;
12401236
}
1241-
if (print_exception_notes(ctx, value) < 0) {
1237+
if (print_exception_notes(ctx, notes) < 0) {
12421238
goto error;
12431239
}
12441240

1241+
Py_XDECREF(notes);
12451242
Py_DECREF(value);
12461243
assert(!PyErr_Occurred());
12471244
return 0;
12481245
error:
1246+
Py_XDECREF(notes);
12491247
Py_DECREF(value);
12501248
return -1;
12511249
}

0 commit comments

Comments
 (0)