From a6d9a1960b3611f6d5b988b3ffc67010f153ffd5 Mon Sep 17 00:00:00 2001 From: Max Fischer Date: Wed, 20 Mar 2024 16:03:39 +0100 Subject: [PATCH 1/2] handle exception groups --- .../utility/concurrent/test_meta_runner.py | 17 +++++++++++++---- setup.py | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cobald_tests/utility/concurrent/test_meta_runner.py b/cobald_tests/utility/concurrent/test_meta_runner.py index d9306fa..f7a4a05 100644 --- a/cobald_tests/utility/concurrent/test_meta_runner.py +++ b/cobald_tests/utility/concurrent/test_meta_runner.py @@ -1,3 +1,4 @@ +from typing import Iterator import threading import pytest import time @@ -6,6 +7,7 @@ import gc import trio +from exceptiongroup import ExceptionGroup from cobald.daemon.runners.base_runner import OrphanedReturn from cobald.daemon.runners.meta_runner import MetaRunner @@ -15,8 +17,15 @@ class TerminateRunner(Exception): pass +def unwrap_cause(exc: BaseException) -> BaseException: + if isinstance(exc.__cause__, ExceptionGroup): + assert len(exc.__cause__.exceptions) == 1 + return exc.__cause__.exceptions[0] + return exc.__cause__ + + @contextlib.contextmanager -def threaded_run(name): +def threaded_run(name: str) -> Iterator[MetaRunner]: gc.collect() runner = MetaRunner() thread = threading.Thread(target=runner.run, name=name, daemon=True) @@ -90,7 +99,7 @@ async def with_return(): runner.register_payload(with_return, flavour=flavour) with pytest.raises(RuntimeError) as exc: runner.run() - assert isinstance(exc.value.__cause__, OrphanedReturn) + assert isinstance(unwrap_cause(exc.value), OrphanedReturn) @pytest.mark.parametrize("flavour", (threading,)) def test_abort_subroutine(self, flavour): @@ -130,7 +139,7 @@ async def abort(): runner.register_payload(abort, flavour=flavour) with pytest.raises(RuntimeError) as exc: runner.run() - assert isinstance(exc.value.__cause__, TerminateRunner) + assert isinstance(unwrap_cause(exc.value), TerminateRunner) async def noop(): return @@ -144,4 +153,4 @@ async def loop(): runner.register_payload(abort, flavour=flavour) with pytest.raises(RuntimeError) as exc: runner.run() - assert isinstance(exc.value.__cause__, TerminateRunner) + assert isinstance(unwrap_cause(exc.value), TerminateRunner) diff --git a/setup.py b/setup.py index a520083..f05a4a2 100644 --- a/setup.py +++ b/setup.py @@ -60,6 +60,7 @@ "trio", "entrypoints", "toposort", + "exceptiongroup", ], extras_require={ "docs": ["sphinx", "sphinx_rtd_theme"], From 65e034229779c4217d5b1b28e825c8eb1e3fcac5 Mon Sep 17 00:00:00 2001 From: Max Fischer Date: Wed, 20 Mar 2024 16:09:38 +0100 Subject: [PATCH 2/2] EG are only used in tests --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index f05a4a2..f96f9a7 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ with open(os.path.join(repo_base_dir, "README.rst"), "r") as README: long_description = README.read() -TESTS_REQUIRE = ["pytest>=4.3.0", "pytest-timeout"] +TESTS_REQUIRE = ["pytest>=4.3.0", "pytest-timeout", "exceptiongroup"] if __name__ == "__main__": setup( @@ -60,7 +60,6 @@ "trio", "entrypoints", "toposort", - "exceptiongroup", ], extras_require={ "docs": ["sphinx", "sphinx_rtd_theme"],