Skip to content

Commit 0b53a35

Browse files
committed
switched to asynccontextmanager for async controller operations
1 parent 3360857 commit 0b53a35

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

mypy.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ warn_unused_ignores = True
1717
disallow_untyped_defs = True
1818
check_untyped_defs = True
1919
no_implicit_reexport = True
20+
21+
[mypy-ninja_extra.compatible.*]
22+
ignore_errors = True

ninja_extra/compatible.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import sys
2+
3+
if sys.version_info >= (3, 7):
4+
from contextlib import asynccontextmanager as asynccontextmanager
5+
else:
6+
from contextlib2 import asynccontextmanager as asynccontextmanager # noqa

ninja_extra/operation.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import (
55
TYPE_CHECKING,
66
Any,
7+
AsyncIterator,
78
Callable,
89
Iterator,
910
List,
@@ -27,6 +28,7 @@
2728
from ninja.types import TCallable
2829
from ninja.utils import check_csrf
2930

31+
from ninja_extra.compatible import asynccontextmanager
3032
from ninja_extra.exceptions import APIException
3133
from ninja_extra.helper import get_function_name
3234
from ninja_extra.logger import request_logger
@@ -119,7 +121,7 @@ def get_execution_context(
119121
return route_function.get_route_execution_context(request, *args, **kwargs)
120122

121123
@contextmanager
122-
def _prep_run(self, request: HttpRequest, **kw: Any) -> Iterator:
124+
def _prep_run(self, request: HttpRequest, **kw: Any) -> Iterator[RouteContext]:
123125
try:
124126
start_time = time.time()
125127
context = self.get_execution_context(request, **kw)
@@ -223,12 +225,43 @@ async def run(self, request: HttpRequest, **kw: Any) -> HttpResponseBase: # typ
223225

224226

225227
class AsyncControllerOperation(AsyncOperation, ControllerOperation):
228+
@asynccontextmanager
229+
async def _prep_run( # type:ignore
230+
self, request: HttpRequest, **kw: Any
231+
) -> AsyncIterator[RouteContext]:
232+
try:
233+
start_time = time.time()
234+
context = self.get_execution_context(request, **kw)
235+
# send route_context_started signal
236+
route_context_started.send(RouteContext, route_context=context)
237+
238+
yield context
239+
self._log_action(
240+
request_logger.info,
241+
request=request,
242+
duration=time.time() - start_time,
243+
extra=dict(request=request),
244+
exc_info=None,
245+
)
246+
except Exception as e:
247+
self._log_action(
248+
request_logger.error,
249+
request=request,
250+
ex=e,
251+
extra=dict(request=request),
252+
exc_info=None,
253+
)
254+
raise e
255+
finally:
256+
# send route_context_finished signal
257+
route_context_finished.send(RouteContext, route_context=None)
258+
226259
async def run(self, request: HttpRequest, **kw: Any) -> HttpResponseBase: # type: ignore
227260
error = await self._run_checks(request)
228261
if error:
229262
return error
230263
try:
231-
with self._prep_run(request, **kw) as ctx:
264+
async with self._prep_run(request, **kw) as ctx:
232265
values = await self._get_values(request, kw) # type: ignore
233266
ctx.kwargs = values
234267
result = await self.view_func(context=ctx, **values)

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ requires = [
4444
"Django >= 2.2",
4545
"django-ninja >= 0.17.0",
4646
"injector",
47-
"asgiref"
47+
"asgiref",
48+
"contextlib2; python_version<'3.7'"
4849
]
4950
description-file = "README.md"
5051
requires-python = ">=3.6"

0 commit comments

Comments
 (0)