]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Add PoolTimeout, and timeout tests 7/head
authorTom Christie <tom@tomchristie.com>
Wed, 17 Apr 2019 16:38:03 +0000 (17:38 +0100)
committerTom Christie <tom@tomchristie.com>
Wed, 17 Apr 2019 16:38:03 +0000 (17:38 +0100)
httpcore/__init__.py
httpcore/compat.py
httpcore/pool.py
tests/conftest.py
tests/test_timeouts.py [new file with mode: 0644]

index 6630a361625ec845d033756c139d94e978f62570..7675068c10efcefd974b33e891615c1e3c207bd6 100644 (file)
@@ -1,6 +1,13 @@
 from .config import PoolLimits, SSLConfig, TimeoutConfig
 from .datastructures import URL, Request, Response
-from .exceptions import ResponseClosed, StreamConsumed
+from .exceptions import (
+    ConnectTimeout,
+    PoolTimeout,
+    ReadTimeout,
+    ResponseClosed,
+    StreamConsumed,
+    Timeout,
+)
 from .pool import ConnectionPool
 
 __version__ = "0.0.3"
index 5369c5e8d8a7a946bb77e045bb26b32c5a592e7e..794cf6f19035ca373e9c7a377ffb6fefdacc623d 100644 (file)
@@ -1,4 +1,4 @@
 try:
     import brotli
-except ImportError:
-    brotli = None  # pragma: nocover
+except ImportError:  # pragma: nocover
+    brotli = None
index fcec56ea4c3170eb15b884b683e038898ee119b4..39216c3dff7c82d7b06eebd5092079f09bb06328 100644 (file)
@@ -16,18 +16,23 @@ from .config import (
 )
 from .connections import Connection
 from .datastructures import URL, Request, Response
+from .exceptions import PoolTimeout
 
 ConnectionKey = typing.Tuple[str, str, int]  # (scheme, host, port)
 
 
 class ConnectionSemaphore:
-    def __init__(self, max_connections: int = None):
+    def __init__(self, max_connections: int = None, timeout: float = None):
+        self.timeout = timeout
         if max_connections is not None:
             self.semaphore = asyncio.BoundedSemaphore(value=max_connections)
 
     async def acquire(self) -> None:
         if hasattr(self, "semaphore"):
-            await self.semaphore.acquire()
+            try:
+                await asyncio.wait_for(self.semaphore.acquire(), self.timeout)
+            except asyncio.TimeoutError:
+                raise PoolTimeout()
 
     def release(self) -> None:
         if hasattr(self, "semaphore"):
@@ -52,7 +57,7 @@ class ConnectionPool:
             {}
         )  # type: typing.Dict[ConnectionKey, typing.List[Connection]]
         self._connection_semaphore = ConnectionSemaphore(
-            max_connections=self.limits.hard_limit
+            max_connections=self.limits.hard_limit, timeout=self.timeout.pool_timeout
         )
 
     async def request(
index efb79df195cd1383eac1dba70a09cf5d4334a13b..3ceaeec0419969f76891a82ac941cf9678fd15b9 100644 (file)
@@ -7,6 +7,25 @@ from uvicorn.main import Server
 
 async def app(scope, receive, send):
     assert scope["type"] == "http"
+    if scope["path"] == "/slow_response":
+        await slow_response(scope, receive, send)
+    else:
+        await hello_world(scope, receive, send)
+
+
+async def hello_world(scope, receive, send):
+    await send(
+        {
+            "type": "http.response.start",
+            "status": 200,
+            "headers": [[b"content-type", b"text/plain"]],
+        }
+    )
+    await send({"type": "http.response.body", "body": b"Hello, world!"})
+
+
+async def slow_response(scope, receive, send):
+    await asyncio.sleep(0.01)
     await send(
         {
             "type": "http.response.start",
@@ -28,5 +47,4 @@ async def server():
         yield server
     finally:
         server.should_exit = True
-        server.force_exit = True
         await task
diff --git a/tests/test_timeouts.py b/tests/test_timeouts.py
new file mode 100644 (file)
index 0000000..61ce9a1
--- /dev/null
@@ -0,0 +1,26 @@
+import pytest
+
+import httpcore
+
+
+@pytest.mark.asyncio
+async def test_read_timeout(server):
+    timeout = httpcore.TimeoutConfig(read_timeout=0.0001)
+
+    async with httpcore.ConnectionPool(timeout=timeout) as http:
+        with pytest.raises(httpcore.ReadTimeout):
+            await http.request("GET", "http://127.0.0.1:8000/slow_response")
+
+
+@pytest.mark.asyncio
+async def test_pool_timeout(server):
+    timeout = httpcore.TimeoutConfig(pool_timeout=0.0001)
+    limits = httpcore.PoolLimits(hard_limit=1)
+
+    async with httpcore.ConnectionPool(timeout=timeout, limits=limits) as http:
+        response = await http.request("GET", "http://127.0.0.1:8000/", stream=True)
+
+        with pytest.raises(httpcore.PoolTimeout):
+            await http.request("GET", "http://localhost:8000/")
+
+        await response.read()