From c42e2924051a2f234be75a942ca7607ff350b10d Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Wed, 12 Jul 2023 14:56:01 +0200
Subject: [PATCH 1/5] catch now raises typeerror on async handler
---
CHANGES.rst | 3 +++
src/exceptiongroup/_catch.py | 9 ++++++++-
tests/test_catch.py | 17 +++++++++++++++++
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/CHANGES.rst b/CHANGES.rst
index 040c6f9..6780ff9 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -3,6 +3,9 @@ Version history
This library adheres to `Semantic Versioning 2.0 `_.
+**1.1.3**
+- `catch` now raises a `TypeError` if passed an async exception handler instead of just giving a `RuntimeWarning` about the coroutine never being awaited. (#66, PR by John Litborn)
+
**1.1.2**
- Changed handling of exceptions in exception group handler callbacks to not wrap a
diff --git a/src/exceptiongroup/_catch.py b/src/exceptiongroup/_catch.py
index 0be39b4..728cdd2 100644
--- a/src/exceptiongroup/_catch.py
+++ b/src/exceptiongroup/_catch.py
@@ -1,5 +1,6 @@
from __future__ import annotations
+import inspect
import sys
from collections.abc import Callable, Iterable, Mapping
from contextlib import AbstractContextManager
@@ -49,9 +50,15 @@ def handle_exception(self, exc: BaseException) -> BaseException | None:
matched, excgroup = excgroup.split(exc_types)
if matched:
try:
- handler(matched)
+ result = handler(matched)
except BaseException as new_exc:
new_exceptions.append(new_exc)
+ else:
+ if inspect.iscoroutine(result):
+ raise TypeError(
+ f"Error trying to handle {matched!r} with {handler!r}. "
+ "Exception handler must be a sync function."
+ )
if not excgroup:
break
diff --git a/tests/test_catch.py b/tests/test_catch.py
index 0af2fa0..82b58e5 100644
--- a/tests/test_catch.py
+++ b/tests/test_catch.py
@@ -162,3 +162,20 @@ def test_catch_subclass():
assert isinstance(lookup_errors[0], ExceptionGroup)
exceptions = lookup_errors[0].exceptions
assert isinstance(exceptions[0], KeyError)
+
+
+def test_async_handler():
+ import asyncio
+
+ from exceptiongroup import ExceptionGroup, catch
+
+ async def handler(eg):
+ # Log some stuff, then re-raise
+ raise eg
+
+ async def main():
+ with catch({TypeError: handler}):
+ raise ExceptionGroup("message", TypeError("uh-oh"))
+
+ with pytest.raises(TypeError):
+ asyncio.run(main())
From 086920b214e04602285ed855a86a8b620ee99260 Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Wed, 12 Jul 2023 15:59:13 +0200
Subject: [PATCH 2/5] fixes after review from agronholm
---
CHANGES.rst | 2 +-
src/exceptiongroup/_catch.py | 2 +-
tests/test_catch.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/CHANGES.rst b/CHANGES.rst
index 6780ff9..0aa8e73 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -3,7 +3,7 @@ Version history
This library adheres to `Semantic Versioning 2.0 `_.
-**1.1.3**
+**UNRELEASED**
- `catch` now raises a `TypeError` if passed an async exception handler instead of just giving a `RuntimeWarning` about the coroutine never being awaited. (#66, PR by John Litborn)
**1.1.2**
diff --git a/src/exceptiongroup/_catch.py b/src/exceptiongroup/_catch.py
index 728cdd2..f010d07 100644
--- a/src/exceptiongroup/_catch.py
+++ b/src/exceptiongroup/_catch.py
@@ -58,7 +58,7 @@ def handle_exception(self, exc: BaseException) -> BaseException | None:
raise TypeError(
f"Error trying to handle {matched!r} with {handler!r}. "
"Exception handler must be a sync function."
- )
+ ) from excgroup
if not excgroup:
break
diff --git a/tests/test_catch.py b/tests/test_catch.py
index 82b58e5..f0cb835 100644
--- a/tests/test_catch.py
+++ b/tests/test_catch.py
@@ -177,5 +177,5 @@ async def main():
with catch({TypeError: handler}):
raise ExceptionGroup("message", TypeError("uh-oh"))
- with pytest.raises(TypeError):
+ with pytest.raises(TypeError, match="Exception handler must be a sync function."):
asyncio.run(main())
From 7702cecad26a4fb9dc34e93ebac8fec664b96ad8 Mon Sep 17 00:00:00 2001
From: jakkdl
Date: Wed, 12 Jul 2023 17:02:04 +0200
Subject: [PATCH 3/5] from exc instead of from excgroup
---
src/exceptiongroup/_catch.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/exceptiongroup/_catch.py b/src/exceptiongroup/_catch.py
index f010d07..2d82be1 100644
--- a/src/exceptiongroup/_catch.py
+++ b/src/exceptiongroup/_catch.py
@@ -58,7 +58,7 @@ def handle_exception(self, exc: BaseException) -> BaseException | None:
raise TypeError(
f"Error trying to handle {matched!r} with {handler!r}. "
"Exception handler must be a sync function."
- ) from excgroup
+ ) from exc
if not excgroup:
break
From 1e3c95e1743666b1315f2f27089484c3033e9632 Mon Sep 17 00:00:00 2001
From: John Litborn <11260241+jakkdl@users.noreply.github.com>
Date: Wed, 12 Jul 2023 17:10:28 +0200
Subject: [PATCH 4/5] Update tests/test_catch.py
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Alex Grönholm
---
tests/test_catch.py | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/tests/test_catch.py b/tests/test_catch.py
index f0cb835..caf1368 100644
--- a/tests/test_catch.py
+++ b/tests/test_catch.py
@@ -164,18 +164,15 @@ def test_catch_subclass():
assert isinstance(exceptions[0], KeyError)
-def test_async_handler():
- import asyncio
-
- from exceptiongroup import ExceptionGroup, catch
-
+def test_async_handler(request):
async def handler(eg):
- # Log some stuff, then re-raise
- raise eg
+ pass
- async def main():
- with catch({TypeError: handler}):
- raise ExceptionGroup("message", TypeError("uh-oh"))
+ def delegate(eg):
+ coro = handler(eg)
+ request.addfinalizer(coro.close)
+ return coro
with pytest.raises(TypeError, match="Exception handler must be a sync function."):
- asyncio.run(main())
+ with catch({TypeError: delegate}):
+ raise ExceptionGroup("message", TypeError("uh-oh"))
From 3aa76d8459e0b517803dd79c22d0c509c29e58f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?=
Date: Wed, 12 Jul 2023 18:42:37 +0300
Subject: [PATCH 5/5] Update CHANGES.rst
---
CHANGES.rst | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/CHANGES.rst b/CHANGES.rst
index 0aa8e73..eccb5b3 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,9 @@ Version history
This library adheres to `Semantic Versioning 2.0 `_.
**UNRELEASED**
-- `catch` now raises a `TypeError` if passed an async exception handler instead of just giving a `RuntimeWarning` about the coroutine never being awaited. (#66, PR by John Litborn)
+- `catch()` now raises a `TypeError` if passed an async exception handler instead of
+ just giving a `RuntimeWarning` about the coroutine never being awaited. (#66, PR by
+ John Litborn)
**1.1.2**