1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

Refs #34118 -- Adopted asgiref coroutine detection shims.

Thanks to Mariusz Felisiak for review.
This commit is contained in:
Carlton Gibson
2022-12-20 11:10:48 +01:00
committed by GitHub
parent a09d39f286
commit 32d70b2f55
15 changed files with 42 additions and 44 deletions

View File

@@ -2,7 +2,7 @@ import asyncio
import logging
import types
from asgiref.sync import async_to_sync, sync_to_async
from asgiref.sync import async_to_sync, iscoroutinefunction, sync_to_async
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, MiddlewareNotUsed
@@ -119,7 +119,7 @@ class BaseHandler:
- Asynchronous methods are left alone
"""
if method_is_async is None:
method_is_async = asyncio.iscoroutinefunction(method)
method_is_async = iscoroutinefunction(method)
if debug and not name:
name = name or "method %s()" % method.__qualname__
if is_async:
@@ -191,7 +191,7 @@ class BaseHandler:
if response is None:
wrapped_callback = self.make_view_atomic(callback)
# If it is an asynchronous view, run it in a subthread.
if asyncio.iscoroutinefunction(wrapped_callback):
if iscoroutinefunction(wrapped_callback):
wrapped_callback = async_to_sync(wrapped_callback)
try:
response = wrapped_callback(request, *callback_args, **callback_kwargs)
@@ -245,7 +245,7 @@ class BaseHandler:
if response is None:
wrapped_callback = self.make_view_atomic(callback)
# If it is a synchronous view, run it in a subthread
if not asyncio.iscoroutinefunction(wrapped_callback):
if not iscoroutinefunction(wrapped_callback):
wrapped_callback = sync_to_async(
wrapped_callback, thread_sensitive=True
)
@@ -278,7 +278,7 @@ class BaseHandler:
% (middleware_method.__self__.__class__.__name__,),
)
try:
if asyncio.iscoroutinefunction(response.render):
if iscoroutinefunction(response.render):
response = await response.render()
else:
response = await sync_to_async(
@@ -346,7 +346,7 @@ class BaseHandler:
non_atomic_requests = getattr(view, "_non_atomic_requests", set())
for alias, settings_dict in connections.settings.items():
if settings_dict["ATOMIC_REQUESTS"] and alias not in non_atomic_requests:
if asyncio.iscoroutinefunction(view):
if iscoroutinefunction(view):
raise RuntimeError(
"You cannot use ATOMIC_REQUESTS with async views."
)

View File

@@ -1,9 +1,8 @@
import asyncio
import logging
import sys
from functools import wraps
from asgiref.sync import sync_to_async
from asgiref.sync import iscoroutinefunction, sync_to_async
from django.conf import settings
from django.core import signals
@@ -34,7 +33,7 @@ def convert_exception_to_response(get_response):
no middleware leaks an exception and that the next middleware in the stack
can rely on getting a response instead of an exception.
"""
if asyncio.iscoroutinefunction(get_response):
if iscoroutinefunction(get_response):
@wraps(get_response)
async def inner(request):

View File

@@ -1,4 +1,3 @@
import asyncio
import difflib
import inspect
import json
@@ -26,7 +25,7 @@ from urllib.parse import (
)
from urllib.request import url2pathname
from asgiref.sync import async_to_sync
from asgiref.sync import async_to_sync, iscoroutinefunction
from django.apps import apps
from django.conf import settings
@@ -401,7 +400,7 @@ class SimpleTestCase(unittest.TestCase):
)
# Convert async test methods.
if asyncio.iscoroutinefunction(testMethod):
if iscoroutinefunction(testMethod):
setattr(self, self._testMethodName, async_to_sync(testMethod))
if not skipped:

View File

@@ -1,4 +1,3 @@
import asyncio
import collections
import logging
import os
@@ -14,6 +13,8 @@ from types import SimpleNamespace
from unittest import TestCase, skipIf, skipUnless
from xml.dom.minidom import Node, parseString
from asgiref.sync import iscoroutinefunction
from django.apps import apps
from django.apps.registry import Apps
from django.conf import UserSettingsHolder, settings
@@ -440,7 +441,7 @@ class TestContextDecorator:
raise TypeError("Can only decorate subclasses of unittest.TestCase")
def decorate_callable(self, func):
if asyncio.iscoroutinefunction(func):
if iscoroutinefunction(func):
# If the inner function is an async function, we must execute async
# as well so that the `with` statement executes at the right time.
@wraps(func)

View File

@@ -1,8 +1,7 @@
import asyncio
import inspect
import warnings
from asgiref.sync import sync_to_async
from asgiref.sync import iscoroutinefunction, markcoroutinefunction, sync_to_async
class RemovedInDjango50Warning(DeprecationWarning):
@@ -120,16 +119,14 @@ class MiddlewareMixin:
If get_response is a coroutine function, turns us into async mode so
a thread is not consumed during a whole request.
"""
if asyncio.iscoroutinefunction(self.get_response):
if iscoroutinefunction(self.get_response):
# Mark the class as async-capable, but do the actual switch
# inside __call__ to avoid swapping out dunder methods
self._is_coroutine = asyncio.coroutines._is_coroutine
else:
self._is_coroutine = None
markcoroutinefunction(self)
def __call__(self, request):
# Exit out to async mode, if needed
if self._is_coroutine:
if iscoroutinefunction(self):
return self.__acall__(request)
response = None
if hasattr(self, "process_request"):

View File

@@ -1,6 +1,7 @@
import asyncio
import logging
from asgiref.sync import iscoroutinefunction, markcoroutinefunction
from django.core.exceptions import ImproperlyConfigured
from django.http import (
HttpResponse,
@@ -68,8 +69,8 @@ class View:
]
if not handlers:
return False
is_async = asyncio.iscoroutinefunction(handlers[0])
if not all(asyncio.iscoroutinefunction(h) == is_async for h in handlers[1:]):
is_async = iscoroutinefunction(handlers[0])
if not all(iscoroutinefunction(h) == is_async for h in handlers[1:]):
raise ImproperlyConfigured(
f"{cls.__qualname__} HTTP handlers must either be all sync or all "
"async."
@@ -117,7 +118,7 @@ class View:
# Mark the callback if the view class is async.
if cls.view_is_async:
view._is_coroutine = asyncio.coroutines._is_coroutine
markcoroutinefunction(view)
return view