summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorCarlton Gibson <carlton.gibson@noumenal.es>2022-12-20 11:10:48 +0100
committerGitHub <noreply@github.com>2022-12-20 11:10:48 +0100
commit32d70b2f55b1f74736fd11bc8efce890ad5fa2f0 (patch)
treed88822bb2391e7cf4fdbda59b9f222839aeb7e93 /django
parenta09d39f28609c707a62dbbbdc4e55489fae1631f (diff)
Refs #34118 -- Adopted asgiref coroutine detection shims.
Thanks to Mariusz Felisiak for review.
Diffstat (limited to 'django')
-rw-r--r--django/core/handlers/base.py12
-rw-r--r--django/core/handlers/exception.py5
-rw-r--r--django/test/testcases.py5
-rw-r--r--django/test/utils.py5
-rw-r--r--django/utils/deprecation.py11
-rw-r--r--django/views/generic/base.py9
6 files changed, 22 insertions, 25 deletions
diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py
index a934659186..8911543d4e 100644
--- a/django/core/handlers/base.py
+++ b/django/core/handlers/base.py
@@ -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."
)
diff --git a/django/core/handlers/exception.py b/django/core/handlers/exception.py
index 79577c2d0a..a0b1ba678a 100644
--- a/django/core/handlers/exception.py
+++ b/django/core/handlers/exception.py
@@ -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):
diff --git a/django/test/testcases.py b/django/test/testcases.py
index c78c2300a7..090a31e7c4 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -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:
diff --git a/django/test/utils.py b/django/test/utils.py
index 2b2b92c593..5e5649b0ac 100644
--- a/django/test/utils.py
+++ b/django/test/utils.py
@@ -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)
diff --git a/django/utils/deprecation.py b/django/utils/deprecation.py
index caed5b25d4..19379dfe58 100644
--- a/django/utils/deprecation.py
+++ b/django/utils/deprecation.py
@@ -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"):
diff --git a/django/views/generic/base.py b/django/views/generic/base.py
index 3a3afb0c73..8f8f9397e8 100644
--- a/django/views/generic/base.py
+++ b/django/views/generic/base.py
@@ -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