123456789101112131415161718192021222324252627282930313233343536373839 |
- import os
- from asyncio import get_running_loop
- from functools import wraps
-
- from django.core.exceptions import SynchronousOnlyOperation
-
-
- 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):
- @wraps(func)
- def inner(*args, **kwargs):
- # 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)
-
- 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
|