https://github.com/python/cpython/commit/421c411672710e29df4c027b6824df17586c9d51
commit: 421c411672710e29df4c027b6824df17586c9d51
branch: main
author: Locked-chess-official <[email protected]>
committer: terryjreedy <[email protected]>
date: 2026-09-27T00:03:50-04:00
summary:

gh-135511 Fixed truncated exception message for Name- and AttributeError  
(#135526)

Only the last line of multiline error messages was displayed.
---------

Co-authored-by: Terry Jan Reedy <[email protected]>
Co-authored-by: Serhiy Storchaka <[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 19adb325ec06f13..d7e69f70fd87d85 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' instead of '.reel'?\n"),  # More in 
3.15.
+            (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 48e8f3c4605fc07..5e04afe2ccc5c15 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 000000000000000..10e59572b53746e
--- /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]

Reply via email to