0001-Bump-async-timeout-version-for-aiohttp-3.8-5299.patch 11 KB

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