about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/sniffio
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/sniffio')
-rw-r--r--.venv/lib/python3.12/site-packages/sniffio/__init__.py17
-rw-r--r--.venv/lib/python3.12/site-packages/sniffio/_impl.py95
-rw-r--r--.venv/lib/python3.12/site-packages/sniffio/_tests/__init__.py0
-rw-r--r--.venv/lib/python3.12/site-packages/sniffio/_tests/test_sniffio.py84
-rw-r--r--.venv/lib/python3.12/site-packages/sniffio/_version.py3
-rw-r--r--.venv/lib/python3.12/site-packages/sniffio/py.typed0
6 files changed, 199 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/sniffio/__init__.py b/.venv/lib/python3.12/site-packages/sniffio/__init__.py
new file mode 100644
index 00000000..63f2f19e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sniffio/__init__.py
@@ -0,0 +1,17 @@
+"""Top-level package for sniffio."""
+
+__all__ = [
+    "current_async_library",
+    "AsyncLibraryNotFoundError",
+    "current_async_library_cvar",
+    "thread_local",
+]
+
+from ._version import __version__
+
+from ._impl import (
+    current_async_library,
+    AsyncLibraryNotFoundError,
+    current_async_library_cvar,
+    thread_local,
+)
diff --git a/.venv/lib/python3.12/site-packages/sniffio/_impl.py b/.venv/lib/python3.12/site-packages/sniffio/_impl.py
new file mode 100644
index 00000000..c1a7bbf2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sniffio/_impl.py
@@ -0,0 +1,95 @@
+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"
+    )
diff --git a/.venv/lib/python3.12/site-packages/sniffio/_tests/__init__.py b/.venv/lib/python3.12/site-packages/sniffio/_tests/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sniffio/_tests/__init__.py
diff --git a/.venv/lib/python3.12/site-packages/sniffio/_tests/test_sniffio.py b/.venv/lib/python3.12/site-packages/sniffio/_tests/test_sniffio.py
new file mode 100644
index 00000000..02945a94
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sniffio/_tests/test_sniffio.py
@@ -0,0 +1,84 @@
+import os
+import sys
+
+import pytest
+
+from .. import (
+    current_async_library, AsyncLibraryNotFoundError,
+    current_async_library_cvar, thread_local
+)
+
+
+def test_basics_cvar():
+    with pytest.raises(AsyncLibraryNotFoundError):
+        current_async_library()
+
+    token = current_async_library_cvar.set("generic-lib")
+    try:
+        assert current_async_library() == "generic-lib"
+    finally:
+        current_async_library_cvar.reset(token)
+
+    with pytest.raises(AsyncLibraryNotFoundError):
+        current_async_library()
+
+
+def test_basics_tlocal():
+    with pytest.raises(AsyncLibraryNotFoundError):
+        current_async_library()
+
+    old_name, thread_local.name = thread_local.name, "generic-lib"
+    try:
+        assert current_async_library() == "generic-lib"
+    finally:
+        thread_local.name = old_name
+
+    with pytest.raises(AsyncLibraryNotFoundError):
+        current_async_library()
+
+
+def test_asyncio():
+    import asyncio
+
+    with pytest.raises(AsyncLibraryNotFoundError):
+        current_async_library()
+
+    ran = []
+
+    async def this_is_asyncio():
+        assert current_async_library() == "asyncio"
+        # Call it a second time to exercise the caching logic
+        assert current_async_library() == "asyncio"
+        ran.append(True)
+
+    asyncio.run(this_is_asyncio())
+    assert ran == [True]
+
+    with pytest.raises(AsyncLibraryNotFoundError):
+        current_async_library()
+
+
+@pytest.mark.skipif(
+    sys.version_info >= (3, 12),
+    reason=
+    "curio broken on 3.12 (https://github.com/python-trio/sniffio/pull/42)",
+)
+def test_curio():
+    import curio
+
+    with pytest.raises(AsyncLibraryNotFoundError):
+        current_async_library()
+
+    ran = []
+
+    async def this_is_curio():
+        assert current_async_library() == "curio"
+        # Call it a second time to exercise the caching logic
+        assert current_async_library() == "curio"
+        ran.append(True)
+
+    curio.run(this_is_curio)
+    assert ran == [True]
+
+    with pytest.raises(AsyncLibraryNotFoundError):
+        current_async_library()
diff --git a/.venv/lib/python3.12/site-packages/sniffio/_version.py b/.venv/lib/python3.12/site-packages/sniffio/_version.py
new file mode 100644
index 00000000..0495d105
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sniffio/_version.py
@@ -0,0 +1,3 @@
+# This file is imported from __init__.py and exec'd from setup.py
+
+__version__ = "1.3.1"
diff --git a/.venv/lib/python3.12/site-packages/sniffio/py.typed b/.venv/lib/python3.12/site-packages/sniffio/py.typed
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sniffio/py.typed