bpo-41031: Match C and Python code formatting of unprintable exceptio… by iritkatriel · Pull Request #28139 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions Lib/test/test_sys.py
32 changes: 29 additions & 3 deletions Lib/test/test_traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def __str__(self):
1/0
err = traceback.format_exception_only(X, X())
self.assertEqual(len(err), 1)
str_value = '<unprintable %s object>' % X.__name__
str_value = '<exception str() failed>'
if X.__module__ in ('__main__', 'builtins'):
str_name = X.__qualname__
else:
Expand Down Expand Up @@ -1171,19 +1171,45 @@ def test_syntax_error_various_offsets(self):
exp = "\n".join(expected)
self.assertEqual(exp, err)

def test_format_exception_only_qualname(self):
def test_exception_qualname(self):
class A:
class B:
class X(Exception):
def __str__(self):
return "I am X"
pass

err = self.get_report(A.B.X())
str_value = 'I am X'
str_name = '.'.join([A.B.X.__module__, A.B.X.__qualname__])
exp = "%s: %s\n" % (str_name, str_value)
self.assertEqual(exp, err)

def test_exception_modulename(self):
class X(Exception):
def __str__(self):
return "I am X"

for modulename in '__main__', 'builtins', 'some_module':
X.__module__ = modulename
with self.subTest(modulename=modulename):
err = self.get_report(X())
str_value = 'I am X'
if modulename in ['builtins', '__main__']:
str_name = X.__qualname__
else:
str_name = '.'.join([X.__module__, X.__qualname__])
exp = "%s: %s\n" % (str_name, str_value)
self.assertEqual(exp, err)

def test_exception_bad__str__(self):
class X(Exception):
def __str__(self):
1/0
err = self.get_report(X())
str_value = '<exception str() failed>'
str_name = '.'.join([X.__module__, X.__qualname__])
self.assertEqual(err, f"{str_name}: {str_value}\n")


class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
#
Expand Down
2 changes: 1 addition & 1 deletion Lib/traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def _some_str(value):
try:
return str(value)
except:
return '<unprintable %s object>' % type(value).__name__
return '<exception str() failed>'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The former message contains more information. Would not be better to change other places?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The information is duplicated because the exception is printed separately.


# --

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Match C and Python code formatting of unprintable exceptions and exceptions in the :mod:`__main__` module.
4 changes: 3 additions & 1 deletion Python/errors.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extern char *strerror(int);
extern "C" {
#endif

_Py_IDENTIFIER(__main__);
_Py_IDENTIFIER(__module__);
_Py_IDENTIFIER(builtins);
_Py_IDENTIFIER(stderr);
Expand Down Expand Up @@ -1297,7 +1298,8 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,
}
}
else {
if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins)) {
if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins) &&
!_PyUnicode_EqualToASCIIId(modulename, &PyId___main__)) {
if (PyFile_WriteObject(modulename, file, Py_PRINT_RAW) < 0) {
Py_DECREF(modulename);
return -1;
Expand Down
4 changes: 3 additions & 1 deletion Python/pythonrun.c