asyncio.py 1.0 KB

1234567891011121314151617181920212223242526272829303132
  1. import asyncio
  2. import functools
  3. from django.core.exceptions import SynchronousOnlyOperation
  4. def async_unsafe(message):
  5. """
  6. Decorator to mark functions as async-unsafe. Someone trying to access
  7. the function while in an async context will get an error message.
  8. """
  9. def decorator(func):
  10. @functools.wraps(func)
  11. def inner(*args, **kwargs):
  12. # Detect a running event loop in this thread.
  13. try:
  14. event_loop = asyncio.get_event_loop()
  15. except RuntimeError:
  16. pass
  17. else:
  18. if event_loop.is_running():
  19. raise SynchronousOnlyOperation(message)
  20. # Pass onwards.
  21. return func(*args, **kwargs)
  22. return inner
  23. # If the message is actually a function, then be a no-arguments decorator.
  24. if callable(message):
  25. func = message
  26. message = 'You cannot call this from an async context - use a thread or sync_to_async.'
  27. return decorator(func)
  28. else:
  29. return decorator