Skip to content

Commit

Permalink
tweak docs
Browse files Browse the repository at this point in the history
  • Loading branch information
oremanj committed Jul 11, 2023
1 parent 4e42363 commit 852561d
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 27 deletions.
27 changes: 14 additions & 13 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,26 @@ easy.
**Step 1:** Pick the magic string that will identify your library. To
avoid collisions, this should match your library's PEP 503 normalized name on PyPI.

**Step 2:** There's a special :class:`threading.local` object:
**Step 2:** There's a special :class:`threading.local` object attribute that
sniffio consults to determine the currently running library:

.. data:: thread_local.name
.. data:: sniffio.thread_local.name

Make sure that whenever your library is potentially executing user-provided code,
this is set to your identifier string. In many cases, you can set it once when
your library starts up and restore it on shutdown:

.. code-block:: python3
from sniffio import thread_local as sniffio_loop
from sniffio import thread_local as sniffio_library
# Your library's run function (like trio.run() or asyncio.run())
def run(...):
old_name, sniffio_loop.name = sniffio_loop.name, "my-library's-PyPI-name"
old_name, sniffio_library.name = sniffio_library.name, "my-library's-PyPI-name"
try:
# actual event loop implementation left as an exercise to the reader
finally:
sniffio_loop.name = old_name
sniffio_library.name = old_name
In unusual situations you may need to be more fine-grained about it:

Expand All @@ -87,25 +88,25 @@ In unusual situations you may need to be more fine-grained about it:
than around an entire ``run()`` function.

* If you're using something akin to `trio-asyncio
<https://trio-asyncio.readthedocs.io/en/latest/>`__ to implement one async
library on top of another, then you can set and restore :data:`thread_local.name`
around each task step (call to a coroutine object ``send()``, ``throw()``, or
``close()`` method) into the 'inner' library. For example, trio-asyncio does
something like:
<https://trio-asyncio.readthedocs.io/en/latest/>`__ to implement one
async library on top of another, then you can set and restore
:data:`thread_local.name` around each synchronous call that might
execute user code on behalf of the 'inner' library.
For example, trio-asyncio does something like:

.. code-block:: python3
from sniffio import thread_local as sniffio_loop
from sniffio import thread_local as sniffio_library
# Your library's compatibility loop
async def main_loop(self, ...) -> None:
...
handle: asyncio.Handle = await self.get_next_handle()
old_name, sniffio_loop.name = sniffio_loop.name, "asyncio"
old_name, sniffio_library.name = sniffio_library.name, "asyncio"
try:
result = handle._callback(obj._args)
finally:
sniffio_loop.name = old_name
sniffio_library.name = old_name
**Step 3:** Send us a PR to add your library to the list of supported
libraries above.
Expand Down
15 changes: 2 additions & 13 deletions sniffio/_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,8 @@ async def generic_sleep(seconds):
# Need to sniff for asyncio
if "asyncio" in sys.modules:
import asyncio
try:
test: Callable[
[], object
] = asyncio._get_running_loop # type: ignore[attr-defined]
except AttributeError:
# 3.6 doesn't have _get_running_loop, so we can only detect
# asyncio if we're inside a task (as opposed to a callback)
test = asyncio.Task.current_task # type: ignore[attr-defined]
try:
if test() is not None:
return "asyncio"
except RuntimeError:
pass
if asyncio._get_running_loop() is not None:
return "asyncio"

# Sniff for curio (for now)
if 'curio' in sys.modules:
Expand Down
3 changes: 2 additions & 1 deletion sniffio/_tests/test_sniffio.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ async def this_is_asyncio():
# 3.12 error is from importing a private name that no longer exists in the
# multiprocessing module; unclear if it's going to be fixed or not.
@pytest.mark.skipif(
(os.name == "nt" and sys.version_info >= (3, 9)) or sys.version_info >= (3, 12),
(os.name == "nt" and sys.version_info >= (3, 9))
or sys.version_info >= (3, 12),
reason="Curio breaks on Python 3.9+ on Windows and 3.12+ everywhere",
)
def test_curio():
Expand Down

0 comments on commit 852561d

Please sign in to comment.