Skip to content

Commit e8f7621

Browse files
Revert "gh-139551: add support for BaseExceptionGroup in IDLE (GH-139563)"
This reverts commit 1e79bf6.
1 parent f3c118a commit e8f7621

File tree

3 files changed

+17
-174
lines changed

3 files changed

+17
-174
lines changed

Lib/idlelib/idle_test/test_run.py

Lines changed: 0 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -82,99 +82,6 @@ def test_get_multiple_message(self, mock):
8282
subtests += 1
8383
self.assertEqual(subtests, len(data2)) # All subtests ran?
8484

85-
def _capture_exception(self):
86-
"""Call run.print_exception() and return its stderr output."""
87-
with captured_stderr() as output:
88-
with mock.patch.object(run, 'cleanup_traceback') as ct:
89-
ct.side_effect = lambda t, e: t
90-
run.print_exception()
91-
return output.getvalue()
92-
93-
@force_not_colorized
94-
def test_print_exception_group_nested(self):
95-
try:
96-
try:
97-
raise ExceptionGroup('inner', [ValueError('v1')])
98-
except ExceptionGroup as inner:
99-
raise ExceptionGroup('outer', [inner, TypeError('t1')])
100-
except ExceptionGroup:
101-
tb = self._capture_exception()
102-
103-
self.assertIn('ExceptionGroup: outer (2 sub-exceptions)', tb)
104-
self.assertIn('ExceptionGroup: inner', tb)
105-
self.assertIn('ValueError: v1', tb)
106-
self.assertIn('TypeError: t1', tb)
107-
# Verify tree structure characters.
108-
self.assertIn('+-+---------------- 1 ----------------', tb)
109-
self.assertIn('+---------------- 2 ----------------', tb)
110-
self.assertIn('+------------------------------------', tb)
111-
112-
@force_not_colorized
113-
def test_print_exception_group_chaining(self):
114-
# __cause__ on a sub-exception exercises the prefixed
115-
# chaining-message path (margin chars on separator lines).
116-
sub = TypeError('t1')
117-
sub.__cause__ = ValueError('original')
118-
try:
119-
raise ExceptionGroup('eg1', [sub])
120-
except ExceptionGroup:
121-
tb = self._capture_exception()
122-
self.assertIn('ValueError: original', tb)
123-
self.assertIn('| The above exception was the direct cause', tb)
124-
self.assertIn('ExceptionGroup: eg1', tb)
125-
126-
# __context__ (implicit chaining) on a sub-exception.
127-
sub = TypeError('t2')
128-
sub.__context__ = ValueError('first')
129-
try:
130-
raise ExceptionGroup('eg2', [sub])
131-
except ExceptionGroup:
132-
tb = self._capture_exception()
133-
self.assertIn('ValueError: first', tb)
134-
self.assertIn('| During handling of the above exception', tb)
135-
self.assertIn('ExceptionGroup: eg2', tb)
136-
137-
@force_not_colorized
138-
def test_print_exception_group_seen(self):
139-
shared = ValueError('shared')
140-
try:
141-
raise ExceptionGroup('eg', [shared, shared])
142-
except ExceptionGroup:
143-
tb = self._capture_exception()
144-
145-
self.assertIn('ValueError: shared', tb)
146-
self.assertIn('<exception ValueError has printed>', tb)
147-
148-
@force_not_colorized
149-
def test_print_exception_group_max_width(self):
150-
excs = [ValueError(f'v{i}') for i in range(20)]
151-
try:
152-
raise ExceptionGroup('eg', excs)
153-
except ExceptionGroup:
154-
tb = self._capture_exception()
155-
156-
self.assertIn('+---------------- 15 ----------------', tb)
157-
self.assertIn('+---------------- ... ----------------', tb)
158-
self.assertIn('and 5 more exceptions', tb)
159-
self.assertNotIn('+---------------- 16 ----------------', tb)
160-
161-
@force_not_colorized
162-
def test_print_exception_group_max_depth(self):
163-
def make_nested(depth):
164-
if depth == 0:
165-
return ValueError('leaf')
166-
return ExceptionGroup(f'level{depth}',
167-
[make_nested(depth - 1)])
168-
169-
try:
170-
raise make_nested(15)
171-
except ExceptionGroup:
172-
tb = self._capture_exception()
173-
174-
self.assertIn('... (max_group_depth is 10)', tb)
175-
self.assertIn('ExceptionGroup: level15', tb)
176-
self.assertNotIn('ValueError: leaf', tb)
177-
17885
# StdioFile tests.
17986

18087
class S(str):

Lib/idlelib/run.py

Lines changed: 17 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -249,94 +249,31 @@ def print_exception():
249249
sys.last_type, sys.last_value, sys.last_traceback = excinfo
250250
sys.last_exc = val
251251
seen = set()
252-
exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
253-
"debugger_r.py", "bdb.py")
254-
max_group_width = 15
255-
max_group_depth = 10
256-
group_depth = 0
257-
258-
def print_exc_group(typ, exc, tb, prefix=""):
259-
nonlocal group_depth
260-
group_depth += 1
261-
prefix2 = prefix or " "
262-
if group_depth > max_group_depth:
263-
print(f"{prefix2}| ... (max_group_depth is {max_group_depth})",
264-
file=efile)
265-
group_depth -= 1
266-
return
267-
if tb:
268-
if not prefix:
269-
print(" + Exception Group Traceback (most recent call last):", file=efile)
270-
else:
271-
print(f"{prefix}| Exception Group Traceback (most recent call last):", file=efile)
272-
tbe = traceback.extract_tb(tb)
273-
cleanup_traceback(tbe, exclude)
274-
for line in traceback.format_list(tbe):
275-
for subline in line.rstrip().splitlines():
276-
print(f"{prefix2}| {subline}", file=efile)
277-
lines = get_message_lines(typ, exc, tb)
278-
for line in lines:
279-
print(f"{prefix2}| {line}", end="", file=efile)
280-
num_excs = len(exc.exceptions)
281-
if num_excs <= max_group_width:
282-
n = num_excs
283-
else:
284-
n = max_group_width + 1
285-
for i, sub in enumerate(exc.exceptions[:n], 1):
286-
truncated = (i > max_group_width)
287-
first_line_pre = "+-" if i == 1 else " "
288-
title = str(i) if not truncated else '...'
289-
print(f"{prefix2}{first_line_pre}+---------------- {title} ----------------", file=efile)
290-
if truncated:
291-
remaining = num_excs - max_group_width
292-
plural = 's' if remaining > 1 else ''
293-
print(f"{prefix2} | and {remaining} more exception{plural}",
294-
file=efile)
295-
need_print_underline = True
296-
elif id(sub) not in seen:
297-
if not prefix:
298-
print_exc(type(sub), sub, sub.__traceback__, " ")
299-
else:
300-
print_exc(type(sub), sub, sub.__traceback__, prefix + " ")
301-
need_print_underline = not isinstance(sub, BaseExceptionGroup)
302-
else:
303-
print(f"{prefix2} | <exception {type(sub).__name__} has printed>", file=efile)
304-
need_print_underline = True
305-
if need_print_underline and i == n:
306-
print(f"{prefix2} +------------------------------------", file=efile)
307-
group_depth -= 1
308252

309-
def print_exc(typ, exc, tb, prefix=""):
253+
def print_exc(typ, exc, tb):
310254
seen.add(id(exc))
311255
context = exc.__context__
312256
cause = exc.__cause__
313-
prefix2 = f"{prefix}| " if prefix else ""
314257
if cause is not None and id(cause) not in seen:
315-
print_exc(type(cause), cause, cause.__traceback__, prefix)
316-
print(f"{prefix2}\n{prefix2}The above exception was the direct cause "
317-
f"of the following exception:\n{prefix2}", file=efile)
258+
print_exc(type(cause), cause, cause.__traceback__)
259+
print("\nThe above exception was the direct cause "
260+
"of the following exception:\n", file=efile)
318261
elif (context is not None and
319262
not exc.__suppress_context__ and
320263
id(context) not in seen):
321-
print_exc(type(context), context, context.__traceback__, prefix)
322-
print(f"{prefix2}\n{prefix2}During handling of the above exception, "
323-
f"another exception occurred:\n{prefix2}", file=efile)
324-
if isinstance(exc, BaseExceptionGroup):
325-
print_exc_group(typ, exc, tb, prefix=prefix)
326-
else:
327-
if tb:
328-
print(f"{prefix2}Traceback (most recent call last):", file=efile)
329-
tbe = traceback.extract_tb(tb)
330-
cleanup_traceback(tbe, exclude)
331-
if prefix:
332-
for line in traceback.format_list(tbe):
333-
for subline in line.rstrip().splitlines():
334-
print(f"{prefix}| {subline}", file=efile)
335-
else:
336-
traceback.print_list(tbe, file=efile)
337-
lines = get_message_lines(typ, exc, tb)
338-
for line in lines:
339-
print(f"{prefix2}{line}", end="", file=efile)
264+
print_exc(type(context), context, context.__traceback__)
265+
print("\nDuring handling of the above exception, "
266+
"another exception occurred:\n", file=efile)
267+
if tb:
268+
tbe = traceback.extract_tb(tb)
269+
print('Traceback (most recent call last):', file=efile)
270+
exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
271+
"debugger_r.py", "bdb.py")
272+
cleanup_traceback(tbe, exclude)
273+
traceback.print_list(tbe, file=efile)
274+
lines = get_message_lines(typ, exc, tb)
275+
for line in lines:
276+
print(line, end='', file=efile)
340277

341278
print_exc(typ, val, tb)
342279

Misc/NEWS.d/next/IDLE/2025-10-05-19-33-39.gh-issue-139551.TX9BRc.rst

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)