1From 572db464d3b5123e433759411a0c8796ea9fb5c9 Mon Sep 17 00:00:00 2001 2From: Andrew Svetlov <andrew.svetlov@gmail.com> 3Date: Sun, 29 Nov 2020 15:12:15 +0200 4Subject: [PATCH] Bump async-timeout version for aiohttp 3.8 (#5299) 5 6Signed-off-by: James Hilliard <james.hilliard1@gmail.com> 7[james.hilliard1@gmail.com: backport from upstream commit 81e6ec85e709db083d240c5ca249660d0fa56c61c] 9--- 10 aiohttp/client.py | 4 +-- 11 aiohttp/client_ws.py | 6 ++-- 12 aiohttp/connector.py | 15 ++++++--- 13 aiohttp/helpers.py | 25 ++++++--------- 14 aiohttp/web_protocol.py | 6 ++-- 15 aiohttp/web_ws.py | 6 ++-- 16 setup.py | 2 +- 17 tests/test_client_ws_functional.py | 2 +- 18 tests/test_helpers.py | 49 +++++++----------------------- 19 10 files changed, 44 insertions(+), 73 deletions(-) 20 21diff --git a/aiohttp/client.py b/aiohttp/client.py 22index a9da8e15..2c87eb52 100644 23--- a/aiohttp/client.py 24+++ b/aiohttp/client.py 25@@ -74,8 +74,8 @@ from .helpers import ( 26 DEBUG, 27 PY_36, 28 BasicAuth, 29- CeilTimeout, 30 TimeoutHandle, 31+ ceil_timeout, 32 get_running_loop, 33 proxies_from_env, 34 sentinel, 35@@ -515,7 +515,7 @@ class ClientSession: 36 37 # connection timeout 38 try: 39- with CeilTimeout(real_timeout.connect, loop=self._loop): 40+ async with ceil_timeout(real_timeout.connect): 41 assert self._connector is not None 42 conn = await self._connector.connect( 43 req, traces=traces, timeout=real_timeout 44diff --git a/aiohttp/client_ws.py b/aiohttp/client_ws.py 45index 28fa371c..a4c7371f 100644 46--- a/aiohttp/client_ws.py 47+++ b/aiohttp/client_ws.py 48@@ -191,7 +191,7 @@ class ClientWebSocketResponse: 49 50 while True: 51 try: 52- with async_timeout.timeout(self._timeout, loop=self._loop): 53+ async with async_timeout.timeout(self._timeout): 54 msg = await self._reader.read() 55 except asyncio.CancelledError: 56 self._close_code = 1006 57@@ -224,9 +224,7 @@ class ClientWebSocketResponse: 58 try: 59 self._waiting = self._loop.create_future() 60 try: 61- with async_timeout.timeout( 62- timeout or self._receive_timeout, loop=self._loop 63- ): 64+ async with async_timeout.timeout(timeout or self._receive_timeout): 65 msg = await self._reader.read() 66 self._reset_heartbeat() 67 finally: 68diff --git a/aiohttp/connector.py b/aiohttp/connector.py 69index 748b22a4..77a4f379 100644 70--- a/aiohttp/connector.py 71+++ b/aiohttp/connector.py 72@@ -44,7 +44,14 @@ from .client_exceptions import ( 73 ) 74 from .client_proto import ResponseHandler 75 from .client_reqrep import ClientRequest, Fingerprint, _merge_ssl_params 76-from .helpers import PY_36, CeilTimeout, get_running_loop, is_ip_address, noop, sentinel 77+from .helpers import ( 78+ PY_36, 79+ ceil_timeout, 80+ get_running_loop, 81+ is_ip_address, 82+ noop, 83+ sentinel, 84+) 85 from .http import RESPONSES 86 from .locks import EventResultOrError 87 from .resolver import DefaultResolver 88@@ -965,7 +972,7 @@ class TCPConnector(BaseConnector): 89 **kwargs: Any, 90 ) -> Tuple[asyncio.Transport, ResponseHandler]: 91 try: 92- with CeilTimeout(timeout.sock_connect): 93+ async with ceil_timeout(timeout.sock_connect): 94 return await self._loop.create_connection(*args, **kwargs) # type: ignore # noqa 95 except cert_errors as exc: 96 raise ClientConnectorCertificateError(req.connection_key, exc) from exc 97@@ -1189,7 +1196,7 @@ class UnixConnector(BaseConnector): 98 self, req: "ClientRequest", traces: List["Trace"], timeout: "ClientTimeout" 99 ) -> ResponseHandler: 100 try: 101- with CeilTimeout(timeout.sock_connect): 102+ async with ceil_timeout(timeout.sock_connect): 103 _, proto = await self._loop.create_unix_connection( 104 self._factory, self._path 105 ) 106@@ -1245,7 +1252,7 @@ class NamedPipeConnector(BaseConnector): 107 self, req: "ClientRequest", traces: List["Trace"], timeout: "ClientTimeout" 108 ) -> ResponseHandler: 109 try: 110- with CeilTimeout(timeout.sock_connect): 111+ async with ceil_timeout(timeout.sock_connect): 112 _, proto = await self._loop.create_pipe_connection( # type: ignore 113 self._factory, self._path 114 ) 115diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py 116index bbf5f129..a6b14025 100644 117--- a/aiohttp/helpers.py 118+++ b/aiohttp/helpers.py 119@@ -664,21 +664,16 @@ class TimerContext(BaseTimerContext): 120 self._cancelled = True 121 122 123-class CeilTimeout(async_timeout.timeout): 124- def __enter__(self) -> async_timeout.timeout: 125- if self._timeout is not None: 126- self._task = current_task(loop=self._loop) 127- if self._task is None: 128- raise RuntimeError( 129- "Timeout context manager should be used inside a task" 130- ) 131- now = self._loop.time() 132- delay = self._timeout 133- when = now + delay 134- if delay > 5: 135- when = ceil(when) 136- self._cancel_handler = self._loop.call_at(when, self._cancel_task) 137- return self 138+def ceil_timeout(delay: Optional[float]) -> async_timeout.Timeout: 139+ if delay is None: 140+ return async_timeout.timeout(None) 141+ else: 142+ loop = get_running_loop() 143+ now = loop.time() 144+ when = now + delay 145+ if delay > 5: 146+ when = ceil(when) 147+ return async_timeout.timeout_at(when) 148 149 150 class HeadersMixin: 151diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py 152index 8e02bc4a..16f4d4ef 100644 153--- a/aiohttp/web_protocol.py 154+++ b/aiohttp/web_protocol.py 155@@ -13,7 +13,7 @@ import yarl 156 157 from .abc import AbstractAccessLogger, AbstractStreamWriter 158 from .base_protocol import BaseProtocol 159-from .helpers import CeilTimeout, current_task 160+from .helpers import ceil_timeout, current_task 161 from .http import ( 162 HttpProcessingError, 163 HttpRequestParser, 164@@ -228,7 +228,7 @@ class RequestHandler(BaseProtocol): 165 166 # wait for handlers 167 with suppress(asyncio.CancelledError, asyncio.TimeoutError): 168- with CeilTimeout(timeout, loop=self._loop): 169+ async with ceil_timeout(timeout): 170 if self._error_handler is not None and not self._error_handler.done(): 171 await self._error_handler 172 173@@ -517,7 +517,7 @@ class RequestHandler(BaseProtocol): 174 175 with suppress(asyncio.TimeoutError, asyncio.CancelledError): 176 while not payload.is_eof() and now < end_t: 177- with CeilTimeout(end_t - now, loop=loop): 178+ async with ceil_timeout(end_t - now): 179 # read and ignore 180 await payload.readany() 181 now = loop.time() 182diff --git a/aiohttp/web_ws.py b/aiohttp/web_ws.py 183index da7ce6df..5f3cce56 100644 184--- a/aiohttp/web_ws.py 185+++ b/aiohttp/web_ws.py 186@@ -359,7 +359,7 @@ class WebSocketResponse(StreamResponse): 187 reader = self._reader 188 assert reader is not None 189 try: 190- with async_timeout.timeout(self._timeout, loop=self._loop): 191+ async with async_timeout.timeout(self._timeout): 192 msg = await reader.read() 193 except asyncio.CancelledError: 194 self._close_code = 1006 195@@ -400,9 +400,7 @@ class WebSocketResponse(StreamResponse): 196 try: 197 self._waiting = loop.create_future() 198 try: 199- with async_timeout.timeout( 200- timeout or self._receive_timeout, loop=self._loop 201- ): 202+ async with async_timeout.timeout(timeout or self._receive_timeout): 203 msg = await self._reader.read() 204 self._reset_heartbeat() 205 finally: 206diff --git a/setup.py b/setup.py 207index 54462ba7..c262de1e 100644 208--- a/setup.py 209+++ b/setup.py 210@@ -68,7 +68,7 @@ install_requires = [ 211 "attrs>=17.3.0", 212 "chardet>=2.0,<5.0", 213 "multidict>=4.5,<7.0", 214- "async_timeout>=3.0,<4.0", 215+ "async_timeout>=4.0.0a3,<5.0", 216 "yarl>=1.0,<2.0", 217 'idna-ssl>=1.0; python_version<"3.7"', 218 "typing_extensions>=3.6.5", 219diff --git a/tests/test_client_ws_functional.py b/tests/test_client_ws_functional.py 220index e423765a..76ef0525 100644 221--- a/tests/test_client_ws_functional.py 222+++ b/tests/test_client_ws_functional.py 223@@ -461,7 +461,7 @@ async def test_recv_timeout(aiohttp_client) -> None: 224 await resp.send_str("ask") 225 226 with pytest.raises(asyncio.TimeoutError): 227- with async_timeout.timeout(0.01): 228+ async with async_timeout.timeout(0.01): 229 await resp.receive() 230 231 await resp.close() 232diff --git a/tests/test_helpers.py b/tests/test_helpers.py 233index 3367c24b..d36c7e4c 100644 234--- a/tests/test_helpers.py 235+++ b/tests/test_helpers.py 236@@ -3,7 +3,6 @@ import base64 237 import gc 238 import os 239 import platform 240-import sys 241 import tempfile 242 from math import isclose, modf 243 from unittest import mock 244@@ -391,48 +390,22 @@ async def test_weakref_handle_weak(loop) -> None: 245 await asyncio.sleep(0.1) 246 247 248-def test_ceil_call_later() -> None: 249- cb = mock.Mock() 250- loop = mock.Mock() 251- loop.time.return_value = 10.1 252- helpers.call_later(cb, 10.1, loop) 253- loop.call_at.assert_called_with(21.0, cb) 254- 255- 256-def test_ceil_call_later_no_timeout() -> None: 257- cb = mock.Mock() 258- loop = mock.Mock() 259- helpers.call_later(cb, 0, loop) 260- assert not loop.call_at.called 261- 262- 263-async def test_ceil_timeout(loop) -> None: 264- with helpers.CeilTimeout(None, loop=loop) as timeout: 265- assert timeout._timeout is None 266- assert timeout._cancel_handler is None 267+async def test_ceil_timeout() -> None: 268+ async with helpers.ceil_timeout(None) as timeout: 269+ assert timeout.deadline is None 270 271 272-def test_ceil_timeout_no_task(loop) -> None: 273- with pytest.raises(RuntimeError): 274- with helpers.CeilTimeout(10, loop=loop): 275- pass 276- 277- 278-@pytest.mark.skipif( 279- sys.version_info < (3, 7), reason="TimerHandle.when() doesn't exist" 280-) 281-async def test_ceil_timeout_round(loop) -> None: 282- with helpers.CeilTimeout(7.5, loop=loop) as cm: 283- frac, integer = modf(cm._cancel_handler.when()) 284+async def test_ceil_timeout_round() -> None: 285+ async with helpers.ceil_timeout(7.5) as cm: 286+ assert cm.deadline is not None 287+ frac, integer = modf(cm.deadline) 288 assert frac == 0 289 290 291-@pytest.mark.skipif( 292- sys.version_info < (3, 7), reason="TimerHandle.when() doesn't exist" 293-) 294-async def test_ceil_timeout_small(loop) -> None: 295- with helpers.CeilTimeout(1.1, loop=loop) as cm: 296- frac, integer = modf(cm._cancel_handler.when()) 297+async def test_ceil_timeout_small() -> None: 298+ async with helpers.ceil_timeout(1.1) as cm: 299+ assert cm.deadline is not None 300+ frac, integer = modf(cm.deadline) 301 # a chance for exact integer with zero fraction is negligible 302 assert frac != 0 303 304-- 3052.25.1 306 307