1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- from contextvars import ContextVar
- from typing import Optional
- import sys
- import threading
- current_async_library_cvar = ContextVar(
- "current_async_library_cvar", default=None
- ) # type: ContextVar[Optional[str]]
- class _ThreadLocal(threading.local):
- # Since threading.local provides no explicit mechanism is for setting
- # a default for a value, a custom class with a class attribute is used
- # instead.
- name = None # type: Optional[str]
- thread_local = _ThreadLocal()
- class AsyncLibraryNotFoundError(RuntimeError):
- pass
- def current_async_library() -> str:
- """Detect which async library is currently running.
- The following libraries are currently supported:
- ================ =========== ============================
- Library Requires Magic string
- ================ =========== ============================
- **Trio** Trio v0.6+ ``"trio"``
- **Curio** - ``"curio"``
- **asyncio** ``"asyncio"``
- **Trio-asyncio** v0.8.2+ ``"trio"`` or ``"asyncio"``,
- depending on current mode
- ================ =========== ============================
- Returns:
- A string like ``"trio"``.
- Raises:
- AsyncLibraryNotFoundError: if called from synchronous context,
- or if the current async library was not recognized.
- Examples:
- .. code-block:: python3
- from sniffio import current_async_library
- async def generic_sleep(seconds):
- library = current_async_library()
- if library == "trio":
- import trio
- await trio.sleep(seconds)
- elif library == "asyncio":
- import asyncio
- await asyncio.sleep(seconds)
- # ... and so on ...
- else:
- raise RuntimeError(f"Unsupported library {library!r}")
- """
- value = thread_local.name
- if value is not None:
- return value
- value = current_async_library_cvar.get()
- if value is not None:
- return value
- # Need to sniff for asyncio
- if "asyncio" in sys.modules:
- import asyncio
- try:
- current_task = asyncio.current_task # type: ignore[attr-defined]
- except AttributeError:
- current_task = asyncio.Task.current_task # type: ignore[attr-defined]
- try:
- if current_task() is not None:
- return "asyncio"
- except RuntimeError:
- pass
- # Sniff for curio (for now)
- if 'curio' in sys.modules:
- from curio.meta import curio_running
- if curio_running():
- return 'curio'
- raise AsyncLibraryNotFoundError(
- "unknown async library, or not in async context"
- )
|