From cd9d3a56204b36d342e488ee35868d8d33385d5d Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Sat, 9 Dec 2023 14:23:54 +0100
Subject: [PATCH] add test for _ExceptionInfo (and fix it)
---
src/trio/_tests/test_testing_raisesgroup.py | 15 +++++++++++
src/trio/testing/_raises_group.py | 28 +++++++++++++++++++--
2 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/src/trio/_tests/test_testing_raisesgroup.py b/src/trio/_tests/test_testing_raisesgroup.py
index 274484aad6..87bd36f3b3 100644
--- a/src/trio/_tests/test_testing_raisesgroup.py
+++ b/src/trio/_tests/test_testing_raisesgroup.py
@@ -2,10 +2,12 @@
import re
import sys
+from types import TracebackType
from typing import TYPE_CHECKING
import pytest
+import trio
from trio.testing import Matcher, RaisesGroup
# TODO: make a public export
@@ -195,6 +197,19 @@ def check_errno_is_5(e: OSError) -> bool:
raise ExceptionGroup("", (OSError(6, ""),))
+def test__ExceptionInfo(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setattr(
+ trio.testing._raises_group,
+ "ExceptionInfo",
+ trio.testing._raises_group._ExceptionInfo,
+ )
+ with trio.testing.RaisesGroup(ValueError) as excinfo:
+ raise ExceptionGroup("", (ValueError("hello"),))
+ assert excinfo.type is ExceptionGroup
+ assert excinfo.value.exceptions[0].args == ("hello",)
+ assert isinstance(excinfo.tb, TracebackType)
+
+
if TYPE_CHECKING:
# getting the typing working satisfactory is very tricky
# but with RaisesGroup being seen as a subclass of BaseExceptionGroup
diff --git a/src/trio/testing/_raises_group.py b/src/trio/testing/_raises_group.py
index 127fb42678..3acf243b76 100644
--- a/src/trio/testing/_raises_group.py
+++ b/src/trio/testing/_raises_group.py
@@ -32,7 +32,7 @@ class _ExceptionInfo(Generic[E]):
_excinfo: tuple[type[E], E, TracebackType] | None
def __init__(self, excinfo: tuple[type[E], E, TracebackType] | None):
- self._exc_info = excinfo
+ self._excinfo = excinfo
def fill_unfilled(self, exc_info: tuple[type[E], E, TracebackType]) -> None:
"""Fill an unfilled ExceptionInfo created with ``for_later()``."""
@@ -44,6 +44,30 @@ def for_later(cls) -> _ExceptionInfo[E]:
"""Return an unfilled ExceptionInfo."""
return cls(None)
+ @property
+ def type(self) -> type[E]:
+ """The exception class."""
+ assert (
+ self._excinfo is not None
+ ), ".type can only be used after the context manager exits"
+ return self._excinfo[0]
+
+ @property
+ def value(self) -> E:
+ """The exception value."""
+ assert (
+ self._excinfo is not None
+ ), ".value can only be used after the context manager exits"
+ return self._excinfo[1]
+
+ @property
+ def tb(self) -> TracebackType:
+ """The exception raw traceback."""
+ assert (
+ self._excinfo is not None
+ ), ".tb can only be used after the context manager exits"
+ return self._excinfo[2]
+
# this may bite users with type checkers not using pytest, but that should
# be rare and give quite obvious errors in tests trying to do so.
@@ -53,7 +77,7 @@ def for_later(cls) -> _ExceptionInfo[E]:
else:
try:
from pytest import ExceptionInfo
- except ImportError:
+ except ImportError: # pragma: no cover
ExceptionInfo = _ExceptionInfo