Skip to content

Commit 0c6cfbf

Browse files
worksbyfridayclaudepre-commit-ci[bot]
authored
Fix ExceptionGroup repr changing when original exception sequence is mutated (#155)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 2cba843 commit 0c6cfbf

3 files changed

Lines changed: 19 additions & 5 deletions

File tree

CHANGES.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ Version history
33

44
This library adheres to `Semantic Versioning 2.0 <http://semver.org/>`_.
55

6+
**UNRELEASED**
7+
8+
- Fixed the ``repr()`` of exception groups being affected by mutation of the
9+
original exception sequence after construction
10+
(`#154 <https://github.com/agronholm/exceptiongroup/issues/154>`_)
11+
612
**1.3.1**
713

814
- Fixed ``AttributeError: 'TracebackException' object has no attribute 'exceptions'``

src/exceptiongroup/_exceptions.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,9 @@ def __str__(self) -> str:
275275
return f"{self.message} ({len(self._exceptions)} sub-exception{suffix})"
276276

277277
def __repr__(self) -> str:
278-
return f"{self.__class__.__name__}({self.args[0]!r}, {self.args[1]!r})"
278+
return (
279+
f"{self.__class__.__name__}({self.args[0]!r}, {list(self._exceptions)!r})"
280+
)
279281

280282

281283
class ExceptionGroup(BaseExceptionGroup[_ExceptionT_co], Exception):

tests/test_exceptions.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,13 @@ def test_exceptions_mutate_original_sequence():
882882

883883
exceptions.append(KeyError("bar"))
884884
assert excgrp.exceptions is exc_tuple
885-
assert repr(excgrp) == (
886-
"BaseExceptionGroup('foo', [ValueError(1), KeyboardInterrupt(), "
887-
"KeyError('bar')])"
888-
)
885+
if sys.version_info < (3, 11):
886+
# On < 3.11, the backport is active and stores exceptions as a tuple,
887+
# so repr reflects the original (unmutated) exceptions.
888+
# On >= 3.11, native BaseExceptionGroup is used. Whether the repr
889+
# shows original or mutated exceptions depends on the CPython version
890+
# (cpython#141736 fixes it for 3.13.12+, but not yet in 3.14).
891+
# We only assert the backport behavior since we control it.
892+
assert repr(excgrp) == (
893+
"BaseExceptionGroup('foo', [ValueError(1), KeyboardInterrupt()])"
894+
)

0 commit comments

Comments
 (0)