From 37d9ea5d5c010d54a416417399344c39f4e9f93e Mon Sep 17 00:00:00 2001
From: Adam Johnson <me@adamj.eu>
Date: Wed, 29 Sep 2021 09:47:24 +0100
Subject: [PATCH] Optimized @async_unsafe.

Switched the order of the checks to reduce the overhead. Async unsafe methods
are *normally* called syncrhonously, so we can avoid the overhead of checking
the environment variable in the regular path.
---
 django/utils/asyncio.py | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/django/utils/asyncio.py b/django/utils/asyncio.py
index 740ce5481a3..b8e14f1f68f 100644
--- a/django/utils/asyncio.py
+++ b/django/utils/asyncio.py
@@ -1,6 +1,6 @@
-import asyncio
-import functools
 import os
+from asyncio import get_running_loop
+from functools import wraps
 
 from django.core.exceptions import SynchronousOnlyOperation
 
@@ -11,15 +11,15 @@ def async_unsafe(message):
     the function while in an async context will get an error message.
     """
     def decorator(func):
-        @functools.wraps(func)
+        @wraps(func)
         def inner(*args, **kwargs):
-            if not os.environ.get('DJANGO_ALLOW_ASYNC_UNSAFE'):
-                # Detect a running event loop in this thread.
-                try:
-                    asyncio.get_running_loop()
-                except RuntimeError:
-                    pass
-                else:
+            # Detect a running event loop in this thread.
+            try:
+                get_running_loop()
+            except RuntimeError:
+                pass
+            else:
+                if not os.environ.get('DJANGO_ALLOW_ASYNC_UNSAFE'):
                     raise SynchronousOnlyOperation(message)
             # Pass onward.
             return func(*args, **kwargs)