diff --git a/CHANGES/6757.misc b/CHANGES/6757.misc new file mode 100644 index 00000000000..986e3feb95f --- /dev/null +++ b/CHANGES/6757.misc @@ -0,0 +1,3 @@ +Work around the changes in 3.11, e.g. :py:class:`~asyncio.TimeoutError` is an :py:class:`OSError`, +and :py:class:`~unittest.IsolatedAsyncioTestCase` calls :py:function:`~asyncio.set_event_loop` +differently -- by :user:`graingert`. diff --git a/aiohttp/client.py b/aiohttp/client.py index d05689ca6b7..a97190d078a 100644 --- a/aiohttp/client.py +++ b/aiohttp/client.py @@ -532,6 +532,8 @@ async def _request( except ClientError: raise except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise raise ClientOSError(*exc.args) from exc self._cookie_jar.update_cookies(resp.cookies, resp.url) diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index 733cd48f63c..9478e8d36c5 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -537,12 +537,15 @@ async def write_bytes( await writer.write_eof() except OSError as exc: - new_exc = ClientOSError( - exc.errno, "Can not write request body for %s" % self.url - ) - new_exc.__context__ = exc - new_exc.__cause__ = exc - protocol.set_exception(new_exc) + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + protocol.set_exception(exc) + else: + new_exc = ClientOSError( + exc.errno, "Can not write request body for %s" % self.url + ) + new_exc.__context__ = exc + new_exc.__cause__ = exc + protocol.set_exception(new_exc) except asyncio.CancelledError as exc: if not conn.closed: protocol.set_exception(exc) diff --git a/aiohttp/connector.py b/aiohttp/connector.py index 86399b84272..7dbbf4f2d80 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -970,6 +970,8 @@ async def _wrap_create_connection( except ssl_errors as exc: raise ClientConnectorSSLError(req.connection_key, exc) from exc except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise raise client_error(req.connection_key, exc) from exc def _warn_about_tls_in_tls( @@ -1049,6 +1051,8 @@ async def _start_tls_connection( except ssl_errors as exc: raise ClientConnectorSSLError(req.connection_key, exc) from exc except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise raise client_error(req.connection_key, exc) from exc except TypeError as type_err: # Example cause looks like this: @@ -1100,6 +1104,8 @@ def drop_exception(fut: "asyncio.Future[List[Dict[str, Any]]]") -> None: host_resolved.add_done_callback(drop_exception) raise except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise # in case of proxy it is not ClientProxyConnectionError # it is problem of resolving proxy ip itself raise ClientConnectorError(req.connection_key, exc) from exc @@ -1293,6 +1299,8 @@ async def _create_connection( self._factory, self._path ) except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise raise UnixClientConnectorError(self.path, req.connection_key, exc) from exc return cast(ResponseHandler, proto) @@ -1358,6 +1366,8 @@ async def _create_connection( # other option is to manually set transport like # `proto.transport = trans` except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise raise ClientConnectorError(req.connection_key, exc) from exc return cast(ResponseHandler, proto) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 82956986b9d..e0aacbb68fc 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -430,12 +430,12 @@ def get_app(self) -> Application: raise RuntimeError("Did you forget to define get_application()?") def setUp(self) -> None: - try: - self.loop = asyncio.get_running_loop() - except RuntimeError: - self.loop = asyncio.get_event_loop_policy().get_event_loop() + if not PY_38: + asyncio.get_event_loop().run_until_complete(self.asyncSetUp()) - self.loop.run_until_complete(self.setUpAsync()) + async def asyncSetUp(self) -> None: + self.loop = asyncio.get_running_loop() + return await self.setUpAsync() async def setUpAsync(self) -> None: self.app = await self.get_application() @@ -445,7 +445,11 @@ async def setUpAsync(self) -> None: await self.client.start_server() def tearDown(self) -> None: - self.loop.run_until_complete(self.tearDownAsync()) + if not PY_38: + self.loop.run_until_complete(self.asyncTearDown()) + + async def asyncTearDown(self) -> None: + return await self.tearDownAsync() async def tearDownAsync(self) -> None: await self.client.close()