Skip to content

Commit a843112

Browse files
authored
[3.12] gh-109179: Fix traceback display for SyntaxErrors with notes (#109197) (#109280)
(cherry picked from commit ecd21a6)
1 parent 1d8c18c commit a843112

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
@@ -1599,27 +1599,28 @@ def __repr__(self):
15991599
err_msg = "b'please do not show me as numbers'"
16001600
self.assertEqual(self.get_report(e), vanilla + err_msg + '\n')
16011601

1602-
def test_exception_with_note_with_multiple_notes(self):
1603-
e = ValueError(42)
1604-
vanilla = self.get_report(e)
1605-
1606-
e.add_note('Note 1')
1607-
e.add_note('Note 2')
1608-
e.add_note('Note 3')
1609-
1610-
self.assertEqual(
1611-
self.get_report(e),
1612-
vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n')
1613-
1614-
del e.__notes__
1615-
e.add_note('Note 4')
1616-
del e.__notes__
1617-
e.add_note('Note 5')
1618-
e.add_note('Note 6')
1619-
1620-
self.assertEqual(
1621-
self.get_report(e),
1622-
vanilla + 'Note 5\n' + 'Note 6\n')
1602+
def test_exception_with_multiple_notes(self):
1603+
for e in [ValueError(42), SyntaxError('bad syntax')]:
1604+
with self.subTest(e=e):
1605+
vanilla = self.get_report(e)
1606+
1607+
e.add_note('Note 1')
1608+
e.add_note('Note 2')
1609+
e.add_note('Note 3')
1610+
1611+
self.assertEqual(
1612+
self.get_report(e),
1613+
vanilla + 'Note 1\n' + 'Note 2\n' + 'Note 3\n')
1614+
1615+
del e.__notes__
1616+
e.add_note('Note 4')
1617+
del e.__notes__
1618+
e.add_note('Note 5')
1619+
e.add_note('Note 6')
1620+
1621+
self.assertEqual(
1622+
self.get_report(e),
1623+
vanilla + 'Note 5\n' + 'Note 6\n')
16231624

16241625
def test_exception_qualname(self):
16251626
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
@@ -1092,21 +1092,16 @@ print_exception_suggestions(struct exception_print_context *ctx,
10921092
}
10931093

10941094
static int
1095-
print_exception_notes(struct exception_print_context *ctx, PyObject *value)
1095+
print_exception_notes(struct exception_print_context *ctx, PyObject *notes)
10961096
{
10971097
PyObject *f = ctx->file;
10981098

1099-
if (!PyExceptionInstance_Check(value)) {
1099+
if (notes == NULL) {
11001100
return 0;
11011101
}
11021102

1103-
PyObject *notes;
1104-
int res = _PyObject_LookupAttr(value, &_Py_ID(__notes__), &notes);
1105-
if (res <= 0) {
1106-
return res;
1107-
}
11081103
if (!PySequence_Check(notes) || PyUnicode_Check(notes) || PyBytes_Check(notes)) {
1109-
res = 0;
1104+
int res = 0;
11101105
if (write_indented_margin(ctx, f) < 0) {
11111106
res = -1;
11121107
}
@@ -1119,7 +1114,6 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
11191114
res = PyFile_WriteObject(s, f, Py_PRINT_RAW);
11201115
Py_DECREF(s);
11211116
}
1122-
Py_DECREF(notes);
11231117
if (PyFile_WriteString("\n", f) < 0) {
11241118
res = -1;
11251119
}
@@ -1164,17 +1158,16 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
11641158
}
11651159
}
11661160

1167-
Py_DECREF(notes);
11681161
return 0;
11691162
error:
11701163
Py_XDECREF(lines);
1171-
Py_DECREF(notes);
11721164
return -1;
11731165
}
11741166

11751167
static int
11761168
print_exception(struct exception_print_context *ctx, PyObject *value)
11771169
{
1170+
PyObject *notes = NULL;
11781171
PyObject *f = ctx->file;
11791172

11801173
if (!PyExceptionInstance_Check(value)) {
@@ -1188,8 +1181,11 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
11881181
goto error;
11891182
}
11901183

1191-
/* grab the type now because value can change below */
1184+
/* grab the type and notes now because value can change below */
11921185
PyObject *type = (PyObject *) Py_TYPE(value);
1186+
if (_PyObject_LookupAttr(value, &_Py_ID(__notes__), &notes) < 0) {
1187+
goto error;
1188+
}
11931189

11941190
if (print_exception_file_and_line(ctx, &value) < 0) {
11951191
goto error;
@@ -1203,14 +1199,16 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
12031199
if (PyFile_WriteString("\n", f) < 0) {
12041200
goto error;
12051201
}
1206-
if (print_exception_notes(ctx, value) < 0) {
1202+
if (print_exception_notes(ctx, notes) < 0) {
12071203
goto error;
12081204
}
12091205

1206+
Py_XDECREF(notes);
12101207
Py_DECREF(value);
12111208
assert(!PyErr_Occurred());
12121209
return 0;
12131210
error:
1211+
Py_XDECREF(notes);
12141212
Py_DECREF(value);
12151213
return -1;
12161214
}

0 commit comments

Comments
 (0)