Skip to content

Commit 9e4cc13

Browse files
committed
fix omit_exception's problem with handling generator and async generators
1 parent 2942c31 commit 9e4cc13

File tree

1 file changed

+41
-11
lines changed

1 file changed

+41
-11
lines changed

django_valkey/base.py

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import builtins
22
import contextlib
33
import functools
4+
import inspect
45
import logging
56
from asyncio import iscoroutinefunction
67
from collections.abc import AsyncGenerator, Callable, Iterator
@@ -60,30 +61,59 @@ def omit_exception(method: Callable | None = None, return_value: Any | None = No
6061
if method is None:
6162
return functools.partial(omit_exception, return_value=return_value)
6263

64+
def __handle_error(self, e) -> Any | None:
65+
if getattr(self, "_ignore_exceptions", None):
66+
if getattr(self, "_log_ignored_exceptions", None):
67+
self.logger.exception("Exception ignored")
68+
69+
return return_value
70+
raise e.__cause__
71+
6372
@functools.wraps(method)
6473
def _decorator(self, *args, **kwargs):
6574
try:
6675
return method(self, *args, **kwargs)
6776
except ConnectionInterrupted as e:
68-
if self._ignore_exceptions:
69-
if self._log_ignored_exceptions:
70-
self.logger.exception("Exception ignored")
77+
return __handle_error(self, e)
7178

72-
return return_value
73-
raise e.__cause__ # noqa: B904
79+
@functools.wraps(method)
80+
def _generator_decorator(self, *args, **kwargs):
81+
try:
82+
for item in method(self, *args, **kwargs):
83+
yield item
84+
except ConnectionInterrupted as e:
85+
yield __handle_error(self, e)
7486

7587
@functools.wraps(method)
7688
async def _async_decorator(self, *args, **kwargs):
7789
try:
7890
return await method(self, *args, **kwargs)
7991
except ConnectionInterrupted as e:
80-
if self._ignore_exceptions:
81-
if self._log_ignored_exceptions:
82-
self.logger.exception("Exception ignored")
83-
return return_value
84-
raise e.__cause__
92+
return __handle_error(self, e)
93+
94+
@functools.wraps(method)
95+
async def _async_generator_decorator(self, *args, **kwargs):
96+
try:
97+
async for item in method(self, *args, **kwargs):
98+
yield item
99+
except ConnectionInterrupted as e:
100+
yield __handle_error(self, e)
101+
102+
# inspect.isfunction returns true for generators, so can't use that to check this
103+
if not inspect.isasyncgenfunction(method) and not inspect.isgeneratorfunction(
104+
method
105+
):
106+
wrapper = _async_decorator if iscoroutinefunction(method) else _decorator
107+
108+
# if method is a generator or async generator, it should be iterated over by this decorator
109+
# generators don't error by simply being called, they need to be iterated over.
110+
else:
111+
wrapper = (
112+
_async_generator_decorator
113+
if inspect.isasyncgenfunction(method)
114+
else _generator_decorator
115+
)
85116

86-
wrapper = _async_decorator if iscoroutinefunction(method) else _decorator
87117
wrapper.original = method
88118
return wrapper
89119

0 commit comments

Comments
 (0)