From 078b112138aef905bc45c2569a48862b3680e4c0 Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Thu, 11 Aug 2022 14:41:17 +0200
Subject: [PATCH] Squashed commit of the following:
commit 41d339c46763bbe26123e1e6504b6e32290e33e1
Author: Cheukting
Date: Thu Jun 23 17:01:04 2022 +0800
test in all py versions
commit b3572a5a12672228c3276fc8c8e05980dfb7888a
Author: Cheukting
Date: Thu Jun 23 16:41:06 2022 +0800
add test
commit 7166a2a51e4f99046b028b663c193d8b558c7fd4
Author: Cheukting
Date: Thu Jun 23 16:00:07 2022 +0800
update changelog
commit b958c73d489157f0c0d4e46425083a5e2e2bc851
Author: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Thu Jun 23 07:50:52 2022 +0000
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
commit ea7f376c6ca37c40c83df0e4a1cfaaedb34bae91
Author: Cheukting
Date: Thu Jun 23 15:48:21 2022 +0800
Fix MyPy
commit 97469beb1da40257e9a061a5e19548546c9312c4
Author: Cheukting
Date: Thu Jun 23 15:03:48 2022 +0800
fix if ExceptionGroup not exist
commit 84e553642cd69b4d499231d733df91ebfa84c7ad
Author: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Thu Jun 23 03:43:27 2022 +0000
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
commit 76bbef449b88bbd74fb5cca3b5293337a624ef03
Author: Cheukting
Date: Thu Jun 23 11:40:41 2022 +0800
adding changelog
commit db82bebc5a4969e2083adcd97bdfd2a63bb17d98
Author: Cheukting
Date: Thu Jun 23 11:33:10 2022 +0800
fall back to native when handeling to exception groups
---
changelog/9159.bugfix.rst | 1 +
src/_pytest/_code/code.py | 29 +++++++++++++++++++++++++----
testing/code/test_excinfo.py | 31 +++++++++++++++++++++++++++++++
tox.ini | 1 +
4 files changed, 58 insertions(+), 4 deletions(-)
create mode 100644 changelog/9159.bugfix.rst
diff --git a/changelog/9159.bugfix.rst b/changelog/9159.bugfix.rst
new file mode 100644
index 000000000..5e7f0a301
--- /dev/null
+++ b/changelog/9159.bugfix.rst
@@ -0,0 +1 @@
+Showing inner exceptions by forcing native display in ``ExceptionGroups`` even when using display options other than ``--tb=native``. A temporary step before full implementation of pytest-native display for inner exceptions in ``ExceptionGroups``.
diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py
index 304a5cbd7..b1991f1aa 100644
--- a/src/_pytest/_code/code.py
+++ b/src/_pytest/_code/code.py
@@ -56,6 +56,18 @@ if TYPE_CHECKING:
_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
+ExceptionGroupTypes: tuple = () # type: ignore
+try:
+ ExceptionGroupTypes += (ExceptionGroup,) # type: ignore
+except NameError:
+ pass # Is missing for `python<3.10`
+try:
+ import exceptiongroup
+
+ ExceptionGroupTypes += (exceptiongroup.ExceptionGroup,)
+except ModuleNotFoundError:
+ pass # No backport is installed
+
class Code:
"""Wrapper around Python code objects."""
@@ -923,11 +935,20 @@ class FormattedExcinfo:
seen: Set[int] = set()
while e is not None and id(e) not in seen:
seen.add(id(e))
- if excinfo_:
- reprtraceback = self.repr_traceback(excinfo_)
- reprcrash: Optional[ReprFileLocation] = (
- excinfo_._getreprcrash() if self.style != "value" else None
+ if isinstance(e, ExceptionGroupTypes):
+ reprtraceback: Union[
+ ReprTracebackNative, ReprTraceback
+ ] = ReprTracebackNative(
+ traceback.format_exception(
+ type(excinfo.value),
+ excinfo.value,
+ excinfo.traceback[0]._rawentry,
+ )
)
+ reprcrash: Optional[ReprFileLocation] = None
+ elif excinfo_:
+ reprtraceback = self.repr_traceback(excinfo_)
+ reprcrash = excinfo_._getreprcrash() if self.style != "value" else None
else:
# Fallback to native repr if the exception doesn't have a traceback:
# ExceptionInfo objects require a full traceback to work.
diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py
index af72857f3..78f777718 100644
--- a/testing/code/test_excinfo.py
+++ b/testing/code/test_excinfo.py
@@ -1470,3 +1470,34 @@ def test_no_recursion_index_on_recursion_error():
with pytest.raises(RuntimeError) as excinfo:
RecursionDepthError().trigger
assert "maximum recursion" in str(excinfo.getrepr())
+
+
+def test_exceptiongroup(pytester: Pytester) -> None:
+ pytester.makepyfile(
+ """
+ def f(): raise ValueError("From f()")
+ def g(): raise RuntimeError("From g()")
+
+ def main():
+ excs = []
+ for callback in [f, g]:
+ try:
+ callback()
+ except Exception as err:
+ excs.append(err)
+ if excs:
+ raise ExceptionGroup("Oops", excs)
+
+ def test():
+ main()
+ """
+ )
+ result = pytester.runpytest()
+ assert result.ret != 0
+
+ match = [
+ r" | ExceptionGroup: Oops (2 sub-exceptions)",
+ r" | ValueError: From f()",
+ r" | RuntimeError: From g()",
+ ]
+ result.stdout.re_match_lines(match)
diff --git a/tox.ini b/tox.ini
index 93c390ffc..fd2ff1ba1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -46,6 +46,7 @@ setenv =
extras = testing
deps =
doctesting: PyYAML
+ exceptiongroup: exceptiongroup>=1.0.0
numpy: numpy>=1.19.4
pexpect: pexpect>=4.8.0
pluggymain: pluggy @ git+https://github.com/pytest-dev/pluggy.git