]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Remove usage of loop.create_task in ASGIDispatch (#261)
authorFlorimond Manca <florimond.manca@gmail.com>
Wed, 21 Aug 2019 21:11:12 +0000 (23:11 +0200)
committerGitHub <noreply@github.com>
Wed, 21 Aug 2019 21:11:12 +0000 (23:11 +0200)
* Remove usage of loop.create_task in ASGIDispatch

* Add comment about usage of background manager

* Update comment

httpx/concurrency/asyncio.py
httpx/concurrency/base.py
httpx/dispatch/asgi.py
httpx/dispatch/http11.py
httpx/dispatch/http2.py

index 34d68c38304b170001a3f5a1a43501e239da2497..9b9778326627991d85caeabdd8580aeefb45f556 100644 (file)
@@ -223,7 +223,7 @@ class AsyncioBackend(ConcurrencyBackend):
         return typing.cast(BaseEvent, asyncio.Event())
 
     def background_manager(
-        self, coroutine: typing.Callable, args: typing.Any
+        self, coroutine: typing.Callable, *args: typing.Any
     ) -> "BackgroundManager":
         return BackgroundManager(coroutine, args)
 
index 45785df1c39fa31f45ab2cdd7b54e032fc045ed7..9bfd54d4a48a2685cbd675fd3b43a8647ca7eb9b 100644 (file)
@@ -159,7 +159,7 @@ class ConcurrencyBackend:
         raise NotImplementedError()  # pragma: no cover
 
     def background_manager(
-        self, coroutine: typing.Callable, args: typing.Any
+        self, coroutine: typing.Callable, *args: typing.Any
     ) -> "BaseBackgroundManager":
         raise NotImplementedError()  # pragma: no cover
 
index 589bf8c832af611c0df2bf46de9ebe74bc7eae9d..4e3f3dcd8c6bf086e37182657b2befcc94a01a7e 100644 (file)
@@ -1,4 +1,3 @@
-import asyncio
 import typing
 
 from .base import AsyncDispatcher
@@ -121,13 +120,12 @@ class ASGIDispatch(AsyncDispatcher):
                 await response_body.mark_as_done()
                 response_started_or_failed.set()
 
-        # Really we'd like to push all `asyncio` logic into concurrency.py,
-        # with a standardized interface, so that we can support other event
-        # loop implementations, such as Trio and Curio.
-        # That's a bit fiddly here, so we're not yet supporting using a custom
-        # `ConcurrencyBackend` with the `Client(app=asgi_app)` case.
-        loop = asyncio.get_event_loop()
-        app_task = loop.create_task(run_app())
+        # Using the background manager here *works*, but it is weak design because
+        # the background task isn't strictly context-managed.
+        # We could consider refactoring the other uses of this abstraction
+        # (mainly sending/receiving request/response data in h11 and h2 dispatchers),
+        # and see if that allows us to come back here and refactor things out.
+        background = await self.backend.background_manager(run_app).__aenter__()
 
         await response_started_or_failed.wait()
 
@@ -138,9 +136,9 @@ class ASGIDispatch(AsyncDispatcher):
         assert headers is not None
 
         async def on_close() -> None:
-            nonlocal app_task, response_body
+            nonlocal response_body
             await response_body.drain()
-            await app_task
+            await background.__aexit__(None, None, None)
             if app_exc is not None and self.raise_app_exceptions:
                 raise app_exc
 
index 236c81e2bbe68560c2675526d280f88463ab1efc..a54a8d4d8f6262c8f4324eb8c7502b219cd3a2a0 100644 (file)
@@ -45,7 +45,7 @@ class HTTP11Connection:
         await self._send_request(request, timeout)
 
         task, args = self._send_request_data, [request.stream(), timeout]
-        async with self.backend.background_manager(task, args=args):
+        async with self.backend.background_manager(task, *args):
             http_version, status_code, headers = await self._receive_response(timeout)
         content = self._receive_response_data(timeout)
 
index 0a698f35f4133a716ed83a40a8621b4fc1169af3..f0ea1588362a77f19446683990208813fd821a2c 100644 (file)
@@ -41,7 +41,7 @@ class HTTP2Connection:
         self.timeout_flags[stream_id] = TimeoutFlag()
 
         task, args = self.send_request_data, [stream_id, request.stream(), timeout]
-        async with self.backend.background_manager(task, args=args):
+        async with self.backend.background_manager(task, *args):
             status_code, headers = await self.receive_response(stream_id, timeout)
         content = self.body_iter(stream_id, timeout)
         on_close = functools.partial(self.response_closed, stream_id=stream_id)