diff --git a/homeassistant/async_timeout_backcompat.py b/homeassistant/async_timeout_backcompat.py new file mode 100644 index 00000000000..0a59b0d900e --- /dev/null +++ b/homeassistant/async_timeout_backcompat.py @@ -0,0 +1,67 @@ +"""Provide backwards compat for async_timeout.""" +from __future__ import annotations + +import asyncio +import contextlib +import logging +from typing import Any + +import async_timeout + +from homeassistant.helpers.frame import ( + MissingIntegrationFrame, + get_integration_frame, + report_integration, +) + +_LOGGER = logging.getLogger(__name__) + + +def timeout( + delay: float | None, loop: asyncio.AbstractEventLoop | None = None +) -> async_timeout.Timeout: + """Backwards compatible timeout context manager that warns with loop usage.""" + if loop is None: + loop = asyncio.get_running_loop() + else: + _report( + "called async_timeout.timeout with loop keyword argument. The loop keyword argument is deprecated and calls will fail after Home Assistant 2022.2" + ) + if delay is not None: + deadline: float | None = loop.time() + delay + else: + deadline = None + return async_timeout.Timeout(deadline, loop) + + +def current_task(loop: asyncio.AbstractEventLoop) -> asyncio.Task[Any] | None: + """Backwards compatible current_task.""" + _report( + "called async_timeout.current_task. The current_task call is deprecated and calls will fail after Home Assistant 2022.2; use asyncio.current_task instead" + ) + return asyncio.current_task() + + +def enable() -> None: + """Enable backwards compat transitions.""" + async_timeout.timeout = timeout + async_timeout.current_task = current_task # type: ignore[attr-defined] + + +def _report(what: str) -> None: + """Report incorrect usage. + + Async friendly. + """ + integration_frame = None + + with contextlib.suppress(MissingIntegrationFrame): + integration_frame = get_integration_frame() + + if not integration_frame: + _LOGGER.warning( + "Detected code that %s; Please report this issue", what, stack_info=True + ) + return + + report_integration(what, integration_frame) diff --git a/homeassistant/components/ads/__init__.py b/homeassistant/components/ads/__init__.py index d59d1e5aa0c..53687564cd2 100644 --- a/homeassistant/components/ads/__init__.py +++ b/homeassistant/components/ads/__init__.py @@ -307,7 +307,7 @@ class AdsEntity(Entity): self._ads_hub.add_device_notification, ads_var, plctype, update ) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): await self._event.wait() except asyncio.TimeoutError: _LOGGER.debug("Variable %s: Timeout during first update", ads_var) diff --git a/homeassistant/components/aemet/weather_update_coordinator.py b/homeassistant/components/aemet/weather_update_coordinator.py index 68c979ee27c..d791158b9de 100644 --- a/homeassistant/components/aemet/weather_update_coordinator.py +++ b/homeassistant/components/aemet/weather_update_coordinator.py @@ -140,7 +140,7 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self): data = {} - with async_timeout.timeout(120): + async with async_timeout.timeout(120): weather_response = await self._get_aemet_weather() data = self._convert_weather_response(weather_response) return data diff --git a/homeassistant/components/airly/__init__.py b/homeassistant/components/airly/__init__.py index 0304945e6d2..14a58abc248 100644 --- a/homeassistant/components/airly/__init__.py +++ b/homeassistant/components/airly/__init__.py @@ -167,7 +167,7 @@ class AirlyDataUpdateCoordinator(DataUpdateCoordinator): measurements = self.airly.create_measurements_session_point( self.latitude, self.longitude ) - with async_timeout.timeout(20): + async with async_timeout.timeout(20): try: await measurements.update() except (AirlyError, ClientConnectorError) as error: diff --git a/homeassistant/components/airly/config_flow.py b/homeassistant/components/airly/config_flow.py index a6fa9f2d1d6..10e4990ee05 100644 --- a/homeassistant/components/airly/config_flow.py +++ b/homeassistant/components/airly/config_flow.py @@ -103,7 +103,7 @@ async def test_location( measurements = airly.create_measurements_session_point( latitude=latitude, longitude=longitude ) - with async_timeout.timeout(10): + async with async_timeout.timeout(10): await measurements.update() current = measurements.current diff --git a/homeassistant/components/alexa/auth.py b/homeassistant/components/alexa/auth.py index 91729763804..d888b91a39e 100644 --- a/homeassistant/components/alexa/auth.py +++ b/homeassistant/components/alexa/auth.py @@ -105,7 +105,7 @@ class Auth: try: session = aiohttp_client.async_get_clientsession(self.hass) - with async_timeout.timeout(10): + async with async_timeout.timeout(10): response = await session.post( LWA_TOKEN_URI, headers=LWA_HEADERS, diff --git a/homeassistant/components/alexa/state_report.py b/homeassistant/components/alexa/state_report.py index e611960b9d9..1ab12041e32 100644 --- a/homeassistant/components/alexa/state_report.py +++ b/homeassistant/components/alexa/state_report.py @@ -132,7 +132,7 @@ async def async_send_changereport_message( session = hass.helpers.aiohttp_client.async_get_clientsession() try: - with async_timeout.timeout(DEFAULT_TIMEOUT): + async with async_timeout.timeout(DEFAULT_TIMEOUT): response = await session.post( config.endpoint, headers=headers, @@ -263,7 +263,7 @@ async def async_send_doorbell_event_message(hass, config, alexa_entity): session = hass.helpers.aiohttp_client.async_get_clientsession() try: - with async_timeout.timeout(DEFAULT_TIMEOUT): + async with async_timeout.timeout(DEFAULT_TIMEOUT): response = await session.post( config.endpoint, headers=headers, diff --git a/homeassistant/components/almond/__init__.py b/homeassistant/components/almond/__init__.py index 6a5449e3d51..03fc1f26011 100644 --- a/homeassistant/components/almond/__init__.py +++ b/homeassistant/components/almond/__init__.py @@ -192,7 +192,7 @@ async def _configure_almond_for_ha( # Store token in Almond try: - with async_timeout.timeout(30): + async with async_timeout.timeout(30): await api.async_create_device( { "kind": "io.home-assistant", diff --git a/homeassistant/components/almond/config_flow.py b/homeassistant/components/almond/config_flow.py index b7b56f93864..32d90f7b03b 100644 --- a/homeassistant/components/almond/config_flow.py +++ b/homeassistant/components/almond/config_flow.py @@ -24,7 +24,7 @@ async def async_verify_local_connection(hass: core.HomeAssistant, host: str): api = WebAlmondAPI(AlmondLocalAuth(host, websession)) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): await api.async_list_apps() return True diff --git a/homeassistant/components/analytics/analytics.py b/homeassistant/components/analytics/analytics.py index d7fa781945d..d1b8879bf7c 100644 --- a/homeassistant/components/analytics/analytics.py +++ b/homeassistant/components/analytics/analytics.py @@ -255,7 +255,7 @@ class Analytics: ) try: - with async_timeout.timeout(30): + async with async_timeout.timeout(30): response = await self.session.post(self.endpoint, json=payload) if response.status == 200: LOGGER.info( diff --git a/homeassistant/components/api/__init__.py b/homeassistant/components/api/__init__.py index 229311ff6d9..d2201ccace0 100644 --- a/homeassistant/components/api/__init__.py +++ b/homeassistant/components/api/__init__.py @@ -131,7 +131,7 @@ class APIEventStream(HomeAssistantView): while True: try: - with async_timeout.timeout(STREAM_PING_INTERVAL): + async with async_timeout.timeout(STREAM_PING_INTERVAL): payload = await to_write.get() if payload is stop_obj: diff --git a/homeassistant/components/arcam_fmj/__init__.py b/homeassistant/components/arcam_fmj/__init__.py index d28de3b92aa..8784e0f13ae 100644 --- a/homeassistant/components/arcam_fmj/__init__.py +++ b/homeassistant/components/arcam_fmj/__init__.py @@ -85,7 +85,7 @@ async def _run_client(hass, client, interval): while True: try: - with async_timeout.timeout(interval): + async with async_timeout.timeout(interval): await client.start() _LOGGER.debug("Client connected %s", client.host) diff --git a/homeassistant/components/atag/__init__.py b/homeassistant/components/atag/__init__.py index 69880da5a39..920b910269d 100644 --- a/homeassistant/components/atag/__init__.py +++ b/homeassistant/components/atag/__init__.py @@ -29,7 +29,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def _async_update_data(): """Update data via library.""" - with async_timeout.timeout(20): + async with async_timeout.timeout(20): try: await atag.update() except AtagException as err: diff --git a/homeassistant/components/awair/__init__.py b/homeassistant/components/awair/__init__.py index 39853dab9de..d78931e5d2f 100644 --- a/homeassistant/components/awair/__init__.py +++ b/homeassistant/components/awair/__init__.py @@ -58,7 +58,7 @@ class AwairDataUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self) -> Any | None: """Update data via Awair client library.""" - with timeout(API_TIMEOUT): + async with timeout(API_TIMEOUT): try: LOGGER.debug("Fetching users and devices") user = await self._awair.user() diff --git a/homeassistant/components/axis/device.py b/homeassistant/components/axis/device.py index 823593ecacb..a2eceff6870 100644 --- a/homeassistant/components/axis/device.py +++ b/homeassistant/components/axis/device.py @@ -280,7 +280,7 @@ async def get_device(hass, host, port, username, password): ) try: - with async_timeout.timeout(30): + async with async_timeout.timeout(30): await device.vapix.initialize() return device diff --git a/homeassistant/components/bluesound/media_player.py b/homeassistant/components/bluesound/media_player.py index 6c90a511a05..c91a2dedca3 100644 --- a/homeassistant/components/bluesound/media_player.py +++ b/homeassistant/components/bluesound/media_player.py @@ -358,7 +358,7 @@ class BluesoundPlayer(MediaPlayerEntity): try: websession = async_get_clientsession(self._hass) - with async_timeout.timeout(10): + async with async_timeout.timeout(10): response = await websession.get(url) if response.status == HTTPStatus.OK: @@ -400,7 +400,7 @@ class BluesoundPlayer(MediaPlayerEntity): try: - with async_timeout.timeout(125): + async with async_timeout.timeout(125): response = await self._polling_session.get( url, headers={CONNECTION: KEEP_ALIVE} ) diff --git a/homeassistant/components/buienradar/util.py b/homeassistant/components/buienradar/util.py index 63c585f8c2f..3686e2bd3c9 100644 --- a/homeassistant/components/buienradar/util.py +++ b/homeassistant/components/buienradar/util.py @@ -88,7 +88,7 @@ class BrData: resp = None try: websession = async_get_clientsession(self.hass) - with async_timeout.timeout(10): + async with async_timeout.timeout(10): resp = await websession.get(url) result[STATUS_CODE] = resp.status diff --git a/homeassistant/components/citybikes/sensor.py b/homeassistant/components/citybikes/sensor.py index fd0c96c6fbe..937e2582fbb 100644 --- a/homeassistant/components/citybikes/sensor.py +++ b/homeassistant/components/citybikes/sensor.py @@ -135,7 +135,7 @@ async def async_citybikes_request(hass, uri, schema): try: session = async_get_clientsession(hass) - with async_timeout.timeout(REQUEST_TIMEOUT): + async with async_timeout.timeout(REQUEST_TIMEOUT): req = await session.get(DEFAULT_ENDPOINT.format(uri=uri)) json_response = await req.json() diff --git a/homeassistant/components/cloud/alexa_config.py b/homeassistant/components/cloud/alexa_config.py index a6c30a5a79b..0d1bdf66c12 100644 --- a/homeassistant/components/cloud/alexa_config.py +++ b/homeassistant/components/cloud/alexa_config.py @@ -313,7 +313,7 @@ class AlexaConfig(alexa_config.AbstractConfig): ) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): await asyncio.wait(tasks, return_when=asyncio.ALL_COMPLETED) return True diff --git a/homeassistant/components/cloud/http_api.py b/homeassistant/components/cloud/http_api.py index 5bfebec40a3..64d3943dda7 100644 --- a/homeassistant/components/cloud/http_api.py +++ b/homeassistant/components/cloud/http_api.py @@ -204,7 +204,7 @@ class CloudLogoutView(HomeAssistantView): hass = request.app["hass"] cloud = hass.data[DOMAIN] - with async_timeout.timeout(REQUEST_TIMEOUT): + async with async_timeout.timeout(REQUEST_TIMEOUT): await cloud.logout() return self.json_message("ok") @@ -230,7 +230,7 @@ class CloudRegisterView(HomeAssistantView): hass = request.app["hass"] cloud = hass.data[DOMAIN] - with async_timeout.timeout(REQUEST_TIMEOUT): + async with async_timeout.timeout(REQUEST_TIMEOUT): await cloud.auth.async_register(data["email"], data["password"]) return self.json_message("ok") @@ -249,7 +249,7 @@ class CloudResendConfirmView(HomeAssistantView): hass = request.app["hass"] cloud = hass.data[DOMAIN] - with async_timeout.timeout(REQUEST_TIMEOUT): + async with async_timeout.timeout(REQUEST_TIMEOUT): await cloud.auth.async_resend_email_confirm(data["email"]) return self.json_message("ok") @@ -268,7 +268,7 @@ class CloudForgotPasswordView(HomeAssistantView): hass = request.app["hass"] cloud = hass.data[DOMAIN] - with async_timeout.timeout(REQUEST_TIMEOUT): + async with async_timeout.timeout(REQUEST_TIMEOUT): await cloud.auth.async_forgot_password(data["email"]) return self.json_message("ok") @@ -314,7 +314,7 @@ async def websocket_subscription(hass, connection, msg): """Handle request for account info.""" cloud = hass.data[DOMAIN] try: - with async_timeout.timeout(REQUEST_TIMEOUT): + async with async_timeout.timeout(REQUEST_TIMEOUT): data = await cloud_api.async_subscription_info(cloud) except aiohttp.ClientError: connection.send_error( @@ -353,7 +353,7 @@ async def websocket_update_prefs(hass, connection, msg): if changes.get(PREF_ALEXA_REPORT_STATE): alexa_config = await cloud.client.get_alexa_config() try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): await alexa_config.async_get_access_token() except asyncio.TimeoutError: connection.send_error( @@ -574,7 +574,7 @@ async def alexa_sync(hass, connection, msg): cloud = hass.data[DOMAIN] alexa_config = await cloud.client.get_alexa_config() - with async_timeout.timeout(10): + async with async_timeout.timeout(10): try: success = await alexa_config.async_sync_entities() except alexa_errors.NoTokenAvailable: @@ -597,7 +597,7 @@ async def thingtalk_convert(hass, connection, msg): """Convert a query.""" cloud = hass.data[DOMAIN] - with async_timeout.timeout(10): + async with async_timeout.timeout(10): try: connection.send_result( msg["id"], await thingtalk.async_convert(cloud, msg["query"]) diff --git a/homeassistant/components/color_extractor/__init__.py b/homeassistant/components/color_extractor/__init__.py index b0ab5c2aba7..4d8118483b6 100644 --- a/homeassistant/components/color_extractor/__init__.py +++ b/homeassistant/components/color_extractor/__init__.py @@ -113,7 +113,7 @@ async def async_setup(hass, hass_config): try: session = aiohttp_client.async_get_clientsession(hass) - with async_timeout.timeout(10): + async with async_timeout.timeout(10): response = await session.get(url) except (asyncio.TimeoutError, aiohttp.ClientError) as err: diff --git a/homeassistant/components/comed_hourly_pricing/sensor.py b/homeassistant/components/comed_hourly_pricing/sensor.py index fc038adc568..080b31036d9 100644 --- a/homeassistant/components/comed_hourly_pricing/sensor.py +++ b/homeassistant/components/comed_hourly_pricing/sensor.py @@ -104,7 +104,7 @@ class ComedHourlyPricingSensor(SensorEntity): else: url_string += "?type=currenthouraverage" - with async_timeout.timeout(60): + async with async_timeout.timeout(60): response = await self.websession.get(url_string) # The API responds with MIME type 'text/html' text = await response.text() diff --git a/homeassistant/components/coronavirus/__init__.py b/homeassistant/components/coronavirus/__init__.py index d130e131c8b..5deceb5cddc 100644 --- a/homeassistant/components/coronavirus/__init__.py +++ b/homeassistant/components/coronavirus/__init__.py @@ -66,7 +66,7 @@ async def get_coordinator( return hass.data[DOMAIN] async def async_get_cases(): - with async_timeout.timeout(10): + async with async_timeout.timeout(10): return { case.country: case for case in await coronavirus.get_cases( diff --git a/homeassistant/components/daikin/__init__.py b/homeassistant/components/daikin/__init__.py index 185537cc7d0..507ec2f5d79 100644 --- a/homeassistant/components/daikin/__init__.py +++ b/homeassistant/components/daikin/__init__.py @@ -65,7 +65,7 @@ async def daikin_api_setup(hass, host, key, uuid, password): session = hass.helpers.aiohttp_client.async_get_clientsession() try: - with timeout(TIMEOUT): + async with timeout(TIMEOUT): device = await Appliance.factory( host, session, key=key, uuid=uuid, password=password ) diff --git a/homeassistant/components/daikin/config_flow.py b/homeassistant/components/daikin/config_flow.py index 52e4fa255aa..89b27b68c81 100644 --- a/homeassistant/components/daikin/config_flow.py +++ b/homeassistant/components/daikin/config_flow.py @@ -70,7 +70,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): password = None try: - with timeout(TIMEOUT): + async with timeout(TIMEOUT): device = await Appliance.factory( host, self.hass.helpers.aiohttp_client.async_get_clientsession(), diff --git a/homeassistant/components/deconz/config_flow.py b/homeassistant/components/deconz/config_flow.py index 3a6c5aecfb5..42541123b4f 100644 --- a/homeassistant/components/deconz/config_flow.py +++ b/homeassistant/components/deconz/config_flow.py @@ -85,7 +85,7 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): session = aiohttp_client.async_get_clientsession(self.hass) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): self.bridges = await deconz_discovery(session) except (asyncio.TimeoutError, ResponseError): @@ -141,7 +141,7 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): ) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): api_key = await deconz_session.get_api_key() except (ResponseError, RequestError, asyncio.TimeoutError): @@ -159,7 +159,7 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): session = aiohttp_client.async_get_clientsession(self.hass) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): self.bridge_id = await deconz_get_bridge_id( session, **self.deconz_config ) diff --git a/homeassistant/components/deconz/gateway.py b/homeassistant/components/deconz/gateway.py index ddb0d47190c..fd18be76011 100644 --- a/homeassistant/components/deconz/gateway.py +++ b/homeassistant/components/deconz/gateway.py @@ -276,7 +276,7 @@ async def get_gateway( connection_status=async_connection_status_callback, ) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): await deconz.refresh_state() return deconz diff --git a/homeassistant/components/doorbird/camera.py b/homeassistant/components/doorbird/camera.py index 16606156314..8331570fd2f 100644 --- a/homeassistant/components/doorbird/camera.py +++ b/homeassistant/components/doorbird/camera.py @@ -125,7 +125,7 @@ class DoorBirdCamera(DoorBirdEntity, Camera): try: websession = async_get_clientsession(self.hass) - with async_timeout.timeout(_TIMEOUT): + async with async_timeout.timeout(_TIMEOUT): response = await websession.get(self._url) self._last_image = await response.read() diff --git a/homeassistant/components/elkm1/__init__.py b/homeassistant/components/elkm1/__init__.py index 3b59fffe553..07111282c3d 100644 --- a/homeassistant/components/elkm1/__init__.py +++ b/homeassistant/components/elkm1/__init__.py @@ -319,7 +319,7 @@ async def async_wait_for_elk_to_sync(elk, timeout, conf_host): elk.add_handler("login", login_status) elk.add_handler("sync_complete", sync_complete) try: - with async_timeout.timeout(timeout): + async with async_timeout.timeout(timeout): await event.wait() except asyncio.TimeoutError: _LOGGER.error( diff --git a/homeassistant/components/faa_delays/__init__.py b/homeassistant/components/faa_delays/__init__.py index e27916ec6c1..205fa016130 100644 --- a/homeassistant/components/faa_delays/__init__.py +++ b/homeassistant/components/faa_delays/__init__.py @@ -56,7 +56,7 @@ class FAADataUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self): try: - with timeout(10): + async with timeout(10): await self.data.update() except ClientConnectionError as err: raise UpdateFailed(err) from err diff --git a/homeassistant/components/flick_electric/config_flow.py b/homeassistant/components/flick_electric/config_flow.py index c76b44396f5..7f21397d5a7 100644 --- a/homeassistant/components/flick_electric/config_flow.py +++ b/homeassistant/components/flick_electric/config_flow.py @@ -45,7 +45,7 @@ class FlickConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): ) try: - with async_timeout.timeout(60): + async with async_timeout.timeout(60): token = await auth.async_get_access_token() except asyncio.TimeoutError as err: raise CannotConnect() from err diff --git a/homeassistant/components/flick_electric/sensor.py b/homeassistant/components/flick_electric/sensor.py index 938507e4b0c..7ca3b99f928 100644 --- a/homeassistant/components/flick_electric/sensor.py +++ b/homeassistant/components/flick_electric/sensor.py @@ -67,7 +67,7 @@ class FlickPricingSensor(SensorEntity): if self._price and self._price.end_at >= utcnow(): return # Power price data is still valid - with async_timeout.timeout(60): + async with async_timeout.timeout(60): self._price = await self._api.getPricing() self._attributes[ATTR_START_AT] = self._price.start_at diff --git a/homeassistant/components/flock/notify.py b/homeassistant/components/flock/notify.py index de5c078f714..ee89937599a 100644 --- a/homeassistant/components/flock/notify.py +++ b/homeassistant/components/flock/notify.py @@ -41,7 +41,7 @@ class FlockNotificationService(BaseNotificationService): _LOGGER.debug("Attempting to call Flock at %s", self._url) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): response = await self._session.post(self._url, json=payload) result = await response.json() diff --git a/homeassistant/components/freedns/__init__.py b/homeassistant/components/freedns/__init__.py index 7aa34c8780e..754e6cb8818 100644 --- a/homeassistant/components/freedns/__init__.py +++ b/homeassistant/components/freedns/__init__.py @@ -72,7 +72,7 @@ async def _update_freedns(hass, session, url, auth_token): params[auth_token] = "" try: - with async_timeout.timeout(TIMEOUT): + async with async_timeout.timeout(TIMEOUT): resp = await session.get(url, params=params) body = await resp.text() diff --git a/homeassistant/components/garages_amsterdam/__init__.py b/homeassistant/components/garages_amsterdam/__init__.py index be228e2f3a0..2077dec741f 100644 --- a/homeassistant/components/garages_amsterdam/__init__.py +++ b/homeassistant/components/garages_amsterdam/__init__.py @@ -39,7 +39,7 @@ async def get_coordinator( return hass.data[DOMAIN] async def async_get_garages(): - with async_timeout.timeout(10): + async with async_timeout.timeout(10): return { garage.garage_name: garage for garage in await garages_amsterdam.get_garages( diff --git a/homeassistant/components/gios/__init__.py b/homeassistant/components/gios/__init__.py index c3227254075..8457f62fd3f 100644 --- a/homeassistant/components/gios/__init__.py +++ b/homeassistant/components/gios/__init__.py @@ -87,7 +87,7 @@ class GiosDataUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self) -> dict[str, Any]: """Update data via library.""" try: - with timeout(API_TIMEOUT): + async with timeout(API_TIMEOUT): return cast(Dict[str, Any], await self.gios.async_update()) except ( ApiError, diff --git a/homeassistant/components/gios/config_flow.py b/homeassistant/components/gios/config_flow.py index ff3f33408a5..0fa5052e129 100644 --- a/homeassistant/components/gios/config_flow.py +++ b/homeassistant/components/gios/config_flow.py @@ -37,7 +37,7 @@ class GiosFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): websession = async_get_clientsession(self.hass) - with timeout(API_TIMEOUT): + async with timeout(API_TIMEOUT): gios = Gios(user_input[CONF_STATION_ID], websession) await gios.async_update() diff --git a/homeassistant/components/google_cloud/tts.py b/homeassistant/components/google_cloud/tts.py index f402e2a7a06..3d65f4eb297 100644 --- a/homeassistant/components/google_cloud/tts.py +++ b/homeassistant/components/google_cloud/tts.py @@ -281,7 +281,7 @@ class GoogleCloudTTSProvider(Provider): ) # pylint: enable=no-member - with async_timeout.timeout(10, loop=self.hass.loop): + async with async_timeout.timeout(10): response = await self.hass.async_add_executor_job( self._client.synthesize_speech, synthesis_input, voice, audio_config ) diff --git a/homeassistant/components/google_domains/__init__.py b/homeassistant/components/google_domains/__init__.py index ae6cb5c70d5..59386eb378a 100644 --- a/homeassistant/components/google_domains/__init__.py +++ b/homeassistant/components/google_domains/__init__.py @@ -65,7 +65,7 @@ async def _update_google_domains(hass, session, domain, user, password, timeout) params = {"hostname": domain} try: - with async_timeout.timeout(timeout): + async with async_timeout.timeout(timeout): resp = await session.get(url, params=params) body = await resp.text() diff --git a/homeassistant/components/hue/bridge.py b/homeassistant/components/hue/bridge.py index 19ab2128d62..e669cf7b031 100644 --- a/homeassistant/components/hue/bridge.py +++ b/homeassistant/components/hue/bridge.py @@ -280,7 +280,7 @@ class HueBridge: async def authenticate_bridge(hass: core.HomeAssistant, bridge: aiohue.Bridge): """Create a bridge object and verify authentication.""" try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): # Create username if we don't have one if not bridge.username: device_name = unicode_slug.slugify( diff --git a/homeassistant/components/hue/config_flow.py b/homeassistant/components/hue/config_flow.py index 7149b4d9442..409f88cbe04 100644 --- a/homeassistant/components/hue/config_flow.py +++ b/homeassistant/components/hue/config_flow.py @@ -84,7 +84,7 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): # Find / discover bridges try: - with async_timeout.timeout(5): + async with async_timeout.timeout(5): bridges = await discover_nupnp( websession=aiohttp_client.async_get_clientsession(self.hass) ) diff --git a/homeassistant/components/hue/light.py b/homeassistant/components/hue/light.py index 13a3a70ae53..12fbf77aa8b 100644 --- a/homeassistant/components/hue/light.py +++ b/homeassistant/components/hue/light.py @@ -227,7 +227,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): async def async_safe_fetch(bridge, fetch_method): """Safely fetch data.""" try: - with async_timeout.timeout(4): + async with async_timeout.timeout(4): return await bridge.async_request_call(fetch_method) except aiohue.Unauthorized as err: await bridge.handle_unauthorized_error() diff --git a/homeassistant/components/hue/sensor_base.py b/homeassistant/components/hue/sensor_base.py index 957565c54e9..a99d92c0393 100644 --- a/homeassistant/components/hue/sensor_base.py +++ b/homeassistant/components/hue/sensor_base.py @@ -61,7 +61,7 @@ class SensorManager: async def async_update_data(self): """Update sensor data.""" try: - with async_timeout.timeout(4): + async with async_timeout.timeout(4): return await self.bridge.async_request_call( self.bridge.api.sensors.update ) diff --git a/homeassistant/components/iammeter/sensor.py b/homeassistant/components/iammeter/sensor.py index de0e76fc3aa..3d7336fea5b 100644 --- a/homeassistant/components/iammeter/sensor.py +++ b/homeassistant/components/iammeter/sensor.py @@ -42,7 +42,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= config_port = config[CONF_PORT] config_name = config[CONF_NAME] try: - with async_timeout.timeout(PLATFORM_TIMEOUT): + async with async_timeout.timeout(PLATFORM_TIMEOUT): api = await real_time_api(config_host, config_port) except (IamMeterError, asyncio.TimeoutError) as err: _LOGGER.error("Device is not ready") @@ -50,7 +50,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= async def async_update_data(): try: - with async_timeout.timeout(PLATFORM_TIMEOUT): + async with async_timeout.timeout(PLATFORM_TIMEOUT): return await api.get_data() except (IamMeterError, asyncio.TimeoutError) as err: raise UpdateFailed from err diff --git a/homeassistant/components/imap/sensor.py b/homeassistant/components/imap/sensor.py index c3d6b2198ce..89a1348e90e 100644 --- a/homeassistant/components/imap/sensor.py +++ b/homeassistant/components/imap/sensor.py @@ -134,7 +134,7 @@ class ImapSensor(SensorEntity): idle = await self._connection.idle_start() await self._connection.wait_server_push() self._connection.idle_done() - with async_timeout.timeout(10): + async with async_timeout.timeout(10): await idle else: self.async_write_ha_state() diff --git a/homeassistant/components/ipma/weather.py b/homeassistant/components/ipma/weather.py index 32a5967f8b4..f831bac2eef 100644 --- a/homeassistant/components/ipma/weather.py +++ b/homeassistant/components/ipma/weather.py @@ -142,7 +142,7 @@ async def async_get_api(hass): async def async_get_location(hass, api, latitude, longitude): """Retrieve pyipma location, location name to be used as the entity name.""" - with async_timeout.timeout(30): + async with async_timeout.timeout(30): location = await Location.get(api, float(latitude), float(longitude)) _LOGGER.debug( @@ -172,7 +172,7 @@ class IPMAWeather(WeatherEntity): @Throttle(MIN_TIME_BETWEEN_UPDATES) async def async_update(self): """Update Condition and Forecast.""" - with async_timeout.timeout(10): + async with async_timeout.timeout(10): new_observation = await self._location.observation(self._api) new_forecast = await self._location.forecast(self._api) diff --git a/homeassistant/components/isy994/config_flow.py b/homeassistant/components/isy994/config_flow.py index 34c7a40cfc0..413d0689b6e 100644 --- a/homeassistant/components/isy994/config_flow.py +++ b/homeassistant/components/isy994/config_flow.py @@ -89,7 +89,7 @@ async def validate_input(hass: core.HomeAssistant, data): ) try: - with async_timeout.timeout(30): + async with async_timeout.timeout(30): isy_conf_xml = await isy_conn.test_connection() except ISYInvalidAuthError as error: raise InvalidAuth from error diff --git a/homeassistant/components/kaiterra/api_data.py b/homeassistant/components/kaiterra/api_data.py index b426a298ddb..f34ae161c6d 100644 --- a/homeassistant/components/kaiterra/api_data.py +++ b/homeassistant/components/kaiterra/api_data.py @@ -53,7 +53,7 @@ class KaiterraApiData: """Get the data from Kaiterra API.""" try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): data = await self._api.get_latest_sensor_readings(self._devices) except (ClientResponseError, asyncio.TimeoutError): _LOGGER.debug("Couldn't fetch data from Kaiterra API") diff --git a/homeassistant/components/lifx_cloud/scene.py b/homeassistant/components/lifx_cloud/scene.py index ec2aca00aa9..c91feeaef82 100644 --- a/homeassistant/components/lifx_cloud/scene.py +++ b/homeassistant/components/lifx_cloud/scene.py @@ -38,7 +38,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= try: httpsession = async_get_clientsession(hass) - with async_timeout.timeout(timeout): + async with async_timeout.timeout(timeout): scenes_resp = await httpsession.get(url, headers=headers) except (asyncio.TimeoutError, aiohttp.ClientError): @@ -81,7 +81,7 @@ class LifxCloudScene(Scene): try: httpsession = async_get_clientsession(self.hass) - with async_timeout.timeout(self._timeout): + async with async_timeout.timeout(self._timeout): await httpsession.put(url, headers=self._headers) except (asyncio.TimeoutError, aiohttp.ClientError): diff --git a/homeassistant/components/logi_circle/__init__.py b/homeassistant/components/logi_circle/__init__.py index d9060b10080..45b34928a30 100644 --- a/homeassistant/components/logi_circle/__init__.py +++ b/homeassistant/components/logi_circle/__init__.py @@ -147,7 +147,7 @@ async def async_setup_entry(hass, entry): return False try: - with async_timeout.timeout(_TIMEOUT): + async with async_timeout.timeout(_TIMEOUT): # Ensure the cameras property returns the same Camera objects for # all devices. Performs implicit login and session validation. await logi_circle.synchronize_cameras() diff --git a/homeassistant/components/logi_circle/config_flow.py b/homeassistant/components/logi_circle/config_flow.py index 9054b476332..7453fe27e18 100644 --- a/homeassistant/components/logi_circle/config_flow.py +++ b/homeassistant/components/logi_circle/config_flow.py @@ -158,7 +158,7 @@ class LogiCircleFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): ) try: - with async_timeout.timeout(_TIMEOUT): + async with async_timeout.timeout(_TIMEOUT): await logi_session.authorize(code) except AuthorizationFailed: (self.hass.data[DATA_FLOW_IMPL][DOMAIN][EXTERNAL_ERRORS]) = "invalid_auth" diff --git a/homeassistant/components/mailbox/__init__.py b/homeassistant/components/mailbox/__init__.py index 0c473367fe9..98dd0f45d2b 100644 --- a/homeassistant/components/mailbox/__init__.py +++ b/homeassistant/components/mailbox/__init__.py @@ -250,7 +250,7 @@ class MailboxMediaView(MailboxView): mailbox = self.get_mailbox(platform) with suppress(asyncio.CancelledError, asyncio.TimeoutError): - with async_timeout.timeout(10): + async with async_timeout.timeout(10): try: stream = await mailbox.async_get_media(msgid) except StreamError as err: diff --git a/homeassistant/components/melcloud/__init__.py b/homeassistant/components/melcloud/__init__.py index 518d902a7e1..af34498aba2 100644 --- a/homeassistant/components/melcloud/__init__.py +++ b/homeassistant/components/melcloud/__init__.py @@ -145,7 +145,7 @@ async def mel_devices_setup(hass, token) -> list[MelCloudDevice]: """Query connected devices from MELCloud.""" session = hass.helpers.aiohttp_client.async_get_clientsession() try: - with timeout(10): + async with timeout(10): all_devices = await get_devices( token, session, diff --git a/homeassistant/components/melcloud/config_flow.py b/homeassistant/components/melcloud/config_flow.py index 9c15f5ec242..139a4e8e44d 100644 --- a/homeassistant/components/melcloud/config_flow.py +++ b/homeassistant/components/melcloud/config_flow.py @@ -42,7 +42,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): ) try: - with timeout(10): + async with timeout(10): if (acquired_token := token) is None: acquired_token = await pymelcloud.login( username, diff --git a/homeassistant/components/microsoft_face/__init__.py b/homeassistant/components/microsoft_face/__init__.py index 9f7131d1935..d0f08427b51 100644 --- a/homeassistant/components/microsoft_face/__init__.py +++ b/homeassistant/components/microsoft_face/__init__.py @@ -299,7 +299,7 @@ class MicrosoftFace: payload = None try: - with async_timeout.timeout(self.timeout): + async with async_timeout.timeout(self.timeout): response = await getattr(self.websession, method)( url, data=payload, headers=headers, params=params ) diff --git a/homeassistant/components/mjpeg/camera.py b/homeassistant/components/mjpeg/camera.py index d486f78d334..85f0c21f90c 100644 --- a/homeassistant/components/mjpeg/camera.py +++ b/homeassistant/components/mjpeg/camera.py @@ -122,7 +122,7 @@ class MjpegCamera(Camera): websession = async_get_clientsession(self.hass, verify_ssl=self._verify_ssl) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): response = await websession.get(self._still_image_url, auth=self._auth) image = await response.read() diff --git a/homeassistant/components/mobile_app/notify.py b/homeassistant/components/mobile_app/notify.py index bd5f1354ad3..e1dada100f9 100644 --- a/homeassistant/components/mobile_app/notify.py +++ b/homeassistant/components/mobile_app/notify.py @@ -149,7 +149,7 @@ class MobileAppNotificationService(BaseNotificationService): target_data["registration_info"] = reg_info try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): response = await async_get_clientsession(self._hass).post( push_url, json=target_data ) diff --git a/homeassistant/components/mullvad/__init__.py b/homeassistant/components/mullvad/__init__.py index eeab5abed2f..fe02983633b 100644 --- a/homeassistant/components/mullvad/__init__.py +++ b/homeassistant/components/mullvad/__init__.py @@ -18,7 +18,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: dict) -> bool: """Set up Mullvad VPN integration.""" async def async_get_mullvad_api_data(): - with async_timeout.timeout(10): + async with async_timeout.timeout(10): api = await hass.async_add_executor_job(MullvadAPI) return api.data diff --git a/homeassistant/components/mysensors/gateway.py b/homeassistant/components/mysensors/gateway.py index 41311f45b03..fa7bf1ca88d 100644 --- a/homeassistant/components/mysensors/gateway.py +++ b/homeassistant/components/mysensors/gateway.py @@ -107,7 +107,7 @@ async def try_connect( connect_task = None try: connect_task = asyncio.create_task(gateway.start()) - with async_timeout.timeout(GATEWAY_READY_TIMEOUT): + async with async_timeout.timeout(GATEWAY_READY_TIMEOUT): await gateway_ready.wait() return True except asyncio.TimeoutError: @@ -319,7 +319,7 @@ async def _gw_start( # Gatways connected via mqtt doesn't send gateway ready message. return try: - with async_timeout.timeout(GATEWAY_READY_TIMEOUT): + async with async_timeout.timeout(GATEWAY_READY_TIMEOUT): await gateway_ready.wait() except asyncio.TimeoutError: _LOGGER.warning( diff --git a/homeassistant/components/nam/__init__.py b/homeassistant/components/nam/__init__.py index 4843e96b5a8..5052ffbaf1f 100644 --- a/homeassistant/components/nam/__init__.py +++ b/homeassistant/components/nam/__init__.py @@ -100,7 +100,7 @@ class NAMDataUpdateCoordinator(DataUpdateCoordinator): # Device firmware uses synchronous code and doesn't respond to http queries # when reading data from sensors. The nettigo-air-quality library tries to # get the data 4 times, so we use a longer than usual timeout here. - with async_timeout.timeout(30): + async with async_timeout.timeout(30): data = await self.nam.async_update() except (ApiError, ClientConnectorError, InvalidSensorData) as error: raise UpdateFailed(error) from error diff --git a/homeassistant/components/nam/config_flow.py b/homeassistant/components/nam/config_flow.py index 458895e69c5..0fe2c8f9c65 100644 --- a/homeassistant/components/nam/config_flow.py +++ b/homeassistant/components/nam/config_flow.py @@ -120,5 +120,5 @@ class NAMFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): # Device firmware uses synchronous code and doesn't respond to http queries # when reading data from sensors. The nettigo-air-monitor library tries to get # the data 4 times, so we use a longer than usual timeout here. - with async_timeout.timeout(30): + async with async_timeout.timeout(30): return await nam.async_get_mac_address() diff --git a/homeassistant/components/nest/config_flow.py b/homeassistant/components/nest/config_flow.py index 1ec3e421a0d..189a8189e8a 100644 --- a/homeassistant/components/nest/config_flow.py +++ b/homeassistant/components/nest/config_flow.py @@ -211,7 +211,7 @@ class NestFlowHandler( if user_input is not None: try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): tokens = await flow["convert_code"](user_input["code"]) return self._entry_from_tokens( f"Nest (via {flow['name']})", flow, tokens @@ -228,7 +228,7 @@ class NestFlowHandler( _LOGGER.exception("Unexpected error resolving code") try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): url = await flow["gen_authorize_url"](self.flow_id) except asyncio.TimeoutError: return self.async_abort(reason="authorize_url_timeout") diff --git a/homeassistant/components/no_ip/__init__.py b/homeassistant/components/no_ip/__init__.py index 97015eab38a..1c4bcb40819 100644 --- a/homeassistant/components/no_ip/__init__.py +++ b/homeassistant/components/no_ip/__init__.py @@ -96,7 +96,7 @@ async def _update_no_ip( } try: - with async_timeout.timeout(timeout): + async with async_timeout.timeout(timeout): resp = await session.get(url, params=params, headers=headers) body = await resp.text() diff --git a/homeassistant/components/openalpr_cloud/image_processing.py b/homeassistant/components/openalpr_cloud/image_processing.py index dedf242e0c7..c4734d4c168 100644 --- a/homeassistant/components/openalpr_cloud/image_processing.py +++ b/homeassistant/components/openalpr_cloud/image_processing.py @@ -113,7 +113,7 @@ class OpenAlprCloudEntity(ImageProcessingAlprEntity): body = {"image_bytes": str(b64encode(image), "utf-8")} try: - with async_timeout.timeout(self.timeout): + async with async_timeout.timeout(self.timeout): request = await websession.post( OPENALPR_API_URL, params=params, data=body ) diff --git a/homeassistant/components/openweathermap/weather_update_coordinator.py b/homeassistant/components/openweathermap/weather_update_coordinator.py index 5c2633a7a33..f4814e64d9a 100644 --- a/homeassistant/components/openweathermap/weather_update_coordinator.py +++ b/homeassistant/components/openweathermap/weather_update_coordinator.py @@ -73,7 +73,7 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self): data = {} - with async_timeout.timeout(20): + async with async_timeout.timeout(20): try: weather_response = await self._get_owm_weather() data = self._convert_weather_response(weather_response) diff --git a/homeassistant/components/point/config_flow.py b/homeassistant/components/point/config_flow.py index fbcbcd02a2b..8520e53654f 100644 --- a/homeassistant/components/point/config_flow.py +++ b/homeassistant/components/point/config_flow.py @@ -93,7 +93,7 @@ class PointFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): errors["base"] = "follow_link" try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): url = await self._get_authorization_url() except asyncio.TimeoutError: return self.async_abort(reason="authorize_url_timeout") diff --git a/homeassistant/components/poolsense/__init__.py b/homeassistant/components/poolsense/__init__.py index fb7927de970..7ca7751b6f0 100644 --- a/homeassistant/components/poolsense/__init__.py +++ b/homeassistant/components/poolsense/__init__.py @@ -90,7 +90,7 @@ class PoolSenseDataUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self): """Update data via library.""" data = {} - with async_timeout.timeout(10): + async with async_timeout.timeout(10): try: data = await self.poolsense.get_poolsense_data() except (PoolSenseError) as error: diff --git a/homeassistant/components/prowl/notify.py b/homeassistant/components/prowl/notify.py index 91dd8eca5ca..837bad930f4 100644 --- a/homeassistant/components/prowl/notify.py +++ b/homeassistant/components/prowl/notify.py @@ -56,7 +56,7 @@ class ProwlNotificationService(BaseNotificationService): session = async_get_clientsession(self._hass) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): response = await session.post(url, data=payload) result = await response.text() diff --git a/homeassistant/components/push/camera.py b/homeassistant/components/push/camera.py index 8f4d1d04dcf..b5ce846d52f 100644 --- a/homeassistant/components/push/camera.py +++ b/homeassistant/components/push/camera.py @@ -72,7 +72,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= async def handle_webhook(hass, webhook_id, request): """Handle incoming webhook POST with image files.""" try: - with async_timeout.timeout(5): + async with async_timeout.timeout(5): data = dict(await request.post()) except (asyncio.TimeoutError, aiohttp.web.HTTPException) as error: _LOGGER.error("Could not get information from POST <%s>", error) diff --git a/homeassistant/components/rainforest_eagle/data.py b/homeassistant/components/rainforest_eagle/data.py index 91447392ea8..52f40e81d40 100644 --- a/homeassistant/components/rainforest_eagle/data.py +++ b/homeassistant/components/rainforest_eagle/data.py @@ -50,7 +50,7 @@ async def async_get_type(hass, cloud_id, install_code, host): ) try: - with async_timeout.timeout(30): + async with async_timeout.timeout(30): meters = await hub.get_device_list() except aioeagle.BadAuth as err: raise InvalidAuth from err diff --git a/homeassistant/components/rest/switch.py b/homeassistant/components/rest/switch.py index 83bd5ae27ae..3448b79979c 100644 --- a/homeassistant/components/rest/switch.py +++ b/homeassistant/components/rest/switch.py @@ -210,7 +210,7 @@ class RestSwitch(SwitchEntity): rendered_headers = render_templates(self._headers) rendered_params = render_templates(self._params) - with async_timeout.timeout(self._timeout): + async with async_timeout.timeout(self._timeout): req = await getattr(websession, self._method)( self._resource, auth=self._auth, @@ -236,7 +236,7 @@ class RestSwitch(SwitchEntity): rendered_headers = render_templates(self._headers) rendered_params = render_templates(self._params) - with async_timeout.timeout(self._timeout): + async with async_timeout.timeout(self._timeout): req = await websession.get( self._state_resource, auth=self._auth, diff --git a/homeassistant/components/rflink/__init__.py b/homeassistant/components/rflink/__init__.py index e0ce94cb723..6a59212d6c1 100644 --- a/homeassistant/components/rflink/__init__.py +++ b/homeassistant/components/rflink/__init__.py @@ -270,7 +270,7 @@ async def async_setup(hass, config): ) try: - with async_timeout.timeout(CONNECTION_TIMEOUT): + async with async_timeout.timeout(CONNECTION_TIMEOUT): transport, protocol = await connection except ( diff --git a/homeassistant/components/roomba/__init__.py b/homeassistant/components/roomba/__init__.py index 3936d3f6d1d..2911f46d55d 100644 --- a/homeassistant/components/roomba/__init__.py +++ b/homeassistant/components/roomba/__init__.py @@ -80,7 +80,7 @@ async def async_connect_or_timeout(hass, roomba): """Connect to vacuum.""" try: name = None - with async_timeout.timeout(10): + async with async_timeout.timeout(10): _LOGGER.debug("Initialize connection to vacuum") await hass.async_add_executor_job(roomba.connect) while not roomba.roomba_connected or name is None: @@ -104,7 +104,7 @@ async def async_connect_or_timeout(hass, roomba): async def async_disconnect_or_timeout(hass, roomba): """Disconnect to vacuum.""" _LOGGER.debug("Disconnect vacuum") - with async_timeout.timeout(3): + async with async_timeout.timeout(3): await hass.async_add_executor_job(roomba.disconnect) return True diff --git a/homeassistant/components/sensibo/climate.py b/homeassistant/components/sensibo/climate.py index b0b211e4a7d..7104d9ebff7 100644 --- a/homeassistant/components/sensibo/climate.py +++ b/homeassistant/components/sensibo/climate.py @@ -91,7 +91,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= ) devices = [] try: - with async_timeout.timeout(TIMEOUT): + async with async_timeout.timeout(TIMEOUT): for dev in await client.async_get_devices(_INITIAL_FETCH_FIELDS): if config[CONF_ID] == ALL or dev["id"] in config[CONF_ID]: devices.append( @@ -363,7 +363,7 @@ class SensiboClimate(ClimateEntity): async def async_update(self): """Retrieve latest state.""" try: - with async_timeout.timeout(TIMEOUT): + async with async_timeout.timeout(TIMEOUT): data = await self._client.async_get_device(self._id, _FETCH_FIELDS) except ( aiohttp.client_exceptions.ClientError, @@ -389,7 +389,7 @@ class SensiboClimate(ClimateEntity): async def _async_set_ac_state_property(self, name, value, assumed_state=False): """Set AC state.""" try: - with async_timeout.timeout(TIMEOUT): + async with async_timeout.timeout(TIMEOUT): await self._client.async_set_ac_state_property( self._id, name, value, self._ac_states, assumed_state ) diff --git a/homeassistant/components/sharkiq/__init__.py b/homeassistant/components/sharkiq/__init__.py index ed5c7ae1b54..d3246b5ac9e 100644 --- a/homeassistant/components/sharkiq/__init__.py +++ b/homeassistant/components/sharkiq/__init__.py @@ -26,7 +26,7 @@ class CannotConnect(exceptions.HomeAssistantError): async def async_connect_or_timeout(ayla_api: AylaApi) -> bool: """Connect to vacuum.""" try: - with async_timeout.timeout(API_TIMEOUT): + async with async_timeout.timeout(API_TIMEOUT): _LOGGER.debug("Initialize connection to Ayla networks API") await ayla_api.async_sign_in() except SharkIqAuthError: @@ -71,10 +71,11 @@ async def async_setup_entry(hass, config_entry): async def async_disconnect_or_timeout(coordinator: SharkIqUpdateCoordinator): """Disconnect to vacuum.""" _LOGGER.debug("Disconnecting from Ayla Api") - with async_timeout.timeout(5), suppress( - SharkIqAuthError, SharkIqAuthExpiringError, SharkIqNotAuthedError - ): - await coordinator.ayla_api.async_sign_out() + async with async_timeout.timeout(5): + with suppress( + SharkIqAuthError, SharkIqAuthExpiringError, SharkIqNotAuthedError + ): + await coordinator.ayla_api.async_sign_out() async def async_update_options(hass, config_entry): diff --git a/homeassistant/components/sharkiq/config_flow.py b/homeassistant/components/sharkiq/config_flow.py index 8fef217a609..53306e15d12 100644 --- a/homeassistant/components/sharkiq/config_flow.py +++ b/homeassistant/components/sharkiq/config_flow.py @@ -27,7 +27,7 @@ async def validate_input(hass: core.HomeAssistant, data): ) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): _LOGGER.debug("Initialize connection to Ayla networks API") await ayla_api.async_sign_in() except (asyncio.TimeoutError, aiohttp.ClientError) as errors: diff --git a/homeassistant/components/sharkiq/update_coordinator.py b/homeassistant/components/sharkiq/update_coordinator.py index 16ed0e14d9a..f8559bcc31f 100644 --- a/homeassistant/components/sharkiq/update_coordinator.py +++ b/homeassistant/components/sharkiq/update_coordinator.py @@ -54,7 +54,7 @@ class SharkIqUpdateCoordinator(DataUpdateCoordinator): """Asynchronously update the data for a single vacuum.""" dsn = sharkiq.serial_number _LOGGER.debug("Updating sharkiq data for device DSN %s", dsn) - with timeout(API_TIMEOUT): + async with timeout(API_TIMEOUT): await sharkiq.async_update() async def _async_update_data(self) -> bool: diff --git a/homeassistant/components/smhi/weather.py b/homeassistant/components/smhi/weather.py index ec99f2a12ae..ac1ec53f67c 100644 --- a/homeassistant/components/smhi/weather.py +++ b/homeassistant/components/smhi/weather.py @@ -125,7 +125,7 @@ class SmhiWeather(WeatherEntity): async def async_update(self) -> None: """Refresh the forecast data from SMHI weather API.""" try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): self._forecasts = await self.get_weather_forecast() self._fail_count = 0 diff --git a/homeassistant/components/sonos/speaker.py b/homeassistant/components/sonos/speaker.py index 66a2b46eb12..593bd8f034a 100644 --- a/homeassistant/components/sonos/speaker.py +++ b/homeassistant/components/sonos/speaker.py @@ -972,7 +972,7 @@ class SonosSpeaker: return True try: - with async_timeout.timeout(5): + async with async_timeout.timeout(5): while not _test_groups(groups): await hass.data[DATA_SONOS].topology_condition.wait() except asyncio.TimeoutError: diff --git a/homeassistant/components/srp_energy/sensor.py b/homeassistant/components/srp_energy/sensor.py index 4a5e3c33748..747b25faa50 100644 --- a/homeassistant/components/srp_energy/sensor.py +++ b/homeassistant/components/srp_energy/sensor.py @@ -44,7 +44,7 @@ async def async_setup_entry(hass, entry, async_add_entities): # Fetch srp_energy data start_date = datetime.now() + timedelta(days=-1) end_date = datetime.now() - with async_timeout.timeout(10): + async with async_timeout.timeout(10): hourly_usage = await hass.async_add_executor_job( api.usage, start_date, diff --git a/homeassistant/components/startca/sensor.py b/homeassistant/components/startca/sensor.py index 931e9eabfc0..135c3eeebda 100644 --- a/homeassistant/components/startca/sensor.py +++ b/homeassistant/components/startca/sensor.py @@ -193,7 +193,7 @@ class StartcaData: """Get the Start.ca bandwidth data from the web service.""" _LOGGER.debug("Updating Start.ca usage data") url = f"https://www.start.ca/support/usage/api?key={self.api_key}" - with async_timeout.timeout(REQUEST_TIMEOUT): + async with async_timeout.timeout(REQUEST_TIMEOUT): req = await self.websession.get(url) if req.status != HTTPStatus.OK: _LOGGER.error("Request failed with status: %u", req.status) diff --git a/homeassistant/components/system_health/__init__.py b/homeassistant/components/system_health/__init__.py index 2683f6a2f3a..1d4adbfca64 100644 --- a/homeassistant/components/system_health/__init__.py +++ b/homeassistant/components/system_health/__init__.py @@ -64,7 +64,7 @@ async def get_integration_info( ): """Get integration system health.""" try: - with async_timeout.timeout(INFO_CALLBACK_TIMEOUT): + async with async_timeout.timeout(INFO_CALLBACK_TIMEOUT): data = await registration.info_callback(hass) except asyncio.TimeoutError: data = {"error": {"type": "failed", "error": "timeout"}} diff --git a/homeassistant/components/tado/device_tracker.py b/homeassistant/components/tado/device_tracker.py index e49a5be5a71..977be7d226a 100644 --- a/homeassistant/components/tado/device_tracker.py +++ b/homeassistant/components/tado/device_tracker.py @@ -106,7 +106,7 @@ class TadoDeviceScanner(DeviceScanner): last_results = [] try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): # Format the URL here, so we can log the template URL if # anything goes wrong without exposing username and password. url = self.tadoapiurl.format( diff --git a/homeassistant/components/tellduslive/config_flow.py b/homeassistant/components/tellduslive/config_flow.py index 712f25560cd..18ae324a572 100644 --- a/homeassistant/components/tellduslive/config_flow.py +++ b/homeassistant/components/tellduslive/config_flow.py @@ -92,7 +92,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): errors["base"] = "invalid_auth" try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): auth_url = await self.hass.async_add_executor_job(self._get_auth_url) if not auth_url: return self.async_abort(reason="unknown_authorize_url_generation") diff --git a/homeassistant/components/thethingsnetwork/sensor.py b/homeassistant/components/thethingsnetwork/sensor.py index 792eaa0170c..2431d1e2022 100644 --- a/homeassistant/components/thethingsnetwork/sensor.py +++ b/homeassistant/components/thethingsnetwork/sensor.py @@ -124,7 +124,7 @@ class TtnDataStorage: """Get the current state from The Things Network Data Storage.""" try: session = async_get_clientsession(self._hass) - with async_timeout.timeout(DEFAULT_TIMEOUT): + async with async_timeout.timeout(DEFAULT_TIMEOUT): response = await session.get(self._url, headers=self._headers) except (asyncio.TimeoutError, aiohttp.ClientError): diff --git a/homeassistant/components/tradfri/config_flow.py b/homeassistant/components/tradfri/config_flow.py index 11a56200eda..4de2aa302f0 100644 --- a/homeassistant/components/tradfri/config_flow.py +++ b/homeassistant/components/tradfri/config_flow.py @@ -174,7 +174,7 @@ async def authenticate( api_factory = await APIFactory.init(host, psk_id=identity) try: - with async_timeout.timeout(5): + async with async_timeout.timeout(5): key = await api_factory.generate_psk(security_code) except RequestError as err: raise AuthError("invalid_security_code") from err diff --git a/homeassistant/components/unifi/controller.py b/homeassistant/components/unifi/controller.py index b1ebbbe3475..14df45e3aeb 100644 --- a/homeassistant/components/unifi/controller.py +++ b/homeassistant/components/unifi/controller.py @@ -419,7 +419,7 @@ class UniFiController: async def async_reconnect(self) -> None: """Try to reconnect UniFi session.""" try: - with async_timeout.timeout(5): + async with async_timeout.timeout(5): await self.api.login() self.api.start_websocket() @@ -488,7 +488,7 @@ async def get_controller( ) try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): await controller.check_unifi_os() await controller.login() return controller diff --git a/homeassistant/components/updater/__init__.py b/homeassistant/components/updater/__init__.py index f624cf87eda..1d86dbaea8e 100644 --- a/homeassistant/components/updater/__init__.py +++ b/homeassistant/components/updater/__init__.py @@ -125,7 +125,7 @@ async def get_newest_version(hass): """Get the newest Home Assistant version.""" session = async_get_clientsession(hass) - with async_timeout.timeout(30): + async with async_timeout.timeout(30): req = await session.get(UPDATER_URL) try: diff --git a/homeassistant/components/viaggiatreno/sensor.py b/homeassistant/components/viaggiatreno/sensor.py index 0457572e066..c80f4ef42c3 100644 --- a/homeassistant/components/viaggiatreno/sensor.py +++ b/homeassistant/components/viaggiatreno/sensor.py @@ -70,7 +70,7 @@ async def async_http_request(hass, uri): """Perform actual request.""" try: session = hass.helpers.aiohttp_client.async_get_clientsession(hass) - with async_timeout.timeout(REQUEST_TIMEOUT): + async with async_timeout.timeout(REQUEST_TIMEOUT): req = await session.get(uri) if req.status != HTTPStatus.OK: return {"error": req.status} diff --git a/homeassistant/components/voicerss/tts.py b/homeassistant/components/voicerss/tts.py index 3558179c4d1..2525393739b 100644 --- a/homeassistant/components/voicerss/tts.py +++ b/homeassistant/components/voicerss/tts.py @@ -196,7 +196,7 @@ class VoiceRSSProvider(Provider): form_data["hl"] = language try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): request = await websession.post(VOICERSS_API_URL, data=form_data) if request.status != HTTPStatus.OK: diff --git a/homeassistant/components/websocket_api/http.py b/homeassistant/components/websocket_api/http.py index 22fa9816f4e..b657b5f5d94 100644 --- a/homeassistant/components/websocket_api/http.py +++ b/homeassistant/components/websocket_api/http.py @@ -176,7 +176,7 @@ class WebSocketHandler: # Auth Phase try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): msg = await wsock.receive() except asyncio.TimeoutError as err: disconnect_warn = "Did not receive auth message within 10 seconds" diff --git a/homeassistant/components/worxlandroid/sensor.py b/homeassistant/components/worxlandroid/sensor.py index 464892e9126..98b7470b7a8 100644 --- a/homeassistant/components/worxlandroid/sensor.py +++ b/homeassistant/components/worxlandroid/sensor.py @@ -85,7 +85,7 @@ class WorxLandroidSensor(SensorEntity): try: session = async_get_clientsession(self.hass) - with async_timeout.timeout(self.timeout): + async with async_timeout.timeout(self.timeout): auth = aiohttp.helpers.BasicAuth("admin", self.pin) mower_response = await session.get(self.url, auth=auth) except (asyncio.TimeoutError, aiohttp.ClientError): diff --git a/homeassistant/components/yandextts/tts.py b/homeassistant/components/yandextts/tts.py index ec0868b2443..4cbbc679e42 100644 --- a/homeassistant/components/yandextts/tts.py +++ b/homeassistant/components/yandextts/tts.py @@ -121,7 +121,7 @@ class YandexSpeechKitProvider(Provider): options = options or {} try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): url_param = { "text": message, "lang": actual_language, diff --git a/homeassistant/core.py b/homeassistant/core.py index 34b48e66953..891d718a81f 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -25,7 +25,7 @@ import attr import voluptuous as vol import yarl -from homeassistant import block_async_io, loader, util +from homeassistant import async_timeout_backcompat, block_async_io, loader, util from homeassistant.const import ( ATTR_DOMAIN, ATTR_FRIENDLY_NAME, @@ -82,7 +82,7 @@ STAGE_1_SHUTDOWN_TIMEOUT = 100 STAGE_2_SHUTDOWN_TIMEOUT = 60 STAGE_3_SHUTDOWN_TIMEOUT = 30 - +async_timeout_backcompat.enable() block_async_io.enable() T = TypeVar("T") diff --git a/homeassistant/helpers/aiohttp_client.py b/homeassistant/helpers/aiohttp_client.py index 3e5496b4179..908a9d68ddf 100644 --- a/homeassistant/helpers/aiohttp_client.py +++ b/homeassistant/helpers/aiohttp_client.py @@ -123,7 +123,7 @@ async def async_aiohttp_proxy_web( ) -> web.StreamResponse | None: """Stream websession request to aiohttp web response.""" try: - with async_timeout.timeout(timeout): + async with async_timeout.timeout(timeout): req = await web_coro except asyncio.CancelledError: @@ -164,7 +164,7 @@ async def async_aiohttp_proxy_stream( # Suppressing something went wrong fetching data, closed connection with suppress(asyncio.TimeoutError, aiohttp.ClientError): while hass.is_running: - with async_timeout.timeout(timeout): + async with async_timeout.timeout(timeout): data = await stream.read(buffer_size) if not data: diff --git a/homeassistant/helpers/config_entry_oauth2_flow.py b/homeassistant/helpers/config_entry_oauth2_flow.py index 42478e67bb9..3c987b1ea9e 100644 --- a/homeassistant/helpers/config_entry_oauth2_flow.py +++ b/homeassistant/helpers/config_entry_oauth2_flow.py @@ -270,7 +270,7 @@ class AbstractOAuth2FlowHandler(config_entries.ConfigFlow, metaclass=ABCMeta): return self.async_external_step_done(next_step_id="creation") try: - with async_timeout.timeout(10): + async with async_timeout.timeout(10): url = await self.flow_impl.async_generate_authorize_url(self.flow_id) except asyncio.TimeoutError: return self.async_abort(reason="authorize_url_timeout") diff --git a/homeassistant/helpers/script.py b/homeassistant/helpers/script.py index a79caad74b0..6a727aefb4d 100644 --- a/homeassistant/helpers/script.py +++ b/homeassistant/helpers/script.py @@ -476,7 +476,10 @@ class _ScriptRun: def async_script_wait(entity_id, from_s, to_s): """Handle script after template condition is true.""" wait_var = self._variables["wait"] - wait_var["remaining"] = to_context.remaining if to_context else timeout + if to_context and to_context.deadline: + wait_var["remaining"] = to_context.deadline - self._hass.loop.time() + else: + wait_var["remaining"] = timeout wait_var["completed"] = True done.set() @@ -777,7 +780,10 @@ class _ScriptRun: async def async_done(variables, context=None): wait_var = self._variables["wait"] - wait_var["remaining"] = to_context.remaining if to_context else timeout + if to_context and to_context.deadline: + wait_var["remaining"] = to_context.deadline - self._hass.loop.time() + else: + wait_var["remaining"] = timeout wait_var["trigger"] = variables["trigger"] done.set() diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 20b6a257213..32a75ef29d0 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -1,11 +1,11 @@ PyJWT==2.1.0 PyNaCl==1.4.0 aiodiscover==1.4.5 -aiohttp==3.7.4.post0 +aiohttp==3.8.0 aiohttp_cors==0.7.0 astral==2.2 async-upnp-client==0.22.11 -async_timeout==3.0.1 +async_timeout==4.0.0 attrs==21.2.0 awesomeversion==21.10.1 backports.zoneinfo;python_version<"3.9" diff --git a/requirements.txt b/requirements.txt index 84f3e342435..d89db253e06 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ -c homeassistant/package_constraints.txt # Home Assistant Core -aiohttp==3.7.4.post0 +aiohttp==3.8.0 astral==2.2 -async_timeout==3.0.1 +async_timeout==4.0.0 attrs==21.2.0 awesomeversion==21.10.1 backports.zoneinfo;python_version<"3.9" diff --git a/setup.py b/setup.py index 2834a0b973d..647d4c50190 100755 --- a/setup.py +++ b/setup.py @@ -32,9 +32,9 @@ PROJECT_URLS = { PACKAGES = find_packages(exclude=["tests", "tests.*"]) REQUIRES = [ - "aiohttp==3.7.4.post0", + "aiohttp==3.8.0", "astral==2.2", - "async_timeout==3.0.1", + "async_timeout==4.0.0", "attrs==21.2.0", "awesomeversion==21.10.1", 'backports.zoneinfo;python_version<"3.9"', diff --git a/tests/components/cloud/test_http_api.py b/tests/components/cloud/test_http_api.py index 566f2041fdd..947a8e0125c 100644 --- a/tests/components/cloud/test_http_api.py +++ b/tests/components/cloud/test_http_api.py @@ -119,7 +119,7 @@ async def test_login_view(hass, cloud_client): async def test_login_view_random_exception(cloud_client): """Try logging in with invalid JSON.""" - with patch("async_timeout.timeout", side_effect=ValueError("Boom")): + with patch("hass_nabucasa.Cloud.login", side_effect=ValueError("Boom")): req = await cloud_client.post( "/api/cloud/login", json={"email": "my_username", "password": "my_password"} ) diff --git a/tests/components/generic/test_camera.py b/tests/components/generic/test_camera.py index 9f72520105e..c52b4bf6e8f 100644 --- a/tests/components/generic/test_camera.py +++ b/tests/components/generic/test_camera.py @@ -3,7 +3,9 @@ import asyncio from http import HTTPStatus from unittest.mock import patch +import aiohttp import httpx +import pytest import respx from homeassistant import config as hass_config @@ -132,10 +134,13 @@ async def test_limit_refetch(hass, hass_client): hass.states.async_set("sensor.temp", "5") - with patch("async_timeout.timeout", side_effect=asyncio.TimeoutError()): + with pytest.raises(aiohttp.ServerTimeoutError), patch( + "async_timeout.timeout", side_effect=asyncio.TimeoutError() + ): resp = await client.get("/api/camera_proxy/camera.config_test") - assert respx.calls.call_count == 0 - assert resp.status == HTTPStatus.INTERNAL_SERVER_ERROR + + assert respx.calls.call_count == 0 + assert resp.status == HTTPStatus.INTERNAL_SERVER_ERROR hass.states.async_set("sensor.temp", "10") diff --git a/tests/components/hyperion/test_camera.py b/tests/components/hyperion/test_camera.py index a32663d7725..2ab16fb1301 100644 --- a/tests/components/hyperion/test_camera.py +++ b/tests/components/hyperion/test_camera.py @@ -121,7 +121,7 @@ async def test_camera_image_failed_start_stream_call(hass: HomeAssistant) -> Non await setup_test_config_entry(hass, hyperion_client=client) with pytest.raises(HomeAssistantError): - await async_get_image(hass, TEST_CAMERA_ENTITY_ID, timeout=0) + await async_get_image(hass, TEST_CAMERA_ENTITY_ID, timeout=0.01) assert client.async_send_image_stream_start.called assert not client.async_send_image_stream_stop.called diff --git a/tests/components/stream/conftest.py b/tests/components/stream/conftest.py index f5f66258f70..58c69218f14 100644 --- a/tests/components/stream/conftest.py +++ b/tests/components/stream/conftest.py @@ -95,13 +95,13 @@ class SaveRecordWorkerSync: async def get_segments(self): """Return the recorded video segments.""" - with async_timeout.timeout(TEST_TIMEOUT): + async with async_timeout.timeout(TEST_TIMEOUT): await self._save_event.wait() return self._segments async def join(self): """Verify save worker was invoked and block on shutdown.""" - with async_timeout.timeout(TEST_TIMEOUT): + async with async_timeout.timeout(TEST_TIMEOUT): await self._save_event.wait() self._save_thread.join(timeout=TEST_TIMEOUT) assert not self._save_thread.is_alive() diff --git a/tests/components/websocket_api/test_commands.py b/tests/components/websocket_api/test_commands.py index 447f38f9a9c..1099519a2a0 100644 --- a/tests/components/websocket_api/test_commands.py +++ b/tests/components/websocket_api/test_commands.py @@ -369,7 +369,7 @@ async def test_subscribe_unsubscribe_events(hass, websocket_client): hass.bus.async_fire("test_event", {"hello": "world"}) hass.bus.async_fire("ignore_event") - with timeout(3): + async with timeout(3): msg = await websocket_client.receive_json() assert msg["id"] == 5 @@ -566,7 +566,7 @@ async def test_subscribe_unsubscribe_events_whitelist( hass.bus.async_fire("themes_updated") - with timeout(3): + async with timeout(3): msg = await websocket_client.receive_json() assert msg["id"] == 6 @@ -1051,7 +1051,7 @@ async def test_subscribe_trigger(hass, websocket_client): hass.bus.async_fire("test_event", {"hello": "world"}, context=context) hass.bus.async_fire("ignore_event") - with timeout(3): + async with timeout(3): msg = await websocket_client.receive_json() assert msg["id"] == 5 diff --git a/tests/helpers/test_script.py b/tests/helpers/test_script.py index fd98145cab2..a3bf128d3c4 100644 --- a/tests/helpers/test_script.py +++ b/tests/helpers/test_script.py @@ -858,7 +858,7 @@ async def test_wait_basic_times_out(hass, action_type): assert script_obj.last_action == wait_alias hass.states.async_set("switch.test", "not_on") - with timeout(0.1): + async with timeout(0.1): await hass.async_block_till_done() except asyncio.TimeoutError: timed_out = True @@ -1238,7 +1238,7 @@ async def test_wait_template_with_utcnow_no_match(hass): ): async_fire_time_changed(hass, second_non_matching_time) - with timeout(0.1): + async with timeout(0.1): await hass.async_block_till_done() except asyncio.TimeoutError: timed_out = True