|
@@ -0,0 +1,306 @@
|
|
|
+From 572db464d3b5123e433759411a0c8796ea9fb5c9 Mon Sep 17 00:00:00 2001
|
|
|
+From: Andrew Svetlov <andrew.svetlov@gmail.com>
|
|
|
+Date: Sun, 29 Nov 2020 15:12:15 +0200
|
|
|
+Subject: [PATCH] Bump async-timeout version for aiohttp 3.8 (#5299)
|
|
|
+
|
|
|
+Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
|
|
|
+[james.hilliard1@gmail.com: backport from upstream commit
|
|
|
+1e6ec85e709db083d240c5ca249660d0fa56c61c]
|
|
|
+---
|
|
|
+ aiohttp/client.py | 4 +--
|
|
|
+ aiohttp/client_ws.py | 6 ++--
|
|
|
+ aiohttp/connector.py | 15 ++++++---
|
|
|
+ aiohttp/helpers.py | 25 ++++++---------
|
|
|
+ aiohttp/web_protocol.py | 6 ++--
|
|
|
+ aiohttp/web_ws.py | 6 ++--
|
|
|
+ setup.py | 2 +-
|
|
|
+ tests/test_client_ws_functional.py | 2 +-
|
|
|
+ tests/test_helpers.py | 49 +++++++-----------------------
|
|
|
+ 10 files changed, 44 insertions(+), 73 deletions(-)
|
|
|
+
|
|
|
+diff --git a/aiohttp/client.py b/aiohttp/client.py
|
|
|
+index a9da8e15..2c87eb52 100644
|
|
|
+--- a/aiohttp/client.py
|
|
|
++++ b/aiohttp/client.py
|
|
|
+@@ -74,8 +74,8 @@ from .helpers import (
|
|
|
+ DEBUG,
|
|
|
+ PY_36,
|
|
|
+ BasicAuth,
|
|
|
+- CeilTimeout,
|
|
|
+ TimeoutHandle,
|
|
|
++ ceil_timeout,
|
|
|
+ get_running_loop,
|
|
|
+ proxies_from_env,
|
|
|
+ sentinel,
|
|
|
+@@ -515,7 +515,7 @@ class ClientSession:
|
|
|
+
|
|
|
+ # connection timeout
|
|
|
+ try:
|
|
|
+- with CeilTimeout(real_timeout.connect, loop=self._loop):
|
|
|
++ async with ceil_timeout(real_timeout.connect):
|
|
|
+ assert self._connector is not None
|
|
|
+ conn = await self._connector.connect(
|
|
|
+ req, traces=traces, timeout=real_timeout
|
|
|
+diff --git a/aiohttp/client_ws.py b/aiohttp/client_ws.py
|
|
|
+index 28fa371c..a4c7371f 100644
|
|
|
+--- a/aiohttp/client_ws.py
|
|
|
++++ b/aiohttp/client_ws.py
|
|
|
+@@ -191,7 +191,7 @@ class ClientWebSocketResponse:
|
|
|
+
|
|
|
+ while True:
|
|
|
+ try:
|
|
|
+- with async_timeout.timeout(self._timeout, loop=self._loop):
|
|
|
++ async with async_timeout.timeout(self._timeout):
|
|
|
+ msg = await self._reader.read()
|
|
|
+ except asyncio.CancelledError:
|
|
|
+ self._close_code = 1006
|
|
|
+@@ -224,9 +224,7 @@ class ClientWebSocketResponse:
|
|
|
+ try:
|
|
|
+ self._waiting = self._loop.create_future()
|
|
|
+ try:
|
|
|
+- with async_timeout.timeout(
|
|
|
+- timeout or self._receive_timeout, loop=self._loop
|
|
|
+- ):
|
|
|
++ async with async_timeout.timeout(timeout or self._receive_timeout):
|
|
|
+ msg = await self._reader.read()
|
|
|
+ self._reset_heartbeat()
|
|
|
+ finally:
|
|
|
+diff --git a/aiohttp/connector.py b/aiohttp/connector.py
|
|
|
+index 748b22a4..77a4f379 100644
|
|
|
+--- a/aiohttp/connector.py
|
|
|
++++ b/aiohttp/connector.py
|
|
|
+@@ -44,7 +44,14 @@ from .client_exceptions import (
|
|
|
+ )
|
|
|
+ from .client_proto import ResponseHandler
|
|
|
+ from .client_reqrep import ClientRequest, Fingerprint, _merge_ssl_params
|
|
|
+-from .helpers import PY_36, CeilTimeout, get_running_loop, is_ip_address, noop, sentinel
|
|
|
++from .helpers import (
|
|
|
++ PY_36,
|
|
|
++ ceil_timeout,
|
|
|
++ get_running_loop,
|
|
|
++ is_ip_address,
|
|
|
++ noop,
|
|
|
++ sentinel,
|
|
|
++)
|
|
|
+ from .http import RESPONSES
|
|
|
+ from .locks import EventResultOrError
|
|
|
+ from .resolver import DefaultResolver
|
|
|
+@@ -965,7 +972,7 @@ class TCPConnector(BaseConnector):
|
|
|
+ **kwargs: Any,
|
|
|
+ ) -> Tuple[asyncio.Transport, ResponseHandler]:
|
|
|
+ try:
|
|
|
+- with CeilTimeout(timeout.sock_connect):
|
|
|
++ async with ceil_timeout(timeout.sock_connect):
|
|
|
+ return await self._loop.create_connection(*args, **kwargs) # type: ignore # noqa
|
|
|
+ except cert_errors as exc:
|
|
|
+ raise ClientConnectorCertificateError(req.connection_key, exc) from exc
|
|
|
+@@ -1189,7 +1196,7 @@ class UnixConnector(BaseConnector):
|
|
|
+ self, req: "ClientRequest", traces: List["Trace"], timeout: "ClientTimeout"
|
|
|
+ ) -> ResponseHandler:
|
|
|
+ try:
|
|
|
+- with CeilTimeout(timeout.sock_connect):
|
|
|
++ async with ceil_timeout(timeout.sock_connect):
|
|
|
+ _, proto = await self._loop.create_unix_connection(
|
|
|
+ self._factory, self._path
|
|
|
+ )
|
|
|
+@@ -1245,7 +1252,7 @@ class NamedPipeConnector(BaseConnector):
|
|
|
+ self, req: "ClientRequest", traces: List["Trace"], timeout: "ClientTimeout"
|
|
|
+ ) -> ResponseHandler:
|
|
|
+ try:
|
|
|
+- with CeilTimeout(timeout.sock_connect):
|
|
|
++ async with ceil_timeout(timeout.sock_connect):
|
|
|
+ _, proto = await self._loop.create_pipe_connection( # type: ignore
|
|
|
+ self._factory, self._path
|
|
|
+ )
|
|
|
+diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py
|
|
|
+index bbf5f129..a6b14025 100644
|
|
|
+--- a/aiohttp/helpers.py
|
|
|
++++ b/aiohttp/helpers.py
|
|
|
+@@ -664,21 +664,16 @@ class TimerContext(BaseTimerContext):
|
|
|
+ self._cancelled = True
|
|
|
+
|
|
|
+
|
|
|
+-class CeilTimeout(async_timeout.timeout):
|
|
|
+- def __enter__(self) -> async_timeout.timeout:
|
|
|
+- if self._timeout is not None:
|
|
|
+- self._task = current_task(loop=self._loop)
|
|
|
+- if self._task is None:
|
|
|
+- raise RuntimeError(
|
|
|
+- "Timeout context manager should be used inside a task"
|
|
|
+- )
|
|
|
+- now = self._loop.time()
|
|
|
+- delay = self._timeout
|
|
|
+- when = now + delay
|
|
|
+- if delay > 5:
|
|
|
+- when = ceil(when)
|
|
|
+- self._cancel_handler = self._loop.call_at(when, self._cancel_task)
|
|
|
+- return self
|
|
|
++def ceil_timeout(delay: Optional[float]) -> async_timeout.Timeout:
|
|
|
++ if delay is None:
|
|
|
++ return async_timeout.timeout(None)
|
|
|
++ else:
|
|
|
++ loop = get_running_loop()
|
|
|
++ now = loop.time()
|
|
|
++ when = now + delay
|
|
|
++ if delay > 5:
|
|
|
++ when = ceil(when)
|
|
|
++ return async_timeout.timeout_at(when)
|
|
|
+
|
|
|
+
|
|
|
+ class HeadersMixin:
|
|
|
+diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py
|
|
|
+index 8e02bc4a..16f4d4ef 100644
|
|
|
+--- a/aiohttp/web_protocol.py
|
|
|
++++ b/aiohttp/web_protocol.py
|
|
|
+@@ -13,7 +13,7 @@ import yarl
|
|
|
+
|
|
|
+ from .abc import AbstractAccessLogger, AbstractStreamWriter
|
|
|
+ from .base_protocol import BaseProtocol
|
|
|
+-from .helpers import CeilTimeout, current_task
|
|
|
++from .helpers import ceil_timeout, current_task
|
|
|
+ from .http import (
|
|
|
+ HttpProcessingError,
|
|
|
+ HttpRequestParser,
|
|
|
+@@ -228,7 +228,7 @@ class RequestHandler(BaseProtocol):
|
|
|
+
|
|
|
+ # wait for handlers
|
|
|
+ with suppress(asyncio.CancelledError, asyncio.TimeoutError):
|
|
|
+- with CeilTimeout(timeout, loop=self._loop):
|
|
|
++ async with ceil_timeout(timeout):
|
|
|
+ if self._error_handler is not None and not self._error_handler.done():
|
|
|
+ await self._error_handler
|
|
|
+
|
|
|
+@@ -517,7 +517,7 @@ class RequestHandler(BaseProtocol):
|
|
|
+
|
|
|
+ with suppress(asyncio.TimeoutError, asyncio.CancelledError):
|
|
|
+ while not payload.is_eof() and now < end_t:
|
|
|
+- with CeilTimeout(end_t - now, loop=loop):
|
|
|
++ async with ceil_timeout(end_t - now):
|
|
|
+ # read and ignore
|
|
|
+ await payload.readany()
|
|
|
+ now = loop.time()
|
|
|
+diff --git a/aiohttp/web_ws.py b/aiohttp/web_ws.py
|
|
|
+index da7ce6df..5f3cce56 100644
|
|
|
+--- a/aiohttp/web_ws.py
|
|
|
++++ b/aiohttp/web_ws.py
|
|
|
+@@ -359,7 +359,7 @@ class WebSocketResponse(StreamResponse):
|
|
|
+ reader = self._reader
|
|
|
+ assert reader is not None
|
|
|
+ try:
|
|
|
+- with async_timeout.timeout(self._timeout, loop=self._loop):
|
|
|
++ async with async_timeout.timeout(self._timeout):
|
|
|
+ msg = await reader.read()
|
|
|
+ except asyncio.CancelledError:
|
|
|
+ self._close_code = 1006
|
|
|
+@@ -400,9 +400,7 @@ class WebSocketResponse(StreamResponse):
|
|
|
+ try:
|
|
|
+ self._waiting = loop.create_future()
|
|
|
+ try:
|
|
|
+- with async_timeout.timeout(
|
|
|
+- timeout or self._receive_timeout, loop=self._loop
|
|
|
+- ):
|
|
|
++ async with async_timeout.timeout(timeout or self._receive_timeout):
|
|
|
+ msg = await self._reader.read()
|
|
|
+ self._reset_heartbeat()
|
|
|
+ finally:
|
|
|
+diff --git a/setup.py b/setup.py
|
|
|
+index 54462ba7..c262de1e 100644
|
|
|
+--- a/setup.py
|
|
|
++++ b/setup.py
|
|
|
+@@ -68,7 +68,7 @@ install_requires = [
|
|
|
+ "attrs>=17.3.0",
|
|
|
+ "chardet>=2.0,<5.0",
|
|
|
+ "multidict>=4.5,<7.0",
|
|
|
+- "async_timeout>=3.0,<4.0",
|
|
|
++ "async_timeout>=4.0.0a3,<5.0",
|
|
|
+ "yarl>=1.0,<2.0",
|
|
|
+ 'idna-ssl>=1.0; python_version<"3.7"',
|
|
|
+ "typing_extensions>=3.6.5",
|
|
|
+diff --git a/tests/test_client_ws_functional.py b/tests/test_client_ws_functional.py
|
|
|
+index e423765a..76ef0525 100644
|
|
|
+--- a/tests/test_client_ws_functional.py
|
|
|
++++ b/tests/test_client_ws_functional.py
|
|
|
+@@ -461,7 +461,7 @@ async def test_recv_timeout(aiohttp_client) -> None:
|
|
|
+ await resp.send_str("ask")
|
|
|
+
|
|
|
+ with pytest.raises(asyncio.TimeoutError):
|
|
|
+- with async_timeout.timeout(0.01):
|
|
|
++ async with async_timeout.timeout(0.01):
|
|
|
+ await resp.receive()
|
|
|
+
|
|
|
+ await resp.close()
|
|
|
+diff --git a/tests/test_helpers.py b/tests/test_helpers.py
|
|
|
+index 3367c24b..d36c7e4c 100644
|
|
|
+--- a/tests/test_helpers.py
|
|
|
++++ b/tests/test_helpers.py
|
|
|
+@@ -3,7 +3,6 @@ import base64
|
|
|
+ import gc
|
|
|
+ import os
|
|
|
+ import platform
|
|
|
+-import sys
|
|
|
+ import tempfile
|
|
|
+ from math import isclose, modf
|
|
|
+ from unittest import mock
|
|
|
+@@ -391,48 +390,22 @@ async def test_weakref_handle_weak(loop) -> None:
|
|
|
+ await asyncio.sleep(0.1)
|
|
|
+
|
|
|
+
|
|
|
+-def test_ceil_call_later() -> None:
|
|
|
+- cb = mock.Mock()
|
|
|
+- loop = mock.Mock()
|
|
|
+- loop.time.return_value = 10.1
|
|
|
+- helpers.call_later(cb, 10.1, loop)
|
|
|
+- loop.call_at.assert_called_with(21.0, cb)
|
|
|
+-
|
|
|
+-
|
|
|
+-def test_ceil_call_later_no_timeout() -> None:
|
|
|
+- cb = mock.Mock()
|
|
|
+- loop = mock.Mock()
|
|
|
+- helpers.call_later(cb, 0, loop)
|
|
|
+- assert not loop.call_at.called
|
|
|
+-
|
|
|
+-
|
|
|
+-async def test_ceil_timeout(loop) -> None:
|
|
|
+- with helpers.CeilTimeout(None, loop=loop) as timeout:
|
|
|
+- assert timeout._timeout is None
|
|
|
+- assert timeout._cancel_handler is None
|
|
|
++async def test_ceil_timeout() -> None:
|
|
|
++ async with helpers.ceil_timeout(None) as timeout:
|
|
|
++ assert timeout.deadline is None
|
|
|
+
|
|
|
+
|
|
|
+-def test_ceil_timeout_no_task(loop) -> None:
|
|
|
+- with pytest.raises(RuntimeError):
|
|
|
+- with helpers.CeilTimeout(10, loop=loop):
|
|
|
+- pass
|
|
|
+-
|
|
|
+-
|
|
|
+-@pytest.mark.skipif(
|
|
|
+- sys.version_info < (3, 7), reason="TimerHandle.when() doesn't exist"
|
|
|
+-)
|
|
|
+-async def test_ceil_timeout_round(loop) -> None:
|
|
|
+- with helpers.CeilTimeout(7.5, loop=loop) as cm:
|
|
|
+- frac, integer = modf(cm._cancel_handler.when())
|
|
|
++async def test_ceil_timeout_round() -> None:
|
|
|
++ async with helpers.ceil_timeout(7.5) as cm:
|
|
|
++ assert cm.deadline is not None
|
|
|
++ frac, integer = modf(cm.deadline)
|
|
|
+ assert frac == 0
|
|
|
+
|
|
|
+
|
|
|
+-@pytest.mark.skipif(
|
|
|
+- sys.version_info < (3, 7), reason="TimerHandle.when() doesn't exist"
|
|
|
+-)
|
|
|
+-async def test_ceil_timeout_small(loop) -> None:
|
|
|
+- with helpers.CeilTimeout(1.1, loop=loop) as cm:
|
|
|
+- frac, integer = modf(cm._cancel_handler.when())
|
|
|
++async def test_ceil_timeout_small() -> None:
|
|
|
++ async with helpers.ceil_timeout(1.1) as cm:
|
|
|
++ assert cm.deadline is not None
|
|
|
++ frac, integer = modf(cm.deadline)
|
|
|
+ # a chance for exact integer with zero fraction is negligible
|
|
|
+ assert frac != 0
|
|
|
+
|
|
|
+--
|
|
|
+2.25.1
|
|
|
+
|