https://github.com/python/cpython/commit/1f85ffc701b4873c67a8519ed09cdc6f9d32db15 commit: 1f85ffc701b4873c67a8519ed09cdc6f9d32db15 branch: 3.14 author: Serhiy Storchaka <[email protected]> committer: terryjreedy <[email protected]> date: 2026-09-27T05:52:00Z summary:
[3.14] gh-135511: Fixed truncated exception message for Name- and AttributeError (GH-135526) (#158275) Only the last line of multiline error messages was displayed. --------- (cherry picked from commit 421c411672710e29df4c027b6824df17586c9d51) Co-authored-by: Locked-chess-official <[email protected]> Co-authored-by: Terry Jan Reedy <[email protected]> files: A Misc/NEWS.d/next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst M Lib/idlelib/idle_test/test_run.py M Lib/idlelib/run.py diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index 9947ad498965c2..bc762648c80785 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -49,6 +49,7 @@ def __eq__(self, other): ('int.reel', AttributeError, "type object 'int' has no attribute 'reel'. " "Did you mean: 'real'?\n"), + (r'raise NameError("123\n456")', NameError, "123\n456\n"), ) @force_not_colorized @@ -56,7 +57,7 @@ def test_get_message(self): for code, exc, msg in self.data: with self.subTest(code=code): try: - eval(compile(code, '', 'eval')) + exec(compile(code, '', 'exec')) except exc: typ, val, tb = sys.exc_info() actual = run.get_message_lines(typ, val, tb)[0] @@ -68,15 +69,20 @@ def test_get_message(self): new_callable=lambda: (lambda t, e: None)) def test_get_multiple_message(self, mock): d = self.data - data2 = ((d[0], d[1]), (d[1], d[2]), (d[2], d[0])) + data2 = ((d[0], d[1]), + (d[1], d[2]), + (d[2], d[3]), + (d[3], d[0]), + (d[1], d[3]), + (d[0], d[2])) subtests = 0 for (code1, exc1, msg1), (code2, exc2, msg2) in data2: with self.subTest(codes=(code1,code2)): try: - eval(compile(code1, '', 'eval')) + exec(compile(code1, '', 'exec')) except exc1: try: - eval(compile(code2, '', 'eval')) + exec(compile(code2, '', 'exec')) except exc2: with captured_stderr() as output: run.print_exception() diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 48e8f3c4605fc0..5e04afe2ccc5c1 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -4,7 +4,6 @@ f'''{sys.executable} -c "__import__('idlelib.run').run.main()"''' '.run' is needed because __import__ returns idlelib, not idlelib.run. """ -import contextlib import functools import io import linecache @@ -244,15 +243,8 @@ def show_socket_error(err, address): def get_message_lines(typ, exc, tb): - "Return line composing the exception message." - if typ in (AttributeError, NameError): - # 3.10+ hints are not directly accessible from python (#44026). - err = io.StringIO() - with contextlib.redirect_stderr(err): - sys.__excepthook__(typ, exc, tb) - return [err.getvalue().split("\n")[-2] + "\n"] - else: - return traceback.format_exception_only(typ, exc) + "Return lines of the exception message, with any suggestion." + return list(traceback.TracebackException(typ, exc, tb).format_exception_only()) def print_exception(): diff --git a/Misc/NEWS.d/next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst b/Misc/NEWS.d/next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst new file mode 100644 index 00000000000000..10e59572b53746 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst @@ -0,0 +1 @@ +Fix display of :exc:`NameError` and :exc:`AttributeError` with multi-line message. _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
