diff --git a/newsfragments/51.bugfix.rst b/newsfragments/51.bugfix.rst new file mode 100644 index 0000000..8677649 --- /dev/null +++ b/newsfragments/51.bugfix.rst @@ -0,0 +1,4 @@ +``current_async_library`` now reports ``asyncio`` when an event loop is +running but there is no current Task, such as in ``call_soon`` callbacks +and Twisted's asyncioreactor. Detection uses ``asyncio.get_running_loop()`` +only; ``current_task()`` is a slower subset of the same check. diff --git a/sniffio/_impl.py b/sniffio/_impl.py index c1a7bbf..64d311e 100644 --- a/sniffio/_impl.py +++ b/sniffio/_impl.py @@ -75,14 +75,11 @@ async def generic_sleep(seconds): 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" + asyncio.get_running_loop() except RuntimeError: pass + else: + return "asyncio" # Sniff for curio (for now) if 'curio' in sys.modules: diff --git a/sniffio/_tests/test_sniffio.py b/sniffio/_tests/test_sniffio.py index 02945a9..a99f5e8 100644 --- a/sniffio/_tests/test_sniffio.py +++ b/sniffio/_tests/test_sniffio.py @@ -58,6 +58,27 @@ async def this_is_asyncio(): current_async_library() +def test_asyncio_running_loop_without_task(): + import asyncio + + result = [] + + def sync_cb(): + try: + result.append(current_async_library()) + finally: + loop.stop() + + loop = asyncio.new_event_loop() + try: + loop.call_soon(sync_cb) + loop.run_forever() + finally: + loop.close() + + assert result == ["asyncio"] + + @pytest.mark.skipif( sys.version_info >= (3, 12), reason=