mirror of https://github.com/python/cpython
gh-109179: Fix traceback display for SyntaxErrors with notes (#109197)
This commit is contained in:
parent
de5f8f7d13
commit
ecd21a629a
|
@ -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:
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix bug where the C traceback display drops notes from :exc:`SyntaxError`.
|
|
@ -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__), ¬es);
|
|
||||||
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__), ¬es) < 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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue