diff --git a/CHANGES.rst b/CHANGES.rst index e7f43c5..a35a39c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,6 +3,12 @@ Version history This library adheres to `Semantic Versioning 2.0 `_. +**UNRELEASED** + +- Fixed the ``repr()`` of exception groups being affected by mutation of the + original exception sequence after construction + (`#154 `_) + **1.3.1** - Fixed ``AttributeError: 'TracebackException' object has no attribute 'exceptions'`` diff --git a/src/exceptiongroup/_exceptions.py b/src/exceptiongroup/_exceptions.py index f42c1ad..b101e44 100644 --- a/src/exceptiongroup/_exceptions.py +++ b/src/exceptiongroup/_exceptions.py @@ -275,7 +275,9 @@ def __str__(self) -> str: return f"{self.message} ({len(self._exceptions)} sub-exception{suffix})" def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.args[0]!r}, {self.args[1]!r})" + return ( + f"{self.__class__.__name__}({self.args[0]!r}, {list(self._exceptions)!r})" + ) class ExceptionGroup(BaseExceptionGroup[_ExceptionT_co], Exception): diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index e2bc81a..932f394 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -882,7 +882,13 @@ def test_exceptions_mutate_original_sequence(): exceptions.append(KeyError("bar")) assert excgrp.exceptions is exc_tuple - assert repr(excgrp) == ( - "BaseExceptionGroup('foo', [ValueError(1), KeyboardInterrupt(), " - "KeyError('bar')])" - ) + if sys.version_info < (3, 11): + # On < 3.11, the backport is active and stores exceptions as a tuple, + # so repr reflects the original (unmutated) exceptions. + # On >= 3.11, native BaseExceptionGroup is used. Whether the repr + # shows original or mutated exceptions depends on the CPython version + # (cpython#141736 fixes it for 3.13.12+, but not yet in 3.14). + # We only assert the backport behavior since we control it. + assert repr(excgrp) == ( + "BaseExceptionGroup('foo', [ValueError(1), KeyboardInterrupt()])" + )