Repository: python-trio/trio-asyncio (language: python)

Issue:
Properly support ExceptionGroup wrapping in trio 0.25.0+
For now, we're punting by pinning trio to <0.25.0 for our CI. Instead, we should update our testsuite to use the new RaisesGroup and other testing tools to properly handle the ExceptionGroup wrapping.

I don't think there are any hazards to trio-asyncio users, beyond the fact that `open_loop()` now adds ExceptionGroup layers, so this should be just a testsuite change.


Discussion / hints:

Fix patch:
diff --git a/docs-requirements.txt b/docs-requirements.txt
index f546b2e..169a38a 100644
--- a/docs-requirements.txt
+++ b/docs-requirements.txt
@@ -2,7 +2,7 @@ sphinx >= 1.7.0
 sphinx_rtd_theme
 sphinxcontrib-trio
 towncrier
-trio >= 0.15.0,< 0.25.0
+trio >= 0.25.0
 outcome
 attrs
 greenlet
diff --git a/newsfragments/146.misc.rst b/newsfragments/146.misc.rst
new file mode 100644
index 0000000..5176c65
--- /dev/null
+++ b/newsfragments/146.misc.rst
@@ -0,0 +1,1 @@
+Updated test suite to cope with Trio 0.25.0 and later defaulting ``strict_exception_groups`` to ``True``. Trio 0.25.0 is now required to run the tests, although trio-asyncio itself still supports older versions.
\ No newline at end of file


Test patch:
diff --git a/test-requirements.txt b/test-requirements.txt
index 304a4fc..bb660a4 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,4 +3,4 @@ pytest-cov
 pytest-trio
 outcome
 pytest-timeout
-trio >= 0.15.0,< 0.25.0
+trio >= 0.25.0
diff --git a/tests/interop/test_calls.py b/tests/interop/test_calls.py
index f77ba40..59c0197 100644
--- a/tests/interop/test_calls.py
+++ b/tests/interop/test_calls.py
@@ -299,7 +299,7 @@ async def cancel_trio(seen):
                 seen.flag |= 8
 
         seen = Seen()
-        with pytest.raises(asyncio.CancelledError):
+        with trio.testing.RaisesGroup(asyncio.CancelledError):
             await cancel_trio(seen)
         assert seen.flag == 1 | 8
 
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 2343a41..8724149 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -225,7 +225,7 @@ async def run_asyncio_loop(nursery, *, task_status=trio.TASK_STATUS_IGNORED):
     import signal
     import threading
 
-    with pytest.raises(KeyboardInterrupt):
+    with trio.testing.RaisesGroup(KeyboardInterrupt):
         async with trio.open_nursery() as nursery:
             await nursery.start(run_asyncio_loop, nursery)
             # Trigger KeyboardInterrupt that should propagate accross the coroutines
@@ -270,7 +270,7 @@ async def trio_task():
         scope.cancel()
     assert fut.done()
     if throw_another:
-        with pytest.raises(ValueError, match="hi"):
+        with trio.testing.RaisesGroup(trio.testing.Matcher(ValueError, match="hi")):
             fut.result()
     else:
         assert fut.cancelled()
@@ -333,12 +333,19 @@ def collect_exceptions(loop, context):
     )
     expected = [ValueError("hi"), ValueError("lo"), KeyError(), IndexError()]
     await raise_in_aio_loop(expected[0])
-    with pytest.raises(SystemExit):
+    with trio.testing.RaisesGroup(SystemExit, strict=False):
         await raise_in_aio_loop(SystemExit(0))
-    with pytest.raises(BaseExceptionGroup) as result:
+    with trio.testing.RaisesGroup(SystemExit, strict=False) as result:
         await raise_in_aio_loop(BaseExceptionGroup("", [expected[1], SystemExit()]))
+
     assert len(result.value.exceptions) == 1
-    assert isinstance(result.value.exceptions[0], SystemExit)
+
+    def innermost_exception(item):
+        if isinstance(item, BaseExceptionGroup):
+            return innermost_exception(item.exceptions[0])
+        return item
+
+    assert isinstance(innermost_exception(result.value), SystemExit)
     await raise_in_aio_loop(ExceptionGroup("", expected[2:]))
 
     assert len(exceptions) == 3
diff --git a/tests/test_trio_asyncio.py b/tests/test_trio_asyncio.py
index 5afb17a..6bcb684 100644
--- a/tests/test_trio_asyncio.py
+++ b/tests/test_trio_asyncio.py
@@ -121,7 +121,9 @@ async def test_cancel_loop_with_tasks(autojump_clock, shield, body_raises):
     record = []
 
     if body_raises:
-        catcher = pytest.raises(ValueError, match="hi")
+        catcher = trio.testing.RaisesGroup(
+            trio.testing.Matcher(ValueError, match="hi"), strict=False
+        )
     else:
         catcher = contextlib.nullcontext()