**Overview**
With this commit
(https://github.com/django/django/commit/53fad80ffe16ab4edb713b1ef0090d0fcf63565a),
which was included with the 3.2.9 release if we're on PY3.7+, we raise
SynchronousOnlyOperation when asyncio.get_running_loop returns an object
without checking event_loop.is_running().
It appears that asyncio.get_running_loop can return non-running loops, as
observed by including a logging statement before raising the
SynchronousOnlyOperation.
If my understanding is correct, get_running_loop should only be returning
running loops, and is not.
Curious if we can continue to leverage event_loop.is_running() in all
cases.
**Observation Example**
{{{
import asyncio
import functools
import os
from django.core.exceptions import SynchronousOnlyOperation
from django.utils.version import PY37
if PY37:
get_running_loop = asyncio.get_running_loop
else:
get_running_loop = asyncio.get_event_loop
def async_unsafe(message):
"""
Decorator to mark functions as async-unsafe. Someone trying to access
the function while in an async context will get an error message.
"""
def decorator(func):
@functools.wraps(func)
def inner(*args, **kwargs):
if not os.environ.get('DJANGO_ALLOW_ASYNC_UNSAFE'):
# Detect a running event loop in this thread.
try:
event_loop = get_running_loop()
except RuntimeError:
pass
else:
if PY37 or event_loop.is_running():
print(f"raising SynchronousOnlyOperation on
{event_loop} where is_running = {event_loop.is_running()}")
raise SynchronousOnlyOperation(message)
# Pass onwards.
return func(*args, **kwargs)
return inner
# If the message is actually a function, then be a no-arguments
decorator.
if callable(message):
func = message
message = 'You cannot call this from an async context - use a
thread or sync_to_async.'
return decorator(func)
else:
return decorator
}}}
**Observation Output**
{{{
raising SynchronousOnlyOperation on <_UnixSelectorEventLoop running=False
closed=False debug=False> where is_running = False
}}}
**Steps to reproduce**
1. Have a non-running event loop present and do just about anything in
Django
2. See SynchronousOnlyOperation raised
--
Ticket URL: <https://code.djangoproject.com/ticket/34737>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.