From 1b644d689402f6575b237be5323c3c73a82f183e Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Fri, 8 Aug 2025 10:51:53 +0800 Subject: [PATCH 01/11] main --- .../next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst 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..f9526b760573ed --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst @@ -0,0 +1,2 @@ +Fix the missing error message in "NameError" and "AttributeError" in IDLE +when "\n" in message From 97f813e47c941324c1fb963fdc10aa37d3aba6d6 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Fri, 8 Aug 2025 11:18:06 +0800 Subject: [PATCH 02/11] Update run.py --- Lib/idlelib/run.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index a30db99a619a93..65076aac4305ad 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -235,7 +235,15 @@ def get_message_lines(typ, exc, tb): err = io.StringIO() with contextlib.redirect_stderr(err): sys.__excepthook__(typ, exc, tb) - return [err.getvalue().split("\n")[-2] + "\n"] + err_list = err.getvalue().split("\n")[1:] + + for i in range(len(err_list)): + if err_list[i].startswith(" "): + continue + else: + err_list = err_list[i:-1] + break + return ["\n".join(err_list) + "\n"] else: return traceback.format_exception_only(typ, exc) From 4fa7d56e78b720631299b35363f43123ee185d1b Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Fri, 8 Aug 2025 11:19:41 +0800 Subject: [PATCH 03/11] Update test_run.py --- Lib/idlelib/idle_test/test_run.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index 83ecbffa2a197e..c846db0dedc2b5 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -45,6 +45,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 @@ -52,7 +53,10 @@ def test_get_message(self): for code, exc, msg in self.data: with self.subTest(code=code): try: - eval(compile(code, '', 'eval')) + if "raise" not in code: + eval(compile(code, '', 'eval')) + else: + exec(compile(code, '', 'exec')) # code r"raise NameError("123\n456")" cannot run in "eval" mode: SyntaxError except exc: typ, val, tb = sys.exc_info() actual = run.get_message_lines(typ, val, tb)[0] From a6316b007c33246385ef7f9d845d2d5b53217686 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Sun, 10 Aug 2025 11:22:01 +0800 Subject: [PATCH 04/11] Update test_run.py --- Lib/idlelib/idle_test/test_run.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index c846db0dedc2b5..f95b8f01749d83 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -68,15 +68,26 @@ 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')) + if "raise" not in code1: + eval(compile(code1, '', 'eval')) + else: + exec(compile(code1, '', 'exec')) except exc1: try: - eval(compile(code2, '', 'eval')) + if "raise" not in code2: + eval(compile(code2, '', 'eval')) + else: + exec(compile(code2, '', 'exec')) except exc2: with captured_stderr() as output: run.print_exception() From 22d4596e0f6efa736e89ba3e31ed44cd48e699a4 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Wed, 3 Sep 2025 18:11:45 -0400 Subject: [PATCH 05/11] Lib/idlelib/run.py: remove trailing whitespace --- Lib/idlelib/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 65076aac4305ad..ca60a826b45431 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -236,7 +236,7 @@ def get_message_lines(typ, exc, tb): with contextlib.redirect_stderr(err): sys.__excepthook__(typ, exc, tb) err_list = err.getvalue().split("\n")[1:] - + for i in range(len(err_list)): if err_list[i].startswith(" "): continue From 97e414f0a2bd85aa07dbb9f9fdec667f2de586e6 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Sun, 21 Jun 2026 11:32:48 +0800 Subject: [PATCH 06/11] Update get_message_lines to use TracebackException Refactor exception message handling to use TracebackException. --- Lib/idlelib/run.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index ca60a826b45431..ff96216e0c6737 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -232,18 +232,8 @@ 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) - err_list = err.getvalue().split("\n")[1:] - - for i in range(len(err_list)): - if err_list[i].startswith(" "): - continue - else: - err_list = err_list[i:-1] - break - return ["\n".join(err_list) + "\n"] + traceback_exception = traceback.TracebackException(typ, exc, tb) + return list(traceback_exception.format_exception_only()) else: return traceback.format_exception_only(typ, exc) From 1c5c8a07c01e1e84497465f33c9b45b1d7182687 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Sun, 21 Jun 2026 12:11:48 +0800 Subject: [PATCH 07/11] Remove unused import of contextlib for lint --- Lib/idlelib/run.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index a7a9f08946e8e9..adfe1724c06a75 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 From a9b95892db180f6b181c57c5d4b3e852815a5ba3 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Wed, 1 Jul 2026 16:26:22 +0800 Subject: [PATCH 08/11] Simplify code execution in test_get_message by only using `exec` Refactor test_get_message to simplify code execution. --- Lib/idlelib/idle_test/test_run.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index 42fb8ece346903..a5837b23aa030f 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -53,10 +53,7 @@ def test_get_message(self): for code, exc, msg in self.data: with self.subTest(code=code): try: - if "raise" not in code: - eval(compile(code, '', 'eval')) - else: - exec(compile(code, '', 'exec')) # code r"raise NameError("123\n456")" cannot run in "eval" mode: SyntaxError + exec(compile(code, '', 'exec')) except exc: typ, val, tb = sys.exc_info() actual = run.get_message_lines(typ, val, tb)[0] @@ -78,16 +75,10 @@ def test_get_multiple_message(self, mock): for (code1, exc1, msg1), (code2, exc2, msg2) in data2: with self.subTest(codes=(code1,code2)): try: - if "raise" not in code1: - eval(compile(code1, '', 'eval')) - else: - exec(compile(code1, '', 'exec')) + exec(compile(code1, '', 'exec')) except exc1: try: - if "raise" not in code2: - eval(compile(code2, '', 'eval')) - else: - exec(compile(code2, '', 'exec')) + exec(compile(code2, '', 'exec')) except exc2: with captured_stderr() as output: run.print_exception() From 9c4aaad0d681ce46a63b8169dbd1ed73708113b2 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Wed, 1 Jul 2026 17:12:10 +0800 Subject: [PATCH 09/11] Simplify exception message retrieval logic --- Lib/idlelib/run.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index adfe1724c06a75..7bec7cda47cc0e 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -229,12 +229,7 @@ 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). - traceback_exception = traceback.TracebackException(typ, exc, tb) - return list(traceback_exception.format_exception_only()) - else: - return traceback.format_exception_only(typ, exc) + return list(traceback.TracebackException(typ, exc, tb).format_exception_only()) def print_exception(): From 3b07d5da177f241cca30822b8b49ad7f2422588b Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Wed, 1 Jul 2026 23:48:44 +0800 Subject: [PATCH 10/11] Update Misc/NEWS.d/next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst Co-authored-by: Serhiy Storchaka --- .../next/IDLE/2025-08-08-10-50-59.gh-issue-135511.9Rw5Zg.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 index f9526b760573ed..10e59572b53746 100644 --- 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 @@ -1,2 +1 @@ -Fix the missing error message in "NameError" and "AttributeError" in IDLE -when "\n" in message +Fix display of :exc:`NameError` and :exc:`AttributeError` with multi-line message. From 2a5097861e0fdc1ac86bfcb35b2bb443b224d9be Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Wed, 1 Jul 2026 23:48:59 +0800 Subject: [PATCH 11/11] Update Lib/idlelib/run.py Co-authored-by: Serhiy Storchaka --- Lib/idlelib/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index f1cae8f5cb03d4..77a44efbec9459 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -229,7 +229,7 @@ def show_socket_error(err, address): def get_message_lines(typ, exc, tb): - "Return line composing the exception message." + "Return lines of the exception message, with any suggestion." return list(traceback.TracebackException(typ, exc, tb).format_exception_only())