From 2204b5212dd309d50a6801db28575163f8a10ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Wed, 25 Dec 2019 13:38:06 +0200 Subject: [PATCH 1/5] Added detection for Twisted --- sniffio/_impl.py | 12 ++++++++++++ sniffio/_tests/test_sniffio.py | 23 +++++++++++++++++++++++ test-requirements.txt | 1 + 3 files changed, 36 insertions(+) diff --git a/sniffio/_impl.py b/sniffio/_impl.py index febed65..12d6456 100644 --- a/sniffio/_impl.py +++ b/sniffio/_impl.py @@ -77,6 +77,18 @@ async def generic_sleep(seconds): return "asyncio" except RuntimeError: pass + + if "twisted.internet" in sys.modules: + from traceback import walk_stack + from twisted.internet import reactor + + # Check if the reactor is running in this thread + if reactor.running: + for frame, lineno in walk_stack(sys._getframe(2)): + if frame.f_code.co_name == 'run': + if frame.f_code.co_filename.endswith('twisted/internet/base.py'): + return "twisted" + raise AsyncLibraryNotFoundError( "unknown async library, or not in async context" ) diff --git a/sniffio/_tests/test_sniffio.py b/sniffio/_tests/test_sniffio.py index 4425ea1..641316a 100644 --- a/sniffio/_tests/test_sniffio.py +++ b/sniffio/_tests/test_sniffio.py @@ -62,3 +62,26 @@ async def this_is_curio(): with pytest.raises(AsyncLibraryNotFoundError): current_async_library() + + +def test_twisted(): + from twisted.internet import reactor + + with pytest.raises(AsyncLibraryNotFoundError): + current_async_library() + + ran = [] + + def this_is_twisted(): + try: + assert current_async_library() == "twisted" + ran.append(True) + finally: + reactor.stop() + + reactor.callWhenRunning(this_is_twisted) + reactor.run() + assert ran == [True] + + with pytest.raises(AsyncLibraryNotFoundError): + current_async_library() diff --git a/test-requirements.txt b/test-requirements.txt index 6742196..29af8d8 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,4 @@ pytest pytest-cov curio +twisted From fe2930f68427b35f3c5d2875f1bf2fb557bc40f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Wed, 25 Dec 2019 13:49:07 +0200 Subject: [PATCH 2/5] Added a news fragment --- newsfragments/10.feature.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 newsfragments/10.feature.rst diff --git a/newsfragments/10.feature.rst b/newsfragments/10.feature.rst new file mode 100644 index 0000000..1749fa0 --- /dev/null +++ b/newsfragments/10.feature.rst @@ -0,0 +1,3 @@ +Sniffio can now detect Twisted_. + +.. _Twisted: https://twistedmatrix.com/trac/ From 95e506cc34b756a93d30b058fde54c79d4125e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Thu, 26 Dec 2019 12:21:38 +0200 Subject: [PATCH 3/5] Fixed code style --- sniffio/_impl.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sniffio/_impl.py b/sniffio/_impl.py index 12d6456..47e7e75 100644 --- a/sniffio/_impl.py +++ b/sniffio/_impl.py @@ -86,7 +86,8 @@ async def generic_sleep(seconds): if reactor.running: for frame, lineno in walk_stack(sys._getframe(2)): if frame.f_code.co_name == 'run': - if frame.f_code.co_filename.endswith('twisted/internet/base.py'): + if frame.f_code.co_filename.endswith( + 'twisted/internet/base.py'): return "twisted" raise AsyncLibraryNotFoundError( From 2fa6804bd62bdae5520f4be932260ae8f55141ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Sat, 28 Dec 2019 14:50:42 +0200 Subject: [PATCH 4/5] Suppressed attrs deprecation warning --- sniffio/_tests/test_sniffio.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sniffio/_tests/test_sniffio.py b/sniffio/_tests/test_sniffio.py index 641316a..2476a15 100644 --- a/sniffio/_tests/test_sniffio.py +++ b/sniffio/_tests/test_sniffio.py @@ -1,3 +1,5 @@ +import warnings + import pytest from .. import ( @@ -65,7 +67,9 @@ async def this_is_curio(): def test_twisted(): - from twisted.internet import reactor + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + from twisted.internet import reactor with pytest.raises(AsyncLibraryNotFoundError): current_async_library() From 4c01e9b370d11f657627af9f34b69e1dcf33fce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Sat, 28 Dec 2019 14:51:42 +0200 Subject: [PATCH 5/5] Used isInIOThread to detect Twisted --- sniffio/_impl.py | 19 +++++++------------ sniffio/_tests/test_sniffio.py | 23 +++++++++++++++++++++-- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/sniffio/_impl.py b/sniffio/_impl.py index 47e7e75..05e890a 100644 --- a/sniffio/_impl.py +++ b/sniffio/_impl.py @@ -55,6 +55,13 @@ async def generic_sleep(seconds): if value is not None: return value + # Sniff for Twisted + if 'twisted' in sys.modules: + from twisted.internet import reactor + from twisted.python.threadable import isInIOThread + if reactor.running and isInIOThread(): + return "twisted" + # Sniff for curio (for now) if 'curio' in sys.modules: from curio.meta import curio_running @@ -78,18 +85,6 @@ async def generic_sleep(seconds): except RuntimeError: pass - if "twisted.internet" in sys.modules: - from traceback import walk_stack - from twisted.internet import reactor - - # Check if the reactor is running in this thread - if reactor.running: - for frame, lineno in walk_stack(sys._getframe(2)): - if frame.f_code.co_name == 'run': - if frame.f_code.co_filename.endswith( - 'twisted/internet/base.py'): - return "twisted" - raise AsyncLibraryNotFoundError( "unknown async library, or not in async context" ) diff --git a/sniffio/_tests/test_sniffio.py b/sniffio/_tests/test_sniffio.py index 2476a15..b037c98 100644 --- a/sniffio/_tests/test_sniffio.py +++ b/sniffio/_tests/test_sniffio.py @@ -1,3 +1,4 @@ +import sys import warnings import pytest @@ -66,10 +67,28 @@ async def this_is_curio(): current_async_library() -def test_twisted(): +@pytest.fixture(params=['select', 'asyncio']) +def reactor(request): with warnings.catch_warnings(): warnings.simplefilter('ignore', DeprecationWarning) - from twisted.internet import reactor + from twisted.internet import asyncioreactor, selectreactor + + if request.param == 'asyncio': + import asyncio + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + asyncioreactor.install(loop) + yield + loop.close() + else: + selectreactor.install() + yield + + del sys.modules['twisted.internet.reactor'] + + +def test_twisted(reactor): + from twisted.internet import reactor with pytest.raises(AsyncLibraryNotFoundError): current_async_library()