From a78cfb38a0c0f6031cc3ff39ff8bf4afd03ef008 Mon Sep 17 00:00:00 2001 From: Vytautas Liuolia Date: Thu, 21 Mar 2024 20:59:26 +0100 Subject: [PATCH] chore(sync): use `asyncio.Runner` for `async_to_sync()` on py311+ (#2216) * chore(asyncio): replace `get_event_loop()` -> `get_running_loop()` where applicable * chore(sync): use `asyncio.Runner` for `async_to_sync()` on py311+ * chore(sync): exempt a line from coverage as it can only be hit on 3.11+ * chore(tests/asgi): adapt to Uvicorn now propagating signals to retcode * chore(tests/asgi): do not check ASGI server retcode on Windows * chore(tests/asgi): check for a M$ Windows specific exit code constant * chore(sync): use a nicer pattern to get the active runner --- falcon/util/sync.py | 60 ++++++++++++++++++++++++--------- pyproject.toml | 1 - tests/asgi/test_asgi_servers.py | 10 ++++-- tests/asgi/test_scope.py | 6 ++-- tests/dump_asgi.py | 2 +- 5 files changed, 56 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ad445ce55..5ed0c5fab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,7 +97,6 @@ filterwarnings = [ "ignore:.cgi. is deprecated and slated for removal:DeprecationWarning", "ignore:path is deprecated\\. Use files\\(\\) instead:DeprecationWarning", "ignore:This process \\(.+\\) is multi-threaded", - "ignore:There is no current event loop", ] testpaths = [ "tests" diff --git a/tests/asgi/test_asgi_servers.py b/tests/asgi/test_asgi_servers.py index 26f51ad0c..321e41f96 100644 --- a/tests/asgi/test_asgi_servers.py +++ b/tests/asgi/test_asgi_servers.py @@ -4,6 +4,7 @@ import os import platform import random +import signal import subprocess import sys import time @@ -27,7 +28,9 @@ _SERVER_HOST = '127.0.0.1' _SIZE_1_KB = 1024 _SIZE_1_MB = _SIZE_1_KB**2 - +# NOTE(vytas): Windows specific: {Application Exit by CTRL+C}. +# The application terminated as a result of a CTRL+C. +_STATUS_CONTROL_C_EXIT = 0xC000013A _REQUEST_TIMEOUT = 10 @@ -620,7 +623,10 @@ def server_base_url(request): yield base_url - assert server.returncode == 0 + # NOTE(vytas): Starting with 0.29.0, Uvicorn will propagate signal + # values into the return code (which is a good practice in Unix); + # see also https://github.com/encode/uvicorn/pull/1600 + assert server.returncode in (0, -signal.SIGTERM, _STATUS_CONTROL_C_EXIT) break diff --git a/tests/asgi/test_scope.py b/tests/asgi/test_scope.py index bb60ed0e7..e368f6576 100644 --- a/tests/asgi/test_scope.py +++ b/tests/asgi/test_scope.py @@ -70,7 +70,7 @@ def test_supported_asgi_version(version, supported): resp_event_collector = testing.ASGIResponseEventCollector() async def task(): - coro = asyncio.get_event_loop().create_task( + coro = asyncio.get_running_loop().create_task( app(scope, req_event_emitter, resp_event_collector) ) @@ -142,7 +142,7 @@ def test_lifespan_scope_default_version(): scope = {'type': 'lifespan'} async def t(): - t = asyncio.get_event_loop().create_task( + t = asyncio.get_running_loop().create_task( app(scope, req_event_emitter, resp_event_collector) ) @@ -196,7 +196,7 @@ def test_lifespan_scope_version(spec_version, supported): return async def t(): - t = asyncio.get_event_loop().create_task( + t = asyncio.get_running_loop().create_task( app(scope, req_event_emitter, resp_event_collector) ) diff --git a/tests/dump_asgi.py b/tests/dump_asgi.py index 0742a3ca0..0dfdb4b0a 100644 --- a/tests/dump_asgi.py +++ b/tests/dump_asgi.py @@ -23,5 +23,5 @@ async def app(scope, receive, send): } ) - loop = asyncio.get_event_loop() + loop = asyncio.get_running_loop() loop.create_task(_say_hi())