mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-103895: Improve how invalid Exception.__notes__
are displayed (#103897)
This commit is contained in:
parent
93107aa2a4
commit
487f55d580
4 changed files with 23 additions and 5 deletions
|
@ -1539,11 +1539,11 @@ class BaseExceptionReportingTests:
|
||||||
|
|
||||||
e.__notes__ = BadThing()
|
e.__notes__ = BadThing()
|
||||||
notes_repr = 'bad repr'
|
notes_repr = 'bad repr'
|
||||||
self.assertEqual(self.get_report(e), vanilla + notes_repr)
|
self.assertEqual(self.get_report(e), vanilla + notes_repr + '\n')
|
||||||
|
|
||||||
e.__notes__ = Unprintable()
|
e.__notes__ = Unprintable()
|
||||||
err_msg = '<__notes__ repr() failed>'
|
err_msg = '<__notes__ repr() failed>'
|
||||||
self.assertEqual(self.get_report(e), vanilla + err_msg)
|
self.assertEqual(self.get_report(e), vanilla + err_msg + '\n')
|
||||||
|
|
||||||
# non-string item in the __notes__ sequence
|
# non-string item in the __notes__ sequence
|
||||||
e.__notes__ = [BadThing(), 'Final Note']
|
e.__notes__ = [BadThing(), 'Final Note']
|
||||||
|
@ -1555,6 +1555,14 @@ class BaseExceptionReportingTests:
|
||||||
err_msg = '<note str() failed>'
|
err_msg = '<note str() failed>'
|
||||||
self.assertEqual(self.get_report(e), vanilla + err_msg + '\nFinal Note\n')
|
self.assertEqual(self.get_report(e), vanilla + err_msg + '\nFinal Note\n')
|
||||||
|
|
||||||
|
e.__notes__ = "please do not explode me"
|
||||||
|
err_msg = "'please do not explode me'"
|
||||||
|
self.assertEqual(self.get_report(e), vanilla + err_msg + '\n')
|
||||||
|
|
||||||
|
e.__notes__ = 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')
|
||||||
|
|
||||||
def test_exception_with_note_with_multiple_notes(self):
|
def test_exception_with_note_with_multiple_notes(self):
|
||||||
e = ValueError(42)
|
e = ValueError(42)
|
||||||
vanilla = self.get_report(e)
|
vanilla = self.get_report(e)
|
||||||
|
|
|
@ -852,12 +852,16 @@ class TracebackException:
|
||||||
yield _format_final_exc_line(stype, self._str)
|
yield _format_final_exc_line(stype, self._str)
|
||||||
else:
|
else:
|
||||||
yield from self._format_syntax_error(stype)
|
yield from self._format_syntax_error(stype)
|
||||||
if isinstance(self.__notes__, collections.abc.Sequence):
|
|
||||||
|
if (
|
||||||
|
isinstance(self.__notes__, collections.abc.Sequence)
|
||||||
|
and not isinstance(self.__notes__, (str, bytes))
|
||||||
|
):
|
||||||
for note in self.__notes__:
|
for note in self.__notes__:
|
||||||
note = _safe_string(note, 'note')
|
note = _safe_string(note, 'note')
|
||||||
yield from [l + '\n' for l in note.split('\n')]
|
yield from [l + '\n' for l in note.split('\n')]
|
||||||
elif self.__notes__ is not None:
|
elif self.__notes__ is not None:
|
||||||
yield _safe_string(self.__notes__, '__notes__', func=repr)
|
yield "{}\n".format(_safe_string(self.__notes__, '__notes__', func=repr))
|
||||||
|
|
||||||
def _format_syntax_error(self, stype):
|
def _format_syntax_error(self, stype):
|
||||||
"""Format SyntaxError exceptions (internal helper)."""
|
"""Format SyntaxError exceptions (internal helper)."""
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Improve handling of edge cases in showing ``Exception.__notes__``. Ensures
|
||||||
|
that the messages always end with a newline and that string/bytes are not
|
||||||
|
exploded over multiple lines. Patch by Carey Metcalfe.
|
|
@ -1107,7 +1107,7 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
|
||||||
if (notes == NULL) {
|
if (notes == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!PySequence_Check(notes)) {
|
if (!PySequence_Check(notes) || PyUnicode_Check(notes) || PyBytes_Check(notes)) {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
if (write_indented_margin(ctx, f) < 0) {
|
if (write_indented_margin(ctx, f) < 0) {
|
||||||
res = -1;
|
res = -1;
|
||||||
|
@ -1122,6 +1122,9 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value)
|
||||||
Py_DECREF(s);
|
Py_DECREF(s);
|
||||||
}
|
}
|
||||||
Py_DECREF(notes);
|
Py_DECREF(notes);
|
||||||
|
if (PyFile_WriteString("\n", f) < 0) {
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
Py_ssize_t num_notes = PySequence_Length(notes);
|
Py_ssize_t num_notes = PySequence_Length(notes);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue