diff --git a/homeassistant/auth/mfa_modules/__init__.py b/homeassistant/auth/mfa_modules/__init__.py index c2ec2260cf2..6e4b189bf74 100644 --- a/homeassistant/auth/mfa_modules/__init__.py +++ b/homeassistant/auth/mfa_modules/__init__.py @@ -150,7 +150,9 @@ async def _load_mfa_module(hass: HomeAssistant, module_name: str) -> types.Modul module = importlib.import_module(module_path) except ImportError as err: _LOGGER.error("Unable to load mfa module %s: %s", module_name, err) - raise HomeAssistantError(f"Unable to load mfa module {module_name}: {err}") + raise HomeAssistantError( + f"Unable to load mfa module {module_name}: {err}" + ) from err if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"): return module diff --git a/homeassistant/auth/providers/__init__.py b/homeassistant/auth/providers/__init__.py index 35208bd847c..b60fa8eff9c 100644 --- a/homeassistant/auth/providers/__init__.py +++ b/homeassistant/auth/providers/__init__.py @@ -146,7 +146,9 @@ async def load_auth_provider_module( module = importlib.import_module(f"homeassistant.auth.providers.{provider}") except ImportError as err: _LOGGER.error("Unable to load auth provider %s: %s", provider, err) - raise HomeAssistantError(f"Unable to load auth provider {provider}: {err}") + raise HomeAssistantError( + f"Unable to load auth provider {provider}: {err}" + ) from err if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"): return module diff --git a/homeassistant/auth/providers/command_line.py b/homeassistant/auth/providers/command_line.py index 961e1014c5e..d194d8119d1 100644 --- a/homeassistant/auth/providers/command_line.py +++ b/homeassistant/auth/providers/command_line.py @@ -71,7 +71,7 @@ class CommandLineAuthProvider(AuthProvider): except OSError as err: # happens when command doesn't exist or permission is denied _LOGGER.error("Error while authenticating %r: %s", username, err) - raise InvalidAuthError + raise InvalidAuthError from err if process.returncode != 0: _LOGGER.error( diff --git a/homeassistant/components/abode/__init__.py b/homeassistant/components/abode/__init__.py index 92665bc1890..2ac52c87131 100644 --- a/homeassistant/components/abode/__init__.py +++ b/homeassistant/components/abode/__init__.py @@ -120,7 +120,7 @@ async def async_setup_entry(hass, config_entry): except (AbodeException, ConnectTimeout, HTTPError) as ex: LOGGER.error("Unable to connect to Abode: %s", str(ex)) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex for platform in ABODE_PLATFORMS: hass.async_create_task( diff --git a/homeassistant/components/accuweather/__init__.py b/homeassistant/components/accuweather/__init__.py index 1e1a434a036..c8ae14678d5 100644 --- a/homeassistant/components/accuweather/__init__.py +++ b/homeassistant/components/accuweather/__init__.py @@ -127,6 +127,6 @@ class AccuWeatherDataUpdateCoordinator(DataUpdateCoordinator): InvalidApiKeyError, RequestsExceededError, ) as error: - raise UpdateFailed(error) + raise UpdateFailed(error) from error _LOGGER.debug("Requests remaining: %s", self.accuweather.requests_remaining) return {**current, **{ATTR_FORECAST: forecast}} diff --git a/homeassistant/components/agent_dvr/__init__.py b/homeassistant/components/agent_dvr/__init__.py index cc72b1e33ae..878a100684f 100644 --- a/homeassistant/components/agent_dvr/__init__.py +++ b/homeassistant/components/agent_dvr/__init__.py @@ -33,9 +33,9 @@ async def async_setup_entry(hass, config_entry): agent_client = Agent(server_origin, async_get_clientsession(hass)) try: await agent_client.update() - except AgentError: + except AgentError as err: await agent_client.close() - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err if not agent_client.is_available: raise ConfigEntryNotReady diff --git a/homeassistant/components/airly/__init__.py b/homeassistant/components/airly/__init__.py index 85071925357..de09d767b1f 100644 --- a/homeassistant/components/airly/__init__.py +++ b/homeassistant/components/airly/__init__.py @@ -125,7 +125,7 @@ class AirlyDataUpdateCoordinator(DataUpdateCoordinator): try: await measurements.update() except (AirlyError, ClientConnectorError) as error: - raise UpdateFailed(error) + raise UpdateFailed(error) from error values = measurements.current["values"] index = measurements.current["indexes"][0] diff --git a/homeassistant/components/airvisual/__init__.py b/homeassistant/components/airvisual/__init__.py index 3449d5e865f..4e748766425 100644 --- a/homeassistant/components/airvisual/__init__.py +++ b/homeassistant/components/airvisual/__init__.py @@ -227,7 +227,7 @@ async def async_setup_entry(hass, config_entry): try: return await api_coro except AirVisualError as err: - raise UpdateFailed(f"Error while retrieving data: {err}") + raise UpdateFailed(f"Error while retrieving data: {err}") from err coordinator = DataUpdateCoordinator( hass, @@ -263,7 +263,7 @@ async def async_setup_entry(hass, config_entry): include_trends=False, ) except NodeProError as err: - raise UpdateFailed(f"Error while retrieving data: {err}") + raise UpdateFailed(f"Error while retrieving data: {err}") from err coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/alexa/handlers.py b/homeassistant/components/alexa/handlers.py index 7737016d573..6eeb3235a64 100644 --- a/homeassistant/components/alexa/handlers.py +++ b/homeassistant/components/alexa/handlers.py @@ -1542,8 +1542,10 @@ async def async_api_initialize_camera_stream(hass, config, directive, context): require_ssl=True, require_standard_port=True, ) - except network.NoURLAvailableError: - raise AlexaInvalidValueError("Failed to find suitable URL to serve to Alexa") + except network.NoURLAvailableError as err: + raise AlexaInvalidValueError( + "Failed to find suitable URL to serve to Alexa" + ) from err payload = { "cameraStreams": [ diff --git a/homeassistant/components/almond/__init__.py b/homeassistant/components/almond/__init__.py index 2117f809b04..b9f75ff8c6b 100644 --- a/homeassistant/components/almond/__init__.py +++ b/homeassistant/components/almond/__init__.py @@ -208,7 +208,7 @@ async def _configure_almond_for_ha( msg = err _LOGGER.warning("Unable to configure Almond: %s", msg) await hass.auth.async_remove_refresh_token(refresh_token) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err # Clear all other refresh tokens for token in list(user.refresh_tokens.values()): diff --git a/homeassistant/components/ambient_station/__init__.py b/homeassistant/components/ambient_station/__init__.py index 89b6236d392..b3f4aeec3bd 100644 --- a/homeassistant/components/ambient_station/__init__.py +++ b/homeassistant/components/ambient_station/__init__.py @@ -300,7 +300,7 @@ async def async_setup_entry(hass, config_entry): hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = ambient except WebsocketError as err: _LOGGER.error("Config entry failed: %s", err) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err hass.bus.async_listen_once( EVENT_HOMEASSISTANT_STOP, ambient.client.websocket.disconnect() diff --git a/homeassistant/components/api/__init__.py b/homeassistant/components/api/__init__.py index 001ce5d2a4e..c1f692a76ad 100644 --- a/homeassistant/components/api/__init__.py +++ b/homeassistant/components/api/__init__.py @@ -375,8 +375,8 @@ class APIDomainServicesView(HomeAssistantView): await hass.services.async_call( domain, service, data, True, self.context(request) ) - except (vol.Invalid, ServiceNotFound): - raise HTTPBadRequest() + except (vol.Invalid, ServiceNotFound) as ex: + raise HTTPBadRequest() from ex return self.json(changed_states) diff --git a/homeassistant/components/asterisk_mbox/mailbox.py b/homeassistant/components/asterisk_mbox/mailbox.py index b3863eeb13f..62d817df9a3 100644 --- a/homeassistant/components/asterisk_mbox/mailbox.py +++ b/homeassistant/components/asterisk_mbox/mailbox.py @@ -60,7 +60,7 @@ class AsteriskMailbox(Mailbox): partial(client.mp3, msgid, sync=True) ) except ServerError as err: - raise StreamError(err) + raise StreamError(err) from err async def async_get_messages(self): """Return a list of the current messages.""" diff --git a/homeassistant/components/atag/__init__.py b/homeassistant/components/atag/__init__.py index 237a82f207a..e5d06c08756 100644 --- a/homeassistant/components/atag/__init__.py +++ b/homeassistant/components/atag/__init__.py @@ -66,7 +66,7 @@ class AtagDataUpdateCoordinator(DataUpdateCoordinator): if not await self.atag.update(): raise UpdateFailed("No data received") except AtagException as error: - raise UpdateFailed(error) + raise UpdateFailed(error) from error return self.atag.report diff --git a/homeassistant/components/aten_pe/switch.py b/homeassistant/components/aten_pe/switch.py index e5970fc4d3b..1bf54085064 100644 --- a/homeassistant/components/aten_pe/switch.py +++ b/homeassistant/components/aten_pe/switch.py @@ -55,7 +55,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= outlets = dev.outlets() except AtenPEError as exc: _LOGGER.error("Failed to initialize %s:%s: %s", node, serv, str(exc)) - raise PlatformNotReady + raise PlatformNotReady from exc switches = [] async for outlet in outlets: diff --git a/homeassistant/components/august/__init__.py b/homeassistant/components/august/__init__.py index 9e0222dc81d..e0d7749dcbb 100644 --- a/homeassistant/components/august/__init__.py +++ b/homeassistant/components/august/__init__.py @@ -171,8 +171,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): try: await august_gateway.async_setup(entry.data) return await async_setup_august(hass, entry, august_gateway) - except asyncio.TimeoutError: - raise ConfigEntryNotReady + except asyncio.TimeoutError as err: + raise ConfigEntryNotReady from err async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): @@ -339,7 +339,7 @@ class AugustData(AugustSubscriberMixin): device_name = self._get_device_name(device_id) if device_name is None: device_name = f"DeviceID: {device_id}" - raise HomeAssistantError(f"{device_name}: {err}") + raise HomeAssistantError(f"{device_name}: {err}") from err return ret diff --git a/homeassistant/components/august/gateway.py b/homeassistant/components/august/gateway.py index 272c50ac02a..6918907611f 100644 --- a/homeassistant/components/august/gateway.py +++ b/homeassistant/components/august/gateway.py @@ -102,7 +102,7 @@ class AugustGateway: self._authentication = await self.authenticator.async_authenticate() except ClientError as ex: _LOGGER.error("Unable to connect to August service: %s", str(ex)) - raise CannotConnect + raise CannotConnect from ex if self._authentication.state == AuthenticationState.BAD_PASSWORD: raise InvalidAuth diff --git a/homeassistant/components/auth/indieauth.py b/homeassistant/components/auth/indieauth.py index 0d942bd358d..e823659f62b 100644 --- a/homeassistant/components/auth/indieauth.py +++ b/homeassistant/components/auth/indieauth.py @@ -170,8 +170,8 @@ def _parse_client_id(client_id): try: # parts raises ValueError when port cannot be parsed as int parts.port - except ValueError: - raise ValueError("Client ID contains invalid port") + except ValueError as ex: + raise ValueError("Client ID contains invalid port") from ex # Additionally, hostnames # MUST be domain names or a loopback interface and diff --git a/homeassistant/components/awair/__init__.py b/homeassistant/components/awair/__init__.py index 2ae436bebba..56af5d2b662 100644 --- a/homeassistant/components/awair/__init__.py +++ b/homeassistant/components/awair/__init__.py @@ -102,9 +102,9 @@ class AwairDataUpdateCoordinator(DataUpdateCoordinator): ) ) - raise UpdateFailed(err) + raise UpdateFailed(err) from err except Exception as err: - raise UpdateFailed(err) + raise UpdateFailed(err) from err async def _fetch_air_data(self, device): """Fetch latest air quality data.""" diff --git a/homeassistant/components/axis/device.py b/homeassistant/components/axis/device.py index 18845ce12a3..a22fea23e79 100644 --- a/homeassistant/components/axis/device.py +++ b/homeassistant/components/axis/device.py @@ -186,8 +186,8 @@ class AxisNetworkDevice: password=self.config_entry.data[CONF_PASSWORD], ) - except CannotConnect: - raise ConfigEntryNotReady + except CannotConnect as err: + raise ConfigEntryNotReady from err except Exception: # pylint: disable=broad-except LOGGER.error("Unknown error connecting with Axis device on %s", self.host) @@ -271,14 +271,14 @@ async def get_device(hass, host, port, username, password): return device - except axis.Unauthorized: + except axis.Unauthorized as err: LOGGER.warning("Connected to device at %s but not registered.", host) - raise AuthenticationRequired + raise AuthenticationRequired from err - except (asyncio.TimeoutError, axis.RequestError): + except (asyncio.TimeoutError, axis.RequestError) as err: LOGGER.error("Error connecting to the Axis device at %s", host) - raise CannotConnect + raise CannotConnect from err - except axis.AxisException: + except axis.AxisException as err: LOGGER.exception("Unknown Axis communication error occurred") - raise AuthenticationRequired + raise AuthenticationRequired from err diff --git a/homeassistant/components/blink/config_flow.py b/homeassistant/components/blink/config_flow.py index 63c822cfd1f..d244c316483 100644 --- a/homeassistant/components/blink/config_flow.py +++ b/homeassistant/components/blink/config_flow.py @@ -26,8 +26,8 @@ def validate_input(hass: core.HomeAssistant, auth): """Validate the user input allows us to connect.""" try: auth.startup() - except (LoginError, TokenRefreshFailed): - raise InvalidAuth + except (LoginError, TokenRefreshFailed) as err: + raise InvalidAuth from err if auth.check_key_required(): raise Require2FA diff --git a/homeassistant/components/bmp280/sensor.py b/homeassistant/components/bmp280/sensor.py index 70efbce7d85..3c34408cb62 100644 --- a/homeassistant/components/bmp280/sensor.py +++ b/homeassistant/components/bmp280/sensor.py @@ -54,7 +54,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): "%s. Hint: Check wiring and make sure that the SDO pin is tied to either ground (0x76) or VCC (0x77)", error.args[0], ) - raise PlatformNotReady() + raise PlatformNotReady() from error _LOGGER.error(error) return # use custom name if there's any diff --git a/homeassistant/components/bond/config_flow.py b/homeassistant/components/bond/config_flow.py index ca8965d4d43..49ca559685c 100644 --- a/homeassistant/components/bond/config_flow.py +++ b/homeassistant/components/bond/config_flow.py @@ -28,15 +28,15 @@ async def _validate_input(data: Dict[str, Any]) -> str: version = await bond.version() # call to non-version API is needed to validate authentication await bond.devices() - except ClientConnectionError: - raise InputValidationError("cannot_connect") + except ClientConnectionError as error: + raise InputValidationError("cannot_connect") from error except ClientResponseError as error: if error.status == 401: - raise InputValidationError("invalid_auth") - raise InputValidationError("unknown") - except Exception: + raise InputValidationError("invalid_auth") from error + raise InputValidationError("unknown") from error + except Exception as error: _LOGGER.exception("Unexpected exception") - raise InputValidationError("unknown") + raise InputValidationError("unknown") from error # Return unique ID from the hub to be stored in the config entry. bond_id = version.get("bondid") diff --git a/homeassistant/components/broadlink/device.py b/homeassistant/components/broadlink/device.py index c8751182cb9..d05fdfd4df6 100644 --- a/homeassistant/components/broadlink/device.py +++ b/homeassistant/components/broadlink/device.py @@ -82,8 +82,8 @@ class BroadlinkDevice: await self._async_handle_auth_error() return False - except (DeviceOfflineError, OSError): - raise ConfigEntryNotReady + except (DeviceOfflineError, OSError) as err: + raise ConfigEntryNotReady from err except BroadlinkException as err: _LOGGER.error( diff --git a/homeassistant/components/broadlink/remote.py b/homeassistant/components/broadlink/remote.py index 10c45fec262..7c1ae7349da 100644 --- a/homeassistant/components/broadlink/remote.py +++ b/homeassistant/components/broadlink/remote.py @@ -175,8 +175,8 @@ class BroadlinkRemote(RemoteEntity, RestoreEntity): try: code = self._codes[device][command] - except KeyError: - raise KeyError("Command not found") + except KeyError as err: + raise KeyError("Command not found") from err # For toggle commands, alternate between codes in a list. if isinstance(code, list): @@ -187,8 +187,8 @@ class BroadlinkRemote(RemoteEntity, RestoreEntity): try: return data_packet(code), is_toggle_cmd - except ValueError: - raise ValueError("Invalid code") + except ValueError as err: + raise ValueError("Invalid code") from err @callback def get_flags(self): diff --git a/homeassistant/components/broadlink/updater.py b/homeassistant/components/broadlink/updater.py index a81cde49737..bd124d1e1ac 100644 --- a/homeassistant/components/broadlink/updater.py +++ b/homeassistant/components/broadlink/updater.py @@ -63,7 +63,7 @@ class BroadlinkUpdateManager(ABC): _LOGGER.warning( "Disconnected from the device at %s", self.device.api.host[0] ) - raise UpdateFailed(err) + raise UpdateFailed(err) from err else: if self.available is False: diff --git a/homeassistant/components/brother/__init__.py b/homeassistant/components/brother/__init__.py index 4c69282a996..d4cd5d4a2b5 100644 --- a/homeassistant/components/brother/__init__.py +++ b/homeassistant/components/brother/__init__.py @@ -82,5 +82,5 @@ class BrotherDataUpdateCoordinator(DataUpdateCoordinator): try: await self.brother.async_update() except (ConnectionError, SnmpError, UnsupportedModel) as error: - raise UpdateFailed(error) + raise UpdateFailed(error) from error return self.brother.data diff --git a/homeassistant/components/camera/__init__.py b/homeassistant/components/camera/__init__.py index bdc94b19eb1..3de47db80d1 100644 --- a/homeassistant/components/camera/__init__.py +++ b/homeassistant/components/camera/__init__.py @@ -539,8 +539,8 @@ class CameraMjpegStream(CameraView): if interval < MIN_STREAM_INTERVAL: raise ValueError(f"Stream interval must be be > {MIN_STREAM_INTERVAL}") return await camera.handle_async_still_stream(request, interval) - except ValueError: - raise web.HTTPBadRequest() + except ValueError as err: + raise web.HTTPBadRequest() from err @websocket_api.async_response diff --git a/homeassistant/components/cert_expiry/__init__.py b/homeassistant/components/cert_expiry/__init__.py index 84629353bce..d01e38a2e2c 100644 --- a/homeassistant/components/cert_expiry/__init__.py +++ b/homeassistant/components/cert_expiry/__init__.py @@ -76,7 +76,7 @@ class CertExpiryDataUpdateCoordinator(DataUpdateCoordinator[datetime]): try: timestamp = await get_cert_expiry_timestamp(self.hass, self.host, self.port) except TemporaryFailure as err: - raise UpdateFailed(err.args[0]) + raise UpdateFailed(err.args[0]) from err except ValidationFailure as err: self.cert_error = err self.is_cert_valid = False diff --git a/homeassistant/components/cert_expiry/helper.py b/homeassistant/components/cert_expiry/helper.py index f4caee8abf2..6c49e9e26b9 100644 --- a/homeassistant/components/cert_expiry/helper.py +++ b/homeassistant/components/cert_expiry/helper.py @@ -28,16 +28,20 @@ async def get_cert_expiry_timestamp(hass, hostname, port): """Return the certificate's expiration timestamp.""" try: cert = await hass.async_add_executor_job(get_cert, hostname, port) - except socket.gaierror: - raise ResolveFailed(f"Cannot resolve hostname: {hostname}") - except socket.timeout: - raise ConnectionTimeout(f"Connection timeout with server: {hostname}:{port}") - except ConnectionRefusedError: - raise ConnectionRefused(f"Connection refused by server: {hostname}:{port}") + except socket.gaierror as err: + raise ResolveFailed(f"Cannot resolve hostname: {hostname}") from err + except socket.timeout as err: + raise ConnectionTimeout( + f"Connection timeout with server: {hostname}:{port}" + ) from err + except ConnectionRefusedError as err: + raise ConnectionRefused( + f"Connection refused by server: {hostname}:{port}" + ) from err except ssl.CertificateError as err: - raise ValidationFailure(err.verify_message) + raise ValidationFailure(err.verify_message) from err except ssl.SSLError as err: - raise ValidationFailure(err.args[0]) + raise ValidationFailure(err.args[0]) from err ts_seconds = ssl.cert_time_to_seconds(cert["notAfter"]) return dt.utc_from_timestamp(ts_seconds) diff --git a/homeassistant/components/citybikes/sensor.py b/homeassistant/components/citybikes/sensor.py index 799fe6acc70..924ef2fa6b4 100644 --- a/homeassistant/components/citybikes/sensor.py +++ b/homeassistant/components/citybikes/sensor.py @@ -225,8 +225,8 @@ class CityBikesNetworks: result = network[ATTR_ID] return result - except CityBikesRequestError: - raise PlatformNotReady + except CityBikesRequestError as err: + raise PlatformNotReady from err finally: self.networks_loading.release() @@ -251,11 +251,11 @@ class CityBikesNetwork: ) self.stations = network[ATTR_NETWORK][ATTR_STATIONS_LIST] self.ready.set() - except CityBikesRequestError: + except CityBikesRequestError as err: if now is not None: self.ready.clear() else: - raise PlatformNotReady + raise PlatformNotReady from err class CityBikesStation(Entity): diff --git a/homeassistant/components/control4/__init__.py b/homeassistant/components/control4/__init__.py index 0f27c678e59..41b71162d6c 100644 --- a/homeassistant/components/control4/__init__.py +++ b/homeassistant/components/control4/__init__.py @@ -59,7 +59,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): await account.getAccountBearerToken() except client_exceptions.ClientError as exception: _LOGGER.error("Error connecting to Control4 account API: %s", exception) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from exception except BadCredentials as exception: _LOGGER.error( "Error authenticating with Control4 account API, incorrect username or password: %s", diff --git a/homeassistant/components/control4/light.py b/homeassistant/components/control4/light.py index 2871da34f11..09e05791169 100644 --- a/homeassistant/components/control4/light.py +++ b/homeassistant/components/control4/light.py @@ -45,14 +45,14 @@ async def async_setup_entry( try: return await director_update_data(hass, entry, CONTROL4_NON_DIMMER_VAR) except C4Exception as err: - raise UpdateFailed(f"Error communicating with API: {err}") + raise UpdateFailed(f"Error communicating with API: {err}") from err async def async_update_data_dimmer(): """Fetch data from Control4 director for dimmer lights.""" try: return await director_update_data(hass, entry, CONTROL4_DIMMER_VAR) except C4Exception as err: - raise UpdateFailed(f"Error communicating with API: {err}") + raise UpdateFailed(f"Error communicating with API: {err}") from err non_dimmer_coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/daikin/__init__.py b/homeassistant/components/daikin/__init__.py index 49a939b8c72..65a3bf28c3b 100644 --- a/homeassistant/components/daikin/__init__.py +++ b/homeassistant/components/daikin/__init__.py @@ -114,12 +114,12 @@ async def daikin_api_setup(hass, host, key, uuid, password): device = await Appliance.factory( host, session, key=key, uuid=uuid, password=password ) - except asyncio.TimeoutError: + except asyncio.TimeoutError as err: _LOGGER.debug("Connection to %s timed out", host) - raise ConfigEntryNotReady - except ClientConnectionError: + raise ConfigEntryNotReady from err + except ClientConnectionError as err: _LOGGER.debug("ClientConnectionError to %s", host) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err except Exception: # pylint: disable=broad-except _LOGGER.error("Unexpected error creating device %s", host) return None diff --git a/homeassistant/components/deconz/gateway.py b/homeassistant/components/deconz/gateway.py index 6ef68b43f64..828f65c9811 100644 --- a/homeassistant/components/deconz/gateway.py +++ b/homeassistant/components/deconz/gateway.py @@ -98,8 +98,8 @@ class DeconzGateway: self.async_connection_status_callback, ) - except CannotConnect: - raise ConfigEntryNotReady + except CannotConnect as err: + raise ConfigEntryNotReady from err except Exception as err: # pylint: disable=broad-except LOGGER.error("Error connecting with deCONZ gateway: %s", err) @@ -254,10 +254,10 @@ async def get_gateway( await deconz.initialize() return deconz - except errors.Unauthorized: + except errors.Unauthorized as err: LOGGER.warning("Invalid key for deCONZ at %s", config[CONF_HOST]) - raise AuthenticationRequired + raise AuthenticationRequired from err - except (asyncio.TimeoutError, errors.RequestError): + except (asyncio.TimeoutError, errors.RequestError) as err: LOGGER.error("Error connecting to deCONZ gateway at %s", config[CONF_HOST]) - raise CannotConnect + raise CannotConnect from err diff --git a/homeassistant/components/deluge/sensor.py b/homeassistant/components/deluge/sensor.py index 4a24e979607..5e8df89c20d 100644 --- a/homeassistant/components/deluge/sensor.py +++ b/homeassistant/components/deluge/sensor.py @@ -58,9 +58,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): deluge_api = DelugeRPCClient(host, port, username, password) try: deluge_api.connect() - except ConnectionRefusedError: + except ConnectionRefusedError as err: _LOGGER.error("Connection to Deluge Daemon failed") - raise PlatformNotReady + raise PlatformNotReady from err dev = [] for variable in config[CONF_MONITORED_VARIABLES]: dev.append(DelugeSensor(variable, deluge_api, name)) diff --git a/homeassistant/components/deluge/switch.py b/homeassistant/components/deluge/switch.py index 04acf6a9dd9..2aff1b5266c 100644 --- a/homeassistant/components/deluge/switch.py +++ b/homeassistant/components/deluge/switch.py @@ -46,9 +46,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): deluge_api = DelugeRPCClient(host, port, username, password) try: deluge_api.connect() - except ConnectionRefusedError: + except ConnectionRefusedError as err: _LOGGER.error("Connection to Deluge Daemon failed") - raise PlatformNotReady + raise PlatformNotReady from err add_entities([DelugeSwitch(deluge_api, name)]) diff --git a/homeassistant/components/device_automation/__init__.py b/homeassistant/components/device_automation/__init__.py index 33685b2bc1c..1db4af12f22 100644 --- a/homeassistant/components/device_automation/__init__.py +++ b/homeassistant/components/device_automation/__init__.py @@ -83,12 +83,14 @@ async def async_get_device_automation_platform( try: integration = await async_get_integration_with_requirements(hass, domain) platform = integration.get_platform(platform_name) - except IntegrationNotFound: - raise InvalidDeviceAutomationConfig(f"Integration '{domain}' not found") - except ImportError: + except IntegrationNotFound as err: + raise InvalidDeviceAutomationConfig( + f"Integration '{domain}' not found" + ) from err + except ImportError as err: raise InvalidDeviceAutomationConfig( f"Integration '{domain}' does not support device automation {automation_type}s" - ) + ) from err return platform diff --git a/homeassistant/components/devolo_home_control/__init__.py b/homeassistant/components/devolo_home_control/__init__.py index cfe1549f3c4..c955bf77096 100644 --- a/homeassistant/components/devolo_home_control/__init__.py +++ b/homeassistant/components/devolo_home_control/__init__.py @@ -50,8 +50,8 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool hass.data[DOMAIN]["homecontrol"] = await hass.async_add_executor_job( partial(HomeControl, gateway_id=gateway_id, url=mprm_url) ) - except ConnectionError: - raise ConfigEntryNotReady + except ConnectionError as err: + raise ConfigEntryNotReady from err for platform in PLATFORMS: hass.async_create_task( diff --git a/homeassistant/components/dexcom/__init__.py b/homeassistant/components/dexcom/__init__.py index 6c4f8c071a1..c2eb9bd466d 100644 --- a/homeassistant/components/dexcom/__init__.py +++ b/homeassistant/components/dexcom/__init__.py @@ -43,8 +43,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): ) except AccountError: return False - except SessionError: - raise ConfigEntryNotReady + except SessionError as error: + raise ConfigEntryNotReady from error if not entry.options: hass.config_entries.async_update_entry( @@ -55,7 +55,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): try: return await hass.async_add_executor_job(dexcom.get_current_glucose_reading) except SessionError as error: - raise UpdateFailed(error) + raise UpdateFailed(error) from error hass.data[DOMAIN][entry.entry_id] = { COORDINATOR: DataUpdateCoordinator( diff --git a/homeassistant/components/directv/__init__.py b/homeassistant/components/directv/__init__.py index d01f8bd25c9..af27d19cfb0 100644 --- a/homeassistant/components/directv/__init__.py +++ b/homeassistant/components/directv/__init__.py @@ -59,8 +59,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: try: await dtv.update() - except DIRECTVError: - raise ConfigEntryNotReady + except DIRECTVError as err: + raise ConfigEntryNotReady from err hass.data[DOMAIN][entry.entry_id] = dtv diff --git a/homeassistant/components/dlna_dmr/media_player.py b/homeassistant/components/dlna_dmr/media_player.py index 75d88d59c32..acbd69138d4 100644 --- a/homeassistant/components/dlna_dmr/media_player.py +++ b/homeassistant/components/dlna_dmr/media_player.py @@ -182,8 +182,8 @@ async def async_setup_platform( factory = UpnpFactory(requester, disable_state_variable_validation=True) try: upnp_device = await factory.async_create_device(url) - except (asyncio.TimeoutError, aiohttp.ClientError): - raise PlatformNotReady() + except (asyncio.TimeoutError, aiohttp.ClientError) as err: + raise PlatformNotReady() from err # wrap with DmrDevice dlna_device = DmrDevice(upnp_device, event_handler) diff --git a/homeassistant/components/doorbird/__init__.py b/homeassistant/components/doorbird/__init__.py index 8f9ef2a3ed8..43ab0c96153 100644 --- a/homeassistant/components/doorbird/__init__.py +++ b/homeassistant/components/doorbird/__init__.py @@ -132,10 +132,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): "Authorization rejected by DoorBird for %s@%s", username, device_ip ) return False - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err except OSError as oserr: _LOGGER.error("Failed to setup doorbird at %s: %s", device_ip, oserr) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from oserr if not status[0]: _LOGGER.error( diff --git a/homeassistant/components/doorbird/config_flow.py b/homeassistant/components/doorbird/config_flow.py index 52f94116344..07b753da6ee 100644 --- a/homeassistant/components/doorbird/config_flow.py +++ b/homeassistant/components/doorbird/config_flow.py @@ -40,10 +40,10 @@ async def validate_input(hass: core.HomeAssistant, data): info = await hass.async_add_executor_job(device.info) except urllib.error.HTTPError as err: if err.code == 401: - raise InvalidAuth - raise CannotConnect - except OSError: - raise CannotConnect + raise InvalidAuth from err + raise CannotConnect from err + except OSError as err: + raise CannotConnect from err if not status[0]: raise CannotConnect diff --git a/homeassistant/components/ebox/sensor.py b/homeassistant/components/ebox/sensor.py index a8032a4f78a..7bbddb18e7b 100644 --- a/homeassistant/components/ebox/sensor.py +++ b/homeassistant/components/ebox/sensor.py @@ -81,7 +81,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= await ebox_data.async_update() except PyEboxError as exp: _LOGGER.error("Failed login: %s", exp) - raise PlatformNotReady + raise PlatformNotReady from exp sensors = [] for variable in config[CONF_MONITORED_VARIABLES]: diff --git a/homeassistant/components/ebusd/__init__.py b/homeassistant/components/ebusd/__init__.py index a1a7fc88086..855e62727b5 100644 --- a/homeassistant/components/ebusd/__init__.py +++ b/homeassistant/components/ebusd/__init__.py @@ -110,7 +110,7 @@ class EbusdData: self.value[name] = command_result except RuntimeError as err: _LOGGER.error(err) - raise RuntimeError(err) + raise RuntimeError(err) from err def write(self, call): """Call write methon on ebusd.""" diff --git a/homeassistant/components/ecobee/util.py b/homeassistant/components/ecobee/util.py index 2f5d194fec0..ac30b3bb660 100644 --- a/homeassistant/components/ecobee/util.py +++ b/homeassistant/components/ecobee/util.py @@ -8,8 +8,8 @@ def ecobee_date(date_string): """Validate a date_string as valid for the ecobee API.""" try: datetime.strptime(date_string, "%Y-%m-%d") - except ValueError: - raise vol.Invalid("Date does not match ecobee date format YYYY-MM-DD") + except ValueError as err: + raise vol.Invalid("Date does not match ecobee date format YYYY-MM-DD") from err return date_string @@ -17,6 +17,8 @@ def ecobee_time(time_string): """Validate a time_string as valid for the ecobee API.""" try: datetime.strptime(time_string, "%H:%M:%S") - except ValueError: - raise vol.Invalid("Time does not match ecobee 24-hour time format HH:MM:SS") + except ValueError as err: + raise vol.Invalid( + "Time does not match ecobee 24-hour time format HH:MM:SS" + ) from err return time_string diff --git a/homeassistant/components/ecobee/weather.py b/homeassistant/components/ecobee/weather.py index a7fe8d8a0f8..4ea90d27106 100644 --- a/homeassistant/components/ecobee/weather.py +++ b/homeassistant/components/ecobee/weather.py @@ -50,8 +50,8 @@ class EcobeeWeather(WeatherEntity): try: forecast = self.weather["forecasts"][index] return forecast[param] - except (ValueError, IndexError, KeyError): - raise ValueError + except (IndexError, KeyError) as err: + raise ValueError from err @property def name(self): diff --git a/homeassistant/components/everlights/light.py b/homeassistant/components/everlights/light.py index b1a210b8d15..243bd2913b1 100644 --- a/homeassistant/components/everlights/light.py +++ b/homeassistant/components/everlights/light.py @@ -55,8 +55,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= effects = await api.get_all_patterns() - except pyeverlights.ConnectionError: - raise PlatformNotReady + except pyeverlights.ConnectionError as err: + raise PlatformNotReady from err else: lights.append(EverLightsLight(api, pyeverlights.ZONE_1, status, effects)) diff --git a/homeassistant/components/flick_electric/config_flow.py b/homeassistant/components/flick_electric/config_flow.py index 8e6020ebd8a..2dba50cccca 100644 --- a/homeassistant/components/flick_electric/config_flow.py +++ b/homeassistant/components/flick_electric/config_flow.py @@ -48,10 +48,10 @@ class FlickConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): try: with async_timeout.timeout(60): token = await auth.async_get_access_token() - except asyncio.TimeoutError: - raise CannotConnect() - except AuthException: - raise InvalidAuth() + except asyncio.TimeoutError as err: + raise CannotConnect() from err + except AuthException as err: + raise InvalidAuth() from err else: return token is not None diff --git a/homeassistant/components/flo/__init__.py b/homeassistant/components/flo/__init__.py index 6bbadf0e89d..2233b4aa0c3 100644 --- a/homeassistant/components/flo/__init__.py +++ b/homeassistant/components/flo/__init__.py @@ -36,8 +36,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): hass.data[DOMAIN][entry.entry_id]["client"] = client = await async_get_api( entry.data[CONF_USERNAME], entry.data[CONF_PASSWORD], session=session ) - except RequestError: - raise ConfigEntryNotReady + except RequestError as err: + raise ConfigEntryNotReady from err user_info = await client.user.get_info(include_location_info=True) diff --git a/homeassistant/components/flo/config_flow.py b/homeassistant/components/flo/config_flow.py index 24208aa16a8..b509c894068 100644 --- a/homeassistant/components/flo/config_flow.py +++ b/homeassistant/components/flo/config_flow.py @@ -29,7 +29,7 @@ async def validate_input(hass: core.HomeAssistant, data): ) except RequestError as request_error: _LOGGER.error("Error connecting to the Flo API: %s", request_error) - raise CannotConnect + raise CannotConnect from request_error user_info = await api.user.get_info() a_location_id = user_info["locations"][0]["id"] diff --git a/homeassistant/components/flo/device.py b/homeassistant/components/flo/device.py index 179a293ba20..1a01f45b641 100644 --- a/homeassistant/components/flo/device.py +++ b/homeassistant/components/flo/device.py @@ -46,7 +46,7 @@ class FloDeviceDataUpdateCoordinator(DataUpdateCoordinator): *[self._update_device(), self._update_consumption_data()] ) except (RequestError) as error: - raise UpdateFailed(error) + raise UpdateFailed(error) from error @property def location_id(self) -> str: diff --git a/homeassistant/components/flume/__init__.py b/homeassistant/components/flume/__init__.py index 513f77edfb2..b9a5fc17682 100644 --- a/homeassistant/components/flume/__init__.py +++ b/homeassistant/components/flume/__init__.py @@ -67,8 +67,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): http_session=http_session, ) ) - except RequestException: - raise ConfigEntryNotReady + except RequestException as ex: + raise ConfigEntryNotReady from ex except Exception as ex: # pylint: disable=broad-except _LOGGER.error("Invalid credentials for flume: %s", ex) return False diff --git a/homeassistant/components/flume/config_flow.py b/homeassistant/components/flume/config_flow.py index f26be5f1e1d..80f1698a7e6 100644 --- a/homeassistant/components/flume/config_flow.py +++ b/homeassistant/components/flume/config_flow.py @@ -57,10 +57,10 @@ async def validate_input(hass: core.HomeAssistant, data): ) ) flume_devices = await hass.async_add_executor_job(FlumeDeviceList, flume_auth) - except RequestException: - raise CannotConnect - except Exception: # pylint: disable=broad-except - raise InvalidAuth + except RequestException as err: + raise CannotConnect from err + except Exception as err: # pylint: disable=broad-except + raise InvalidAuth from err if not flume_devices or not flume_devices.device_list: raise CannotConnect diff --git a/homeassistant/components/flunearyou/__init__.py b/homeassistant/components/flunearyou/__init__.py index 5e7ebd90cf1..4dae0b3f7cd 100644 --- a/homeassistant/components/flunearyou/__init__.py +++ b/homeassistant/components/flunearyou/__init__.py @@ -52,8 +52,8 @@ def async_get_api_category(sensor_type): if sensor[0] == sensor_type ) ) - except StopIteration: - raise ValueError(f"Can't find category sensor type: {sensor_type}") + except StopIteration as err: + raise ValueError(f"Can't find category sensor type: {sensor_type}") from err async def async_setup(hass, config): diff --git a/homeassistant/components/foobot/sensor.py b/homeassistant/components/foobot/sensor.py index b1d6fefaa3d..3e71963a009 100644 --- a/homeassistant/components/foobot/sensor.py +++ b/homeassistant/components/foobot/sensor.py @@ -82,9 +82,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= asyncio.TimeoutError, FoobotClient.TooManyRequests, FoobotClient.InternalError, - ): + ) as err: _LOGGER.exception("Failed to connect to foobot servers") - raise PlatformNotReady + raise PlatformNotReady from err except FoobotClient.ClientError: _LOGGER.error("Failed to fetch data from foobot servers") return diff --git a/homeassistant/components/garmin_connect/__init__.py b/homeassistant/components/garmin_connect/__init__.py index 85e8132bf02..c0a1012f051 100644 --- a/homeassistant/components/garmin_connect/__init__.py +++ b/homeassistant/components/garmin_connect/__init__.py @@ -49,7 +49,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): _LOGGER.error( "Connection error occurred during Garmin Connect login request: %s", err ) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err except Exception: # pylint: disable=broad-except _LOGGER.exception("Unknown error occurred during Garmin Connect login request") return False diff --git a/homeassistant/components/gios/__init__.py b/homeassistant/components/gios/__init__.py index c7e708e3207..ae3030ac88c 100644 --- a/homeassistant/components/gios/__init__.py +++ b/homeassistant/components/gios/__init__.py @@ -69,7 +69,7 @@ class GiosDataUpdateCoordinator(DataUpdateCoordinator): ClientConnectorError, InvalidSensorsData, ) as error: - raise UpdateFailed(error) + raise UpdateFailed(error) from error if not self.gios.data: raise UpdateFailed("Invalid sensors data") return self.gios.data diff --git a/homeassistant/components/glances/__init__.py b/homeassistant/components/glances/__init__.py index d09aa782534..5a0a1f33394 100644 --- a/homeassistant/components/glances/__init__.py +++ b/homeassistant/components/glances/__init__.py @@ -121,9 +121,9 @@ class GlancesData: self.available = True _LOGGER.debug("Successfully connected to Glances") - except exceptions.GlancesApiConnectionError: + except exceptions.GlancesApiConnectionError as err: _LOGGER.debug("Can not connect to Glances") - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err self.add_options() self.set_scan_interval(self.config_entry.options[CONF_SCAN_INTERVAL]) diff --git a/homeassistant/components/glances/config_flow.py b/homeassistant/components/glances/config_flow.py index 3c86fae0357..48352e88543 100644 --- a/homeassistant/components/glances/config_flow.py +++ b/homeassistant/components/glances/config_flow.py @@ -52,8 +52,8 @@ async def validate_input(hass: core.HomeAssistant, data): try: api = get_api(hass, data) await api.get_data() - except glances_api.exceptions.GlancesApiConnectionError: - raise CannotConnect + except glances_api.exceptions.GlancesApiConnectionError as err: + raise CannotConnect from err class GlancesFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): diff --git a/homeassistant/components/gogogate2/common.py b/homeassistant/components/gogogate2/common.py index c69dee662b0..10adc9c61b3 100644 --- a/homeassistant/components/gogogate2/common.py +++ b/homeassistant/components/gogogate2/common.py @@ -69,7 +69,9 @@ def get_data_update_coordinator( async with async_timeout.timeout(3): return await hass.async_add_executor_job(api.info) except Exception as exception: - raise UpdateFailed(f"Error communicating with API: {exception}") + raise UpdateFailed( + f"Error communicating with API: {exception}" + ) from exception config_entry_data[DATA_UPDATE_COORDINATOR] = GogoGateDataUpdateCoordinator( hass, diff --git a/homeassistant/components/griddy/config_flow.py b/homeassistant/components/griddy/config_flow.py index 56284384ee0..675e48cc999 100644 --- a/homeassistant/components/griddy/config_flow.py +++ b/homeassistant/components/griddy/config_flow.py @@ -28,8 +28,8 @@ async def validate_input(hass: core.HomeAssistant, data): await AsyncGriddy( client_session, settlement_point=data[CONF_LOADZONE] ).async_getnow() - except (asyncio.TimeoutError, ClientError): - raise CannotConnect + except (asyncio.TimeoutError, ClientError) as err: + raise CannotConnect from err # Return info that you want to store in the config entry. return {"title": f"Load Zone {data[CONF_LOADZONE]}"} diff --git a/homeassistant/components/guardian/util.py b/homeassistant/components/guardian/util.py index bd83307afb7..ad2a074564c 100644 --- a/homeassistant/components/guardian/util.py +++ b/homeassistant/components/guardian/util.py @@ -45,5 +45,5 @@ class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict]): try: resp = await self._api_coro() except GuardianError as err: - raise UpdateFailed(err) + raise UpdateFailed(err) from err return resp["data"] diff --git a/homeassistant/components/harmony/__init__.py b/homeassistant/components/harmony/__init__.py index 540e39f8f44..5bc4a132914 100644 --- a/homeassistant/components/harmony/__init__.py +++ b/homeassistant/components/harmony/__init__.py @@ -45,8 +45,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): name, entry.unique_id, address, activity, harmony_conf_file, delay_secs ) connected_ok = await device.connect() - except (asyncio.TimeoutError, ValueError, AttributeError): - raise ConfigEntryNotReady + except (asyncio.TimeoutError, ValueError, AttributeError) as err: + raise ConfigEntryNotReady from err if not connected_ok: raise ConfigEntryNotReady diff --git a/homeassistant/components/hassio/auth.py b/homeassistant/components/hassio/auth.py index fb2b1dc757c..23b91ac40bc 100644 --- a/homeassistant/components/hassio/auth.py +++ b/homeassistant/components/hassio/auth.py @@ -111,7 +111,7 @@ class HassIOPasswordReset(HassIOBaseAuth): await provider.async_change_password( data[ATTR_USERNAME], data[ATTR_PASSWORD] ) - except auth_ha.InvalidUser: - raise HTTPNotFound() + except auth_ha.InvalidUser as err: + raise HTTPNotFound() from err return web.Response(status=HTTP_OK) diff --git a/homeassistant/components/heos/__init__.py b/homeassistant/components/heos/__init__.py index a76a29b2ed5..81f9fd9dd0e 100644 --- a/homeassistant/components/heos/__init__.py +++ b/homeassistant/components/heos/__init__.py @@ -75,7 +75,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): except HeosError as error: await controller.disconnect() _LOGGER.debug("Unable to connect to controller %s: %s", host, error) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from error # Disconnect when shutting down async def disconnect_controller(event): @@ -99,7 +99,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): except HeosError as error: await controller.disconnect() _LOGGER.debug("Unable to retrieve players and sources: %s", error) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from error controller_manager = ControllerManager(hass, controller) await controller_manager.connect_listeners() diff --git a/homeassistant/components/hisense_aehw4a1/__init__.py b/homeassistant/components/hisense_aehw4a1/__init__.py index a2412a2fed4..725b294c00f 100644 --- a/homeassistant/components/hisense_aehw4a1/__init__.py +++ b/homeassistant/components/hisense_aehw4a1/__init__.py @@ -22,8 +22,8 @@ def coerce_ip(value): raise vol.Invalid("Must define an IP address") try: ipaddress.IPv4Network(value) - except ValueError: - raise vol.Invalid("Not a valid IP address") + except ValueError as err: + raise vol.Invalid("Not a valid IP address") from err return value diff --git a/homeassistant/components/hlk_sw16/config_flow.py b/homeassistant/components/hlk_sw16/config_flow.py index 0a9ac79d1b7..5064b00a7ad 100644 --- a/homeassistant/components/hlk_sw16/config_flow.py +++ b/homeassistant/components/hlk_sw16/config_flow.py @@ -49,8 +49,8 @@ async def validate_input(hass: HomeAssistant, user_input): try: client = await connect_client(hass, user_input) - except asyncio.TimeoutError: - raise CannotConnect + except asyncio.TimeoutError as err: + raise CannotConnect from err try: def disconnect_callback(): @@ -62,7 +62,7 @@ async def validate_input(hass: HomeAssistant, user_input): except CannotConnect: client.disconnect_callback = None client.stop() - raise CannotConnect + raise else: client.disconnect_callback = None client.stop() diff --git a/homeassistant/components/homeassistant/triggers/time_pattern.py b/homeassistant/components/homeassistant/triggers/time_pattern.py index ecca4ed444c..41294268ae8 100644 --- a/homeassistant/components/homeassistant/triggers/time_pattern.py +++ b/homeassistant/components/homeassistant/triggers/time_pattern.py @@ -40,8 +40,8 @@ class TimePattern: if not (0 <= number <= self.maximum): raise vol.Invalid(f"must be a value between 0 and {self.maximum}") - except ValueError: - raise vol.Invalid("invalid time_pattern value") + except ValueError as err: + raise vol.Invalid("invalid time_pattern value") from err return value diff --git a/homeassistant/components/homematicip_cloud/hap.py b/homeassistant/components/homematicip_cloud/hap.py index 431b05e692a..78f1d57ac93 100644 --- a/homeassistant/components/homematicip_cloud/hap.py +++ b/homeassistant/components/homematicip_cloud/hap.py @@ -92,8 +92,8 @@ class HomematicipHAP: self.config_entry.data.get(HMIPC_AUTHTOKEN), self.config_entry.data.get(HMIPC_NAME), ) - except HmipcConnectionError: - raise ConfigEntryNotReady + except HmipcConnectionError as err: + raise ConfigEntryNotReady from err except Exception as err: # pylint: disable=broad-except _LOGGER.error("Error connecting with HomematicIP Cloud: %s", err) return False @@ -247,8 +247,8 @@ class HomematicipHAP: try: await home.init(hapid) await home.get_current_state() - except HmipConnectionError: - raise HmipcConnectionError + except HmipConnectionError as err: + raise HmipcConnectionError from err home.on_update(self.async_update) home.on_create(self.async_create_entity) hass.loop.create_task(self.async_connect()) diff --git a/homeassistant/components/horizon/media_player.py b/homeassistant/components/horizon/media_player.py index 0ed98f73a38..5b9fb656938 100644 --- a/homeassistant/components/horizon/media_player.py +++ b/homeassistant/components/horizon/media_player.py @@ -71,7 +71,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): except OSError as msg: # occurs if horizon box is offline _LOGGER.error("Connection to %s at %s failed: %s", name, host, msg) - raise PlatformNotReady + raise PlatformNotReady from msg _LOGGER.info("Connection to %s at %s established", name, host) diff --git a/homeassistant/components/hp_ilo/sensor.py b/homeassistant/components/hp_ilo/sensor.py index 888fa2423ad..1cb65292c7d 100644 --- a/homeassistant/components/hp_ilo/sensor.py +++ b/homeassistant/components/hp_ilo/sensor.py @@ -191,4 +191,4 @@ class HpIloData: hpilo.IloCommunicationError, hpilo.IloLoginFailed, ) as error: - raise ValueError(f"Unable to init HP ILO, {error}") + raise ValueError(f"Unable to init HP ILO, {error}") from error diff --git a/homeassistant/components/http/forwarded.py b/homeassistant/components/http/forwarded.py index 4d9ec69a018..bf6bb811a81 100644 --- a/homeassistant/components/http/forwarded.py +++ b/homeassistant/components/http/forwarded.py @@ -91,11 +91,11 @@ def async_setup_forwarded(app, trusted_proxies): forwarded_for_split = list(reversed(forwarded_for_headers[0].split(","))) try: forwarded_for = [ip_address(addr.strip()) for addr in forwarded_for_split] - except ValueError: + except ValueError as err: _LOGGER.error( "Invalid IP address in X-Forwarded-For: %s", forwarded_for_headers[0] ) - raise HTTPBadRequest + raise HTTPBadRequest from err # Find the last trusted index in the X-Forwarded-For list forwarded_for_index = 0 diff --git a/homeassistant/components/http/view.py b/homeassistant/components/http/view.py index 7766d5a0cb9..354159f13be 100644 --- a/homeassistant/components/http/view.py +++ b/homeassistant/components/http/view.py @@ -52,7 +52,7 @@ class HomeAssistantView: msg = json.dumps(result, cls=JSONEncoder, allow_nan=False).encode("UTF-8") except (ValueError, TypeError) as err: _LOGGER.error("Unable to serialize to JSON: %s\n%s", err, result) - raise HTTPInternalServerError + raise HTTPInternalServerError from err response = web.Response( body=msg, content_type=CONTENT_TYPE_JSON, @@ -127,12 +127,12 @@ def request_handler_factory(view: HomeAssistantView, handler: Callable) -> Calla if asyncio.iscoroutine(result): result = await result - except vol.Invalid: - raise HTTPBadRequest() - except exceptions.ServiceNotFound: - raise HTTPInternalServerError() - except exceptions.Unauthorized: - raise HTTPUnauthorized() + except vol.Invalid as err: + raise HTTPBadRequest() from err + except exceptions.ServiceNotFound as err: + raise HTTPInternalServerError() from err + except exceptions.Unauthorized as err: + raise HTTPUnauthorized() from err if isinstance(result, web.StreamResponse): # The method handler returned a ready-made Response, how nice of it diff --git a/homeassistant/components/hue/bridge.py b/homeassistant/components/hue/bridge.py index 545c980591e..3eb894552ab 100644 --- a/homeassistant/components/hue/bridge.py +++ b/homeassistant/components/hue/bridge.py @@ -94,9 +94,9 @@ class HueBridge: create_config_flow(hass, host) return False - except CannotConnect: + except CannotConnect as err: LOGGER.error("Error connecting to the Hue bridge at %s", host) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err except Exception: # pylint: disable=broad-except LOGGER.exception("Unknown error connecting with Hue bridge at %s", host) @@ -269,18 +269,18 @@ async def authenticate_bridge(hass: core.HomeAssistant, bridge: aiohue.Bridge): # Initialize bridge (and validate our username) await bridge.initialize() - except (aiohue.LinkButtonNotPressed, aiohue.Unauthorized): - raise AuthenticationRequired + except (aiohue.LinkButtonNotPressed, aiohue.Unauthorized) as err: + raise AuthenticationRequired from err except ( asyncio.TimeoutError, client_exceptions.ClientOSError, client_exceptions.ServerDisconnectedError, client_exceptions.ContentTypeError, - ): - raise CannotConnect - except aiohue.AiohueException: + ) as err: + raise CannotConnect from err + except aiohue.AiohueException as err: LOGGER.exception("Unknown Hue linking error occurred") - raise AuthenticationRequired + raise AuthenticationRequired from err async def _update_listener(hass, entry): diff --git a/homeassistant/components/hue/light.py b/homeassistant/components/hue/light.py index c8d7de55ce8..9d055ad6066 100644 --- a/homeassistant/components/hue/light.py +++ b/homeassistant/components/hue/light.py @@ -159,11 +159,11 @@ async def async_safe_fetch(bridge, fetch_method): try: with async_timeout.timeout(4): return await bridge.async_request_call(fetch_method) - except aiohue.Unauthorized: + except aiohue.Unauthorized as err: await bridge.handle_unauthorized_error() - raise UpdateFailed("Unauthorized") + raise UpdateFailed("Unauthorized") from err except (aiohue.AiohueException,) as err: - raise UpdateFailed(f"Hue error: {err}") + raise UpdateFailed(f"Hue error: {err}") from err @callback diff --git a/homeassistant/components/hue/sensor_base.py b/homeassistant/components/hue/sensor_base.py index af8986e0212..263140464aa 100644 --- a/homeassistant/components/hue/sensor_base.py +++ b/homeassistant/components/hue/sensor_base.py @@ -61,11 +61,11 @@ class SensorManager: return await self.bridge.async_request_call( self.bridge.api.sensors.update ) - except Unauthorized: + except Unauthorized as err: await self.bridge.handle_unauthorized_error() - raise UpdateFailed("Unauthorized") + raise UpdateFailed("Unauthorized") from err except AiohueException as err: - raise UpdateFailed(f"Hue error: {err}") + raise UpdateFailed(f"Hue error: {err}") from err async def async_register_component(self, platform, async_add_entities): """Register async_add_entities methods for components.""" diff --git a/homeassistant/components/hunterdouglas_powerview/__init__.py b/homeassistant/components/hunterdouglas_powerview/__init__.py index 3f78726bf30..c87097dc7af 100644 --- a/homeassistant/components/hunterdouglas_powerview/__init__.py +++ b/homeassistant/components/hunterdouglas_powerview/__init__.py @@ -128,9 +128,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): shade_data = _async_map_data_by_id( (await shades.get_resources())[SHADE_DATA] ) - except HUB_EXCEPTIONS: + except HUB_EXCEPTIONS as err: _LOGGER.error("Connection error to PowerView hub: %s", hub_address) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err if not device_info: _LOGGER.error("Unable to initialize PowerView hub: %s", hub_address) diff --git a/homeassistant/components/hunterdouglas_powerview/config_flow.py b/homeassistant/components/hunterdouglas_powerview/config_flow.py index 1e47b9ec3fe..2bbdcfea3a6 100644 --- a/homeassistant/components/hunterdouglas_powerview/config_flow.py +++ b/homeassistant/components/hunterdouglas_powerview/config_flow.py @@ -33,8 +33,8 @@ async def validate_input(hass: core.HomeAssistant, data): try: async with async_timeout.timeout(10): device_info = await async_get_device_info(pv_request) - except HUB_EXCEPTIONS: - raise CannotConnect + except HUB_EXCEPTIONS as err: + raise CannotConnect from err if not device_info: raise CannotConnect diff --git a/homeassistant/components/iammeter/sensor.py b/homeassistant/components/iammeter/sensor.py index b043a6e9832..e2bf879e326 100644 --- a/homeassistant/components/iammeter/sensor.py +++ b/homeassistant/components/iammeter/sensor.py @@ -41,16 +41,16 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= try: with async_timeout.timeout(PLATFORM_TIMEOUT): api = await real_time_api(config_host, config_port) - except (IamMeterError, asyncio.TimeoutError): + except (IamMeterError, asyncio.TimeoutError) as err: _LOGGER.error("Device is not ready") - raise PlatformNotReady + raise PlatformNotReady from err async def async_update_data(): try: with async_timeout.timeout(PLATFORM_TIMEOUT): return await api.get_data() - except (IamMeterError, asyncio.TimeoutError): - raise UpdateFailed + except (IamMeterError, asyncio.TimeoutError) as err: + raise UpdateFailed from err coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/iaqualink/__init__.py b/homeassistant/components/iaqualink/__init__.py index 97ddd95f50c..d0667aab72a 100644 --- a/homeassistant/components/iaqualink/__init__.py +++ b/homeassistant/components/iaqualink/__init__.py @@ -96,7 +96,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> None aiohttp.client_exceptions.ClientConnectorError, ) as aio_exception: _LOGGER.warning("Exception raised while attempting to login: %s", aio_exception) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from aio_exception systems = await aqualink.get_systems() systems = list(systems.values()) diff --git a/homeassistant/components/icloud/account.py b/homeassistant/components/icloud/account.py index d039b270bb8..683d59e9281 100644 --- a/homeassistant/components/icloud/account.py +++ b/homeassistant/components/icloud/account.py @@ -119,9 +119,12 @@ class IcloudAccount: api_devices = self.api.devices # Gets device owners infos user_info = api_devices.response["userInfo"] - except (PyiCloudServiceNotActivatedException, PyiCloudNoDevicesException): + except ( + PyiCloudServiceNotActivatedException, + PyiCloudNoDevicesException, + ) as err: _LOGGER.error("No iCloud device found") - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err self._owner_fullname = f"{user_info['firstName']} {user_info['lastName']}" diff --git a/homeassistant/components/image/__init__.py b/homeassistant/components/image/__init__.py index 91085ce4e64..d08be3e9127 100644 --- a/homeassistant/components/image/__init__.py +++ b/homeassistant/components/image/__init__.py @@ -92,8 +92,8 @@ class ImageStorageCollection(collection.StorageCollection): # Verify we can read the image try: image = Image.open(uploaded_file.file) - except UnidentifiedImageError: - raise vol.Invalid("Unable to identify image file") + except UnidentifiedImageError as err: + raise vol.Invalid("Unable to identify image file") from err # Reset content uploaded_file.file.seek(0) @@ -170,8 +170,8 @@ class ImageServeView(HomeAssistantView): parts = image_size.split("x", 1) width = int(parts[0]) height = int(parts[1]) - except (ValueError, IndexError): - raise web.HTTPBadRequest + except (ValueError, IndexError) as err: + raise web.HTTPBadRequest from err if not width or width != height or width not in VALID_SIZES: raise web.HTTPBadRequest diff --git a/homeassistant/components/influxdb/__init__.py b/homeassistant/components/influxdb/__init__.py index 60939741894..db49e119235 100644 --- a/homeassistant/components/influxdb/__init__.py +++ b/homeassistant/components/influxdb/__init__.py @@ -324,22 +324,22 @@ def get_influx_connection(conf, test_write=False, test_read=False): try: write_api.write(bucket=bucket, record=json) except (urllib3.exceptions.HTTPError, OSError) as exc: - raise ConnectionError(CONNECTION_ERROR % exc) + raise ConnectionError(CONNECTION_ERROR % exc) from exc except ApiException as exc: if exc.status == CODE_INVALID_INPUTS: - raise ValueError(WRITE_ERROR % (json, exc)) - raise ConnectionError(CLIENT_ERROR_V2 % exc) + raise ValueError(WRITE_ERROR % (json, exc)) from exc + raise ConnectionError(CLIENT_ERROR_V2 % exc) from exc def query_v2(query, _=None): """Query V2 influx.""" try: return query_api.query(query) except (urllib3.exceptions.HTTPError, OSError) as exc: - raise ConnectionError(CONNECTION_ERROR % exc) + raise ConnectionError(CONNECTION_ERROR % exc) from exc except ApiException as exc: if exc.status == CODE_INVALID_INPUTS: - raise ValueError(QUERY_ERROR % (query, exc)) - raise ConnectionError(CLIENT_ERROR_V2 % exc) + raise ValueError(QUERY_ERROR % (query, exc)) from exc + raise ConnectionError(CLIENT_ERROR_V2 % exc) from exc def close_v2(): """Close V2 influx client.""" @@ -399,11 +399,11 @@ def get_influx_connection(conf, test_write=False, test_read=False): exceptions.InfluxDBServerError, OSError, ) as exc: - raise ConnectionError(CONNECTION_ERROR % exc) + raise ConnectionError(CONNECTION_ERROR % exc) from exc except exceptions.InfluxDBClientError as exc: if exc.code == CODE_INVALID_INPUTS: - raise ValueError(WRITE_ERROR % (json, exc)) - raise ConnectionError(CLIENT_ERROR_V1 % exc) + raise ValueError(WRITE_ERROR % (json, exc)) from exc + raise ConnectionError(CLIENT_ERROR_V1 % exc) from exc def query_v1(query, database=None): """Query V1 influx.""" @@ -414,11 +414,11 @@ def get_influx_connection(conf, test_write=False, test_read=False): exceptions.InfluxDBServerError, OSError, ) as exc: - raise ConnectionError(CONNECTION_ERROR % exc) + raise ConnectionError(CONNECTION_ERROR % exc) from exc except exceptions.InfluxDBClientError as exc: if exc.code == CODE_INVALID_INPUTS: - raise ValueError(QUERY_ERROR % (query, exc)) - raise ConnectionError(CLIENT_ERROR_V1 % exc) + raise ValueError(QUERY_ERROR % (query, exc)) from exc + raise ConnectionError(CLIENT_ERROR_V1 % exc) from exc def close_v1(): """Close the V1 Influx client.""" diff --git a/homeassistant/components/influxdb/sensor.py b/homeassistant/components/influxdb/sensor.py index 60e2a1088ca..eb5b0ce6091 100644 --- a/homeassistant/components/influxdb/sensor.py +++ b/homeassistant/components/influxdb/sensor.py @@ -147,7 +147,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): influx = get_influx_connection(config, test_read=True) except ConnectionError as exc: _LOGGER.error(exc) - raise PlatformNotReady() + raise PlatformNotReady() from exc entities = [] if CONF_QUERIES_FLUX in config: diff --git a/homeassistant/components/insteon/schemas.py b/homeassistant/components/insteon/schemas.py index 5a293fb2e52..a6c4b4627bc 100644 --- a/homeassistant/components/insteon/schemas.py +++ b/homeassistant/components/insteon/schemas.py @@ -173,8 +173,8 @@ def normalize_byte_entry_to_int(entry: [int, bytes, str]): raise ValueError("Not a valid hex code") try: entry = unhexlify(entry) - except HexError: - raise ValueError("Not a valid hex code") + except HexError as err: + raise ValueError("Not a valid hex code") from err return int.from_bytes(entry, byteorder="big") @@ -184,8 +184,8 @@ def add_device_override(config_data, new_override): address = str(Address(new_override[CONF_ADDRESS])) cat = normalize_byte_entry_to_int(new_override[CONF_CAT]) subcat = normalize_byte_entry_to_int(new_override[CONF_SUBCAT]) - except ValueError: - raise ValueError("Incorrect values") + except ValueError as err: + raise ValueError("Incorrect values") from err overrides = config_data.get(CONF_OVERRIDE, []) curr_override = {} diff --git a/homeassistant/components/intesishome/climate.py b/homeassistant/components/intesishome/climate.py index 781117e8b71..57912d7d24d 100644 --- a/homeassistant/components/intesishome/climate.py +++ b/homeassistant/components/intesishome/climate.py @@ -107,9 +107,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= except IHAuthenticationError: _LOGGER.error("Invalid username or password") return - except IHConnectionError: + except IHConnectionError as ex: _LOGGER.error("Error connecting to the %s server", device_type) - raise PlatformNotReady + raise PlatformNotReady from ex ih_devices = controller.get_devices() if ih_devices: @@ -199,7 +199,7 @@ class IntesisAC(ClimateEntity): await self._controller.connect() except IHConnectionError as ex: _LOGGER.error("Exception connecting to IntesisHome: %s", ex) - raise PlatformNotReady + raise PlatformNotReady from ex @property def name(self): diff --git a/homeassistant/components/ipp/__init__.py b/homeassistant/components/ipp/__init__.py index 07d1258d735..1f9a616dc4f 100644 --- a/homeassistant/components/ipp/__init__.py +++ b/homeassistant/components/ipp/__init__.py @@ -121,7 +121,7 @@ class IPPDataUpdateCoordinator(DataUpdateCoordinator[IPPPrinter]): try: return await self.ipp.printer() except IPPError as error: - raise UpdateFailed(f"Invalid response from API: {error}") + raise UpdateFailed(f"Invalid response from API: {error}") from error class IPPEntity(Entity): diff --git a/homeassistant/components/islamic_prayer_times/__init__.py b/homeassistant/components/islamic_prayer_times/__init__.py index 5f47c7dc372..d7ded256f73 100644 --- a/homeassistant/components/islamic_prayer_times/__init__.py +++ b/homeassistant/components/islamic_prayer_times/__init__.py @@ -174,8 +174,8 @@ class IslamicPrayerClient: try: await self.hass.async_add_executor_job(self.get_new_prayer_times) - except (exceptions.InvalidResponseError, ConnError): - raise ConfigEntryNotReady + except (exceptions.InvalidResponseError, ConnError) as err: + raise ConfigEntryNotReady from err await self.async_update() self.config_entry.add_update_listener(self.async_options_updated) diff --git a/homeassistant/components/isy994/config_flow.py b/homeassistant/components/isy994/config_flow.py index 0ed1d7e6833..bc589a3aa11 100644 --- a/homeassistant/components/isy994/config_flow.py +++ b/homeassistant/components/isy994/config_flow.py @@ -98,7 +98,7 @@ def _fetch_isy_configuration( webroot=webroot, ) except ValueError as err: - raise InvalidAuth(err.args[0]) + raise InvalidAuth(err.args[0]) from err return Configuration(log=_LOGGER, xml=isy_conn.get_config()) diff --git a/homeassistant/components/juicenet/__init__.py b/homeassistant/components/juicenet/__init__.py index d333b9f913b..080df7be6bf 100644 --- a/homeassistant/components/juicenet/__init__.py +++ b/homeassistant/components/juicenet/__init__.py @@ -63,7 +63,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): return False except aiohttp.ClientError as error: _LOGGER.error("Could not reach the JuiceNet API %s", error) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from error if not juicenet.devices: _LOGGER.error("No JuiceNet devices found for this account") diff --git a/homeassistant/components/juicenet/config_flow.py b/homeassistant/components/juicenet/config_flow.py index 3f089300025..5ea7e4f267a 100644 --- a/homeassistant/components/juicenet/config_flow.py +++ b/homeassistant/components/juicenet/config_flow.py @@ -28,10 +28,10 @@ async def validate_input(hass: core.HomeAssistant, data): await juicenet.get_devices() except TokenError as error: _LOGGER.error("Token Error %s", error) - raise InvalidAuth + raise InvalidAuth from error except aiohttp.ClientError as error: _LOGGER.error("Error connecting %s", error) - raise CannotConnect + raise CannotConnect from error # Return info that you want to store in the config entry. return {"title": "JuiceNet"} diff --git a/homeassistant/components/konnected/config_flow.py b/homeassistant/components/konnected/config_flow.py index 88888da44f8..4e8d13c999e 100644 --- a/homeassistant/components/konnected/config_flow.py +++ b/homeassistant/components/konnected/config_flow.py @@ -186,8 +186,8 @@ class KonnectedFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): try: status = await get_status(self.hass, host, port) self.data[CONF_ID] = status.get("chipId", status["mac"].replace(":", "")) - except (CannotConnect, KeyError): - raise CannotConnect + except (CannotConnect, KeyError) as err: + raise CannotConnect from err else: self.data[CONF_MODEL] = status.get("model", KONN_MODEL) self.data[CONF_ACCESS_TOKEN] = "".join( diff --git a/homeassistant/components/konnected/panel.py b/homeassistant/components/konnected/panel.py index bd91bf3adbc..76e75159290 100644 --- a/homeassistant/components/konnected/panel.py +++ b/homeassistant/components/konnected/panel.py @@ -390,4 +390,4 @@ async def get_status(hass, host, port): except client.ClientError as err: _LOGGER.error("Exception trying to get panel status: %s", err) - raise CannotConnect + raise CannotConnect from err diff --git a/homeassistant/components/luftdaten/__init__.py b/homeassistant/components/luftdaten/__init__.py index f7ed2d72f16..ed93d4a9791 100644 --- a/homeassistant/components/luftdaten/__init__.py +++ b/homeassistant/components/luftdaten/__init__.py @@ -148,8 +148,8 @@ async def async_setup_entry(hass, config_entry): ) await luftdaten.async_update() hass.data[DOMAIN][DATA_LUFTDATEN_CLIENT][config_entry.entry_id] = luftdaten - except LuftdatenError: - raise ConfigEntryNotReady + except LuftdatenError as err: + raise ConfigEntryNotReady from err hass.async_create_task( hass.config_entries.async_forward_entry_setup(config_entry, "sensor") diff --git a/homeassistant/components/media_extractor/__init__.py b/homeassistant/components/media_extractor/__init__.py index af5ada7d2c9..a223385d8e8 100644 --- a/homeassistant/components/media_extractor/__init__.py +++ b/homeassistant/components/media_extractor/__init__.py @@ -103,9 +103,9 @@ class MediaExtractor: try: all_media = ydl.extract_info(self.get_media_url(), process=False) - except DownloadError: + except DownloadError as err: # This exception will be logged by youtube-dl itself - raise MEDownloadException() + raise MEDownloadException() from err if "entries" in all_media: _LOGGER.warning("Playlists are not supported, looking for the first video") @@ -123,9 +123,9 @@ class MediaExtractor: try: ydl.params["format"] = query requested_stream = ydl.process_ie_result(selected_media, download=False) - except (ExtractorError, DownloadError): + except (ExtractorError, DownloadError) as err: _LOGGER.error("Could not extract stream for the query: %s", query) - raise MEQueryException() + raise MEQueryException() from err return requested_stream["url"] diff --git a/homeassistant/components/met/__init__.py b/homeassistant/components/met/__init__.py index ae994bfc396..1f5502170e4 100644 --- a/homeassistant/components/met/__init__.py +++ b/homeassistant/components/met/__init__.py @@ -83,7 +83,7 @@ class MetDataUpdateCoordinator(DataUpdateCoordinator): try: return await self.weather.fetch_data() except Exception as err: - raise UpdateFailed(f"Update failed: {err}") + raise UpdateFailed(f"Update failed: {err}") from err def track_home(self): """Start tracking changes to HA home setting.""" diff --git a/homeassistant/components/mikrotik/hub.py b/homeassistant/components/mikrotik/hub.py index 1dc6041b535..fb120aa29c7 100644 --- a/homeassistant/components/mikrotik/hub.py +++ b/homeassistant/components/mikrotik/hub.py @@ -253,7 +253,7 @@ class MikrotikData: socket.timeout, ) as api_error: _LOGGER.error("Mikrotik %s connection error %s", self._host, api_error) - raise CannotConnect + raise CannotConnect from api_error except librouteros.exceptions.ProtocolError as api_error: _LOGGER.warning( "Mikrotik %s failed to retrieve data. cmd=[%s] Error: %s", @@ -367,8 +367,8 @@ class MikrotikHub: api = await self.hass.async_add_executor_job( get_api, self.hass, self.config_entry.data ) - except CannotConnect: - raise ConfigEntryNotReady + except CannotConnect as api_error: + raise ConfigEntryNotReady from api_error except LoginError: return False @@ -415,5 +415,5 @@ def get_api(hass, entry): ) as api_error: _LOGGER.error("Mikrotik %s error: %s", entry[CONF_HOST], api_error) if "invalid user name or password" in str(api_error): - raise LoginError - raise CannotConnect + raise LoginError from api_error + raise CannotConnect from api_error diff --git a/homeassistant/components/mobile_app/webhook.py b/homeassistant/components/mobile_app/webhook.py index 8820d08a518..01db11a04e3 100644 --- a/homeassistant/components/mobile_app/webhook.py +++ b/homeassistant/components/mobile_app/webhook.py @@ -219,7 +219,7 @@ async def webhook_call_service(hass, config_entry, data): config_entry.data[ATTR_DEVICE_NAME], ex, ) - raise HTTPBadRequest() + raise HTTPBadRequest() from ex return empty_okay_response() diff --git a/homeassistant/components/modbus/sensor.py b/homeassistant/components/modbus/sensor.py index 8bf5f6f3115..9b367292fcf 100644 --- a/homeassistant/components/modbus/sensor.py +++ b/homeassistant/components/modbus/sensor.py @@ -58,8 +58,8 @@ def number(value: Any) -> Union[int, float]: try: value = float(value) return value - except (TypeError, ValueError): - raise vol.Invalid(f"invalid number {value}") + except (TypeError, ValueError) as err: + raise vol.Invalid(f"invalid number {value}") from err PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( diff --git a/homeassistant/components/monoprice/__init__.py b/homeassistant/components/monoprice/__init__.py index 9bceff1531c..06883ddc8a8 100644 --- a/homeassistant/components/monoprice/__init__.py +++ b/homeassistant/components/monoprice/__init__.py @@ -34,9 +34,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): try: monoprice = await hass.async_add_executor_job(get_monoprice, port) - except SerialException: + except SerialException as err: _LOGGER.error("Error connecting to Monoprice controller at %s", port) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err # double negative to handle absence of value first_run = not bool(entry.data.get(CONF_NOT_FIRST_RUN)) diff --git a/homeassistant/components/monoprice/config_flow.py b/homeassistant/components/monoprice/config_flow.py index ddaafd01d8c..05158144916 100644 --- a/homeassistant/components/monoprice/config_flow.py +++ b/homeassistant/components/monoprice/config_flow.py @@ -55,9 +55,9 @@ async def validate_input(hass: core.HomeAssistant, data): """ try: await get_async_monoprice(data[CONF_PORT], hass.loop) - except SerialException: + except SerialException as err: _LOGGER.error("Error connecting to Monoprice controller") - raise CannotConnect + raise CannotConnect from err sources = _sources_from_config(data) diff --git a/homeassistant/components/mqtt/util.py b/homeassistant/components/mqtt/util.py index 568dbabd7b0..651fe48fe3d 100644 --- a/homeassistant/components/mqtt/util.py +++ b/homeassistant/components/mqtt/util.py @@ -21,8 +21,8 @@ def valid_topic(value: Any) -> str: value = cv.string(value) try: raw_value = value.encode("utf-8") - except UnicodeError: - raise vol.Invalid("MQTT topic name/filter must be valid UTF-8 string.") + except UnicodeError as err: + raise vol.Invalid("MQTT topic name/filter must be valid UTF-8 string.") from err if not raw_value: raise vol.Invalid("MQTT topic name/filter must not be empty.") if len(raw_value) > 65535: diff --git a/homeassistant/components/myq/__init__.py b/homeassistant/components/myq/__init__.py index fc1d374fe43..959000da3b3 100644 --- a/homeassistant/components/myq/__init__.py +++ b/homeassistant/components/myq/__init__.py @@ -37,8 +37,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): except InvalidCredentialsError as err: _LOGGER.error("There was an error while logging in: %s", err) return False - except MyQError: - raise ConfigEntryNotReady + except MyQError as err: + raise ConfigEntryNotReady from err coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/myq/config_flow.py b/homeassistant/components/myq/config_flow.py index 4fd267f1b21..d06f01342a1 100644 --- a/homeassistant/components/myq/config_flow.py +++ b/homeassistant/components/myq/config_flow.py @@ -28,10 +28,10 @@ async def validate_input(hass: core.HomeAssistant, data): try: await pymyq.login(data[CONF_USERNAME], data[CONF_PASSWORD], websession) - except InvalidCredentialsError: - raise InvalidAuth - except MyQError: - raise CannotConnect + except InvalidCredentialsError as err: + raise InvalidAuth from err + except MyQError as err: + raise CannotConnect from err return {"title": data[CONF_USERNAME]} diff --git a/homeassistant/components/mysensors/gateway.py b/homeassistant/components/mysensors/gateway.py index 56c1562eea0..3bb6326f78d 100644 --- a/homeassistant/components/mysensors/gateway.py +++ b/homeassistant/components/mysensors/gateway.py @@ -54,8 +54,8 @@ def is_socket_address(value): try: socket.getaddrinfo(value, None) return value - except OSError: - raise vol.Invalid("Device is not a valid domain name or ip address") + except OSError as err: + raise vol.Invalid("Device is not a valid domain name or ip address") from err def get_mysensors_gateway(hass, gateway_id): diff --git a/homeassistant/components/mystrom/light.py b/homeassistant/components/mystrom/light.py index 2762792e133..510245ea859 100644 --- a/homeassistant/components/mystrom/light.py +++ b/homeassistant/components/mystrom/light.py @@ -52,9 +52,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= if bulb.bulb_type != "rgblamp": _LOGGER.error("Device %s (%s) is not a myStrom bulb", host, mac) return - except MyStromConnectionError: + except MyStromConnectionError as err: _LOGGER.warning("No route to myStrom bulb: %s", host) - raise PlatformNotReady() + raise PlatformNotReady() from err async_add_entities([MyStromLight(bulb, name, mac)], True) diff --git a/homeassistant/components/mystrom/switch.py b/homeassistant/components/mystrom/switch.py index ab1207658ab..6332760f189 100644 --- a/homeassistant/components/mystrom/switch.py +++ b/homeassistant/components/mystrom/switch.py @@ -30,9 +30,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= try: plug = _MyStromSwitch(host) await plug.get_state() - except MyStromConnectionError: + except MyStromConnectionError as err: _LOGGER.error("No route to myStrom plug: %s", host) - raise PlatformNotReady() + raise PlatformNotReady() from err async_add_entities([MyStromSwitch(plug, name)]) diff --git a/homeassistant/components/neato/__init__.py b/homeassistant/components/neato/__init__.py index 311f5ff5f42..9775dc592fd 100644 --- a/homeassistant/components/neato/__init__.py +++ b/homeassistant/components/neato/__init__.py @@ -101,9 +101,9 @@ async def async_setup_entry(hass, entry): try: await hass.async_add_executor_job(hub.update_robots) - except NeatoRobotException: + except NeatoRobotException as ex: _LOGGER.debug("Failed to connect to Neato API") - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex hass.data[NEATO_LOGIN] = hub @@ -156,7 +156,7 @@ class NeatoHub: _LOGGER.error("Invalid credentials") else: _LOGGER.error("Unable to connect to Neato API") - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex self.logged_in = False return diff --git a/homeassistant/components/nederlandse_spoorwegen/sensor.py b/homeassistant/components/nederlandse_spoorwegen/sensor.py index dd43227a5ab..3d15e3c4d9b 100644 --- a/homeassistant/components/nederlandse_spoorwegen/sensor.py +++ b/homeassistant/components/nederlandse_spoorwegen/sensor.py @@ -57,7 +57,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): requests.exceptions.HTTPError, ) as error: _LOGGER.error("Could not connect to the internet: %s", error) - raise PlatformNotReady() + raise PlatformNotReady() from error except RequestParametersError as error: _LOGGER.error("Could not fetch stations, please check configuration: %s", error) return diff --git a/homeassistant/components/nexia/__init__.py b/homeassistant/components/nexia/__init__.py index 122f00f7b59..25dce69417c 100644 --- a/homeassistant/components/nexia/__init__.py +++ b/homeassistant/components/nexia/__init__.py @@ -79,7 +79,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): ) except ConnectTimeout as ex: _LOGGER.error("Unable to connect to Nexia service: %s", ex) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex except HTTPError as http_ex: if ( http_ex.response.status_code >= HTTP_BAD_REQUEST @@ -90,7 +90,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): ) return False _LOGGER.error("HTTP error from Nexia service: %s", http_ex) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from http_ex async def _async_update_data(): """Fetch data from API endpoint.""" diff --git a/homeassistant/components/nexia/config_flow.py b/homeassistant/components/nexia/config_flow.py index d71a5470c98..b5163d88f63 100644 --- a/homeassistant/components/nexia/config_flow.py +++ b/homeassistant/components/nexia/config_flow.py @@ -39,15 +39,15 @@ async def validate_input(hass: core.HomeAssistant, data): await hass.async_add_executor_job(nexia_home.login) except ConnectTimeout as ex: _LOGGER.error("Unable to connect to Nexia service: %s", ex) - raise CannotConnect + raise CannotConnect from ex except HTTPError as http_ex: _LOGGER.error("HTTP error from Nexia service: %s", http_ex) if ( http_ex.response.status_code >= HTTP_BAD_REQUEST and http_ex.response.status_code < HTTP_INTERNAL_SERVER_ERROR ): - raise InvalidAuth - raise CannotConnect + raise InvalidAuth from http_ex + raise CannotConnect from http_ex if not nexia_home.get_name(): raise InvalidAuth diff --git a/homeassistant/components/nightscout/config_flow.py b/homeassistant/components/nightscout/config_flow.py index 699ce39355f..bd33bc8dcb4 100644 --- a/homeassistant/components/nightscout/config_flow.py +++ b/homeassistant/components/nightscout/config_flow.py @@ -23,8 +23,8 @@ async def _validate_input(data): try: api = NightscoutAPI(url) status = await api.get_server_status() - except (ClientError, AsyncIOTimeoutError, OSError): - raise InputValidationError("cannot_connect") + except (ClientError, AsyncIOTimeoutError, OSError) as error: + raise InputValidationError("cannot_connect") from error # Return info to be stored in the config entry. return {"title": status.name} diff --git a/homeassistant/components/niko_home_control/light.py b/homeassistant/components/niko_home_control/light.py index 4875e2e1e57..c5bc33b7e5e 100644 --- a/homeassistant/components/niko_home_control/light.py +++ b/homeassistant/components/niko_home_control/light.py @@ -31,7 +31,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= await niko_data.async_update() except OSError as err: _LOGGER.error("Unable to access %s (%s)", host, err) - raise PlatformNotReady + raise PlatformNotReady from err async_add_entities( [NikoHomeControlLight(light, niko_data) for light in nhc.list_actions()], True diff --git a/homeassistant/components/notion/__init__.py b/homeassistant/components/notion/__init__.py index 1c8fc650803..72b6ac610db 100644 --- a/homeassistant/components/notion/__init__.py +++ b/homeassistant/components/notion/__init__.py @@ -85,7 +85,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: return False except NotionError as err: _LOGGER.error("Config entry failed: %s", err) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err async def async_update(): """Get the latest data from the Notion API.""" diff --git a/homeassistant/components/nuheat/__init__.py b/homeassistant/components/nuheat/__init__.py index 4c7455be3c0..80765d88866 100644 --- a/homeassistant/components/nuheat/__init__.py +++ b/homeassistant/components/nuheat/__init__.py @@ -81,8 +81,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): try: await hass.async_add_executor_job(api.authenticate) - except requests.exceptions.Timeout: - raise ConfigEntryNotReady + except requests.exceptions.Timeout as ex: + raise ConfigEntryNotReady from ex except requests.exceptions.HTTPError as ex: if ( ex.response.status_code > HTTP_BAD_REQUEST @@ -90,7 +90,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): ): _LOGGER.error("Failed to login to nuheat: %s", ex) return False - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex except Exception as ex: # pylint: disable=broad-except _LOGGER.error("Failed to login to nuheat: %s", ex) return False diff --git a/homeassistant/components/nuheat/config_flow.py b/homeassistant/components/nuheat/config_flow.py index bdbdfe22ea3..dc72438ce5e 100644 --- a/homeassistant/components/nuheat/config_flow.py +++ b/homeassistant/components/nuheat/config_flow.py @@ -36,27 +36,27 @@ async def validate_input(hass: core.HomeAssistant, data): try: await hass.async_add_executor_job(api.authenticate) - except requests.exceptions.Timeout: - raise CannotConnect + except requests.exceptions.Timeout as ex: + raise CannotConnect from ex except requests.exceptions.HTTPError as ex: if ( ex.response.status_code > HTTP_BAD_REQUEST and ex.response.status_code < HTTP_INTERNAL_SERVER_ERROR ): - raise InvalidAuth - raise CannotConnect + raise InvalidAuth from ex + raise CannotConnect from ex # # The underlying module throws a generic exception on login failure # - except Exception: # pylint: disable=broad-except - raise InvalidAuth + except Exception as ex: # pylint: disable=broad-except + raise InvalidAuth from ex try: thermostat = await hass.async_add_executor_job( api.get_thermostat, data[CONF_SERIAL_NUMBER] ) - except requests.exceptions.HTTPError: - raise InvalidThermostat + except requests.exceptions.HTTPError as ex: + raise InvalidThermostat from ex return {"title": thermostat.room, "serial_number": thermostat.serial_number} diff --git a/homeassistant/components/numato/__init__.py b/homeassistant/components/numato/__init__.py index e5eeaa31846..8efc56e12fe 100644 --- a/homeassistant/components/numato/__init__.py +++ b/homeassistant/components/numato/__init__.py @@ -57,8 +57,8 @@ def float_range(rng): coe = vol.Coerce(float) coe(rng[0]) coe(rng[1]) - except vol.CoerceInvalid: - raise vol.Invalid(f"Only int or float values are allowed: {rng}") + except vol.CoerceInvalid as err: + raise vol.Invalid(f"Only int or float values are allowed: {rng}") from err if len(rng) != 2: raise vol.Invalid(f"Only two numbers allowed in a range: {rng}") if rng[0] > rng[1]: @@ -70,8 +70,8 @@ def adc_port_number(num): """Validate input number to be in the range of ADC enabled ports.""" try: num = int(num) - except (ValueError): - raise vol.Invalid(f"Port numbers must be integers: {num}") + except ValueError as err: + raise vol.Invalid(f"Port numbers must be integers: {num}") from err if num not in range(1, 8): raise vol.Invalid(f"Only port numbers from 1 to 7 are ADC capable: {num}") return num diff --git a/homeassistant/components/nws/config_flow.py b/homeassistant/components/nws/config_flow.py index ebef7418d98..12ab09abaae 100644 --- a/homeassistant/components/nws/config_flow.py +++ b/homeassistant/components/nws/config_flow.py @@ -34,7 +34,7 @@ async def validate_input(hass: core.HomeAssistant, data): await nws.set_station(station) except aiohttp.ClientError as err: _LOGGER.error("Could not connect: %s", err) - raise CannotConnect + raise CannotConnect from err return {"title": nws.station} diff --git a/homeassistant/components/nx584/alarm_control_panel.py b/homeassistant/components/nx584/alarm_control_panel.py index 7ce882e3c82..2df7cd1bb4b 100644 --- a/homeassistant/components/nx584/alarm_control_panel.py +++ b/homeassistant/components/nx584/alarm_control_panel.py @@ -60,7 +60,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= "Unable to connect to %(host)s: %(reason)s", dict(host=url, reason=ex), ) - raise PlatformNotReady + raise PlatformNotReady from ex entity = NX584Alarm(name, alarm_client, url) async_add_entities([entity]) diff --git a/homeassistant/components/openuv/__init__.py b/homeassistant/components/openuv/__init__.py index a9ebd77b5a6..5161011dd4c 100644 --- a/homeassistant/components/openuv/__init__.py +++ b/homeassistant/components/openuv/__init__.py @@ -80,7 +80,7 @@ async def async_setup_entry(hass, config_entry): hass.data[DOMAIN][DATA_OPENUV_CLIENT][config_entry.entry_id] = openuv except OpenUvError as err: _LOGGER.error("Config entry failed: %s", err) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err for component in PLATFORMS: hass.async_create_task( diff --git a/homeassistant/components/pencom/switch.py b/homeassistant/components/pencom/switch.py index 0fcdd056b15..7f193bc09a1 100644 --- a/homeassistant/components/pencom/switch.py +++ b/homeassistant/components/pencom/switch.py @@ -47,7 +47,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): hub = Pencompy(host, port, boards=boards) except OSError as error: _LOGGER.error("Could not connect to pencompy: %s", error) - raise PlatformNotReady + raise PlatformNotReady from error # Add devices. devs = [] diff --git a/homeassistant/components/pi_hole/__init__.py b/homeassistant/components/pi_hole/__init__.py index 5e7fc723cc4..a1aa0f819f8 100644 --- a/homeassistant/components/pi_hole/__init__.py +++ b/homeassistant/components/pi_hole/__init__.py @@ -95,14 +95,14 @@ async def async_setup_entry(hass, entry): await api.get_data() except HoleError as ex: _LOGGER.warning("Failed to connect: %s", ex) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex async def async_update_data(): """Fetch data from API endpoint.""" try: await api.get_data() except HoleError as err: - raise UpdateFailed(f"Failed to communicating with API: {err}") + raise UpdateFailed(f"Failed to communicating with API: {err}") from err coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/plex/__init__.py b/homeassistant/components/plex/__init__.py index 85d4b43b532..3552823677d 100644 --- a/homeassistant/components/plex/__init__.py +++ b/homeassistant/components/plex/__init__.py @@ -91,7 +91,7 @@ async def async_setup_entry(hass, entry): server_config[CONF_URL], error, ) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from error except ( plexapi.exceptions.BadRequest, plexapi.exceptions.Unauthorized, diff --git a/homeassistant/components/plugwise/__init__.py b/homeassistant/components/plugwise/__init__.py index efb97f51c41..7e43a68b9e8 100644 --- a/homeassistant/components/plugwise/__init__.py +++ b/homeassistant/components/plugwise/__init__.py @@ -50,13 +50,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: _LOGGER.error("Invalid Smile ID") return False - except Smile.PlugwiseError: + except Smile.PlugwiseError as err: _LOGGER.error("Error while communicating to device") - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err - except asyncio.TimeoutError: + except asyncio.TimeoutError as err: _LOGGER.error("Timeout while connecting to Smile") - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err update_interval = timedelta(seconds=60) if api.smile_type == "power": @@ -68,8 +68,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async with async_timeout.timeout(10): await api.full_update_device() return True - except Smile.XMLDataMissingError: - raise UpdateFailed("Smile update failed") + except Smile.XMLDataMissingError as err: + raise UpdateFailed("Smile update failed") from err coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/plugwise/config_flow.py b/homeassistant/components/plugwise/config_flow.py index b02bb3cb92b..1f86394775a 100644 --- a/homeassistant/components/plugwise/config_flow.py +++ b/homeassistant/components/plugwise/config_flow.py @@ -48,10 +48,10 @@ async def validate_input(hass: core.HomeAssistant, data): try: await api.connect() - except Smile.InvalidAuthentication: - raise InvalidAuth - except Smile.PlugwiseError: - raise CannotConnect + except Smile.InvalidAuthentication as err: + raise InvalidAuth from err + except Smile.PlugwiseError as err: + raise CannotConnect from err return api diff --git a/homeassistant/components/plum_lightpad/__init__.py b/homeassistant/components/plum_lightpad/__init__.py index 8e7596bd7e0..2a7ce4497bb 100644 --- a/homeassistant/components/plum_lightpad/__init__.py +++ b/homeassistant/components/plum_lightpad/__init__.py @@ -62,7 +62,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): return False except (ConnectTimeout, HTTPError) as ex: _LOGGER.error("Unable to connect to Plum cloud: %s", ex) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = plum diff --git a/homeassistant/components/poolsense/__init__.py b/homeassistant/components/poolsense/__init__.py index bb41541b434..c3577982dc0 100644 --- a/homeassistant/components/poolsense/__init__.py +++ b/homeassistant/components/poolsense/__init__.py @@ -136,6 +136,6 @@ class PoolSenseDataUpdateCoordinator(DataUpdateCoordinator): data = await self.poolsense.get_poolsense_data() except (PoolSenseError) as error: _LOGGER.error("PoolSense query did not complete.") - raise UpdateFailed(error) + raise UpdateFailed(error) from error return data diff --git a/homeassistant/components/powerwall/__init__.py b/homeassistant/components/powerwall/__init__.py index 9c1ea7afe53..2dc19a0771d 100644 --- a/homeassistant/components/powerwall/__init__.py +++ b/homeassistant/components/powerwall/__init__.py @@ -113,9 +113,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): await hass.async_add_executor_job(power_wall.detect_and_pin_version) await hass.async_add_executor_job(_fetch_powerwall_data, power_wall) powerwall_data = await hass.async_add_executor_job(call_base_info, power_wall) - except PowerwallUnreachableError: + except PowerwallUnreachableError as err: http_session.close() - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err except APIChangedError as err: http_session.close() await _async_handle_api_changed_error(hass, err) @@ -133,8 +133,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): return await hass.async_add_executor_job( _fetch_powerwall_data, power_wall ) - except PowerwallUnreachableError: - raise UpdateFailed("Unable to fetch data from powerwall") + except PowerwallUnreachableError as err: + raise UpdateFailed("Unable to fetch data from powerwall") from err except APIChangedError as err: await _async_handle_api_changed_error(hass, err) hass.data[DOMAIN][entry.entry_id][POWERWALL_API_CHANGED] = True diff --git a/homeassistant/components/powerwall/config_flow.py b/homeassistant/components/powerwall/config_flow.py index 8c313b79024..fd44949e386 100644 --- a/homeassistant/components/powerwall/config_flow.py +++ b/homeassistant/components/powerwall/config_flow.py @@ -25,12 +25,12 @@ async def validate_input(hass: core.HomeAssistant, data): try: await hass.async_add_executor_job(power_wall.detect_and_pin_version) site_info = await hass.async_add_executor_job(power_wall.get_site_info) - except PowerwallUnreachableError: - raise CannotConnect + except PowerwallUnreachableError as err: + raise CannotConnect from err except APIChangedError as err: # Only log the exception without the traceback _LOGGER.error(str(err)) - raise WrongVersion + raise WrongVersion from err # Return info that you want to store in the config entry. return {"title": site_info.site_name} diff --git a/homeassistant/components/proxy/camera.py b/homeassistant/components/proxy/camera.py index 7aa83d30ae4..754f09fa199 100644 --- a/homeassistant/components/proxy/camera.py +++ b/homeassistant/components/proxy/camera.py @@ -70,9 +70,9 @@ def _precheck_image(image, opts): raise ValueError() try: img = Image.open(io.BytesIO(image)) - except OSError: + except OSError as err: _LOGGER.warning("Failed to open image") - raise ValueError() + raise ValueError() from err imgfmt = str(img.format) if imgfmt not in ("PNG", "JPEG"): _LOGGER.warning("Image is of unsupported type: %s", imgfmt) @@ -272,8 +272,8 @@ class ProxyCamera(Camera): image = await async_get_image(self.hass, self._proxied_camera) if not image: return None - except HomeAssistantError: - raise asyncio.CancelledError() + except HomeAssistantError as err: + raise asyncio.CancelledError() from err if self._mode == MODE_RESIZE: job = _resize_image diff --git a/homeassistant/components/qbittorrent/sensor.py b/homeassistant/components/qbittorrent/sensor.py index 4bf982bbbce..cd67355d883 100644 --- a/homeassistant/components/qbittorrent/sensor.py +++ b/homeassistant/components/qbittorrent/sensor.py @@ -51,9 +51,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): except LoginRequired: _LOGGER.error("Invalid authentication") return - except RequestException: + except RequestException as err: _LOGGER.error("Connection failed") - raise PlatformNotReady + raise PlatformNotReady from err name = config.get(CONF_NAME) diff --git a/homeassistant/components/rachio/__init__.py b/homeassistant/components/rachio/__init__.py index b84ccb8fa5d..8310a12d51c 100644 --- a/homeassistant/components/rachio/__init__.py +++ b/homeassistant/components/rachio/__init__.py @@ -117,7 +117,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): # and there is not a reasonable timeout here so it can block for a long time except RACHIO_API_EXCEPTIONS as error: _LOGGER.error("Could not reach the Rachio API: %s", error) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from error # Check for Rachio controller devices if not person.controllers: diff --git a/homeassistant/components/rachio/config_flow.py b/homeassistant/components/rachio/config_flow.py index df9ead463f7..f262843d4ad 100644 --- a/homeassistant/components/rachio/config_flow.py +++ b/homeassistant/components/rachio/config_flow.py @@ -46,7 +46,7 @@ async def validate_input(hass: core.HomeAssistant, data): # Yes we really do get all these exceptions (hopefully rachiopy switches to requests) except RACHIO_API_EXCEPTIONS as error: _LOGGER.error("Could not reach the Rachio API: %s", error) - raise CannotConnect + raise CannotConnect from error # Return info that you want to store in the config entry. return {"title": username} diff --git a/homeassistant/components/rainmachine/__init__.py b/homeassistant/components/rainmachine/__init__.py index 239878d0219..544a79c42df 100644 --- a/homeassistant/components/rainmachine/__init__.py +++ b/homeassistant/components/rainmachine/__init__.py @@ -144,7 +144,7 @@ async def async_setup_entry(hass, config_entry): ) except RainMachineError as err: _LOGGER.error("An error occurred: %s", err) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err else: # regenmaschine can load multiple controllers at once, but we only grab the one # we loaded above: diff --git a/homeassistant/components/raspihats/__init__.py b/homeassistant/components/raspihats/__init__.py index e6fd3d7bb59..c9e862a0672 100644 --- a/homeassistant/components/raspihats/__init__.py +++ b/homeassistant/components/raspihats/__init__.py @@ -214,7 +214,7 @@ class I2CHatsManager(threading.Thread): value = i2c_hat.di.value return (value >> channel) & 0x01 except ResponseException as ex: - raise I2CHatsException(str(ex)) + raise I2CHatsException(str(ex)) from ex def write_dq(self, address, channel, value): """Write a value to a I2C-HAT digital output.""" @@ -228,7 +228,7 @@ class I2CHatsManager(threading.Thread): try: i2c_hat.dq.channels[channel] = value except ResponseException as ex: - raise I2CHatsException(str(ex)) + raise I2CHatsException(str(ex)) from ex def read_dq(self, address, channel): """Read a value from a I2C-HAT digital output.""" @@ -242,4 +242,4 @@ class I2CHatsManager(threading.Thread): try: return i2c_hat.dq.channels[channel] except ResponseException as ex: - raise I2CHatsException(str(ex)) + raise I2CHatsException(str(ex)) from ex diff --git a/homeassistant/components/rfxtrx/__init__.py b/homeassistant/components/rfxtrx/__init__.py index 8b0f4364e09..947a945eee7 100644 --- a/homeassistant/components/rfxtrx/__init__.py +++ b/homeassistant/components/rfxtrx/__init__.py @@ -90,8 +90,10 @@ def _bytearray_string(data): val = cv.string(data) try: return bytearray.fromhex(val) - except ValueError: - raise vol.Invalid("Data must be a hex string with multiple of two characters") + except ValueError as err: + raise vol.Invalid( + "Data must be a hex string with multiple of two characters" + ) from err def _ensure_device(value): diff --git a/homeassistant/components/ring/config_flow.py b/homeassistant/components/ring/config_flow.py index 607e4f1937b..87b2026882c 100644 --- a/homeassistant/components/ring/config_flow.py +++ b/homeassistant/components/ring/config_flow.py @@ -24,10 +24,10 @@ async def validate_input(hass: core.HomeAssistant, data): data["password"], data.get("2fa"), ) - except MissingTokenError: - raise Require2FA - except AccessDeniedError: - raise InvalidAuth + except MissingTokenError as err: + raise Require2FA from err + except AccessDeniedError as err: + raise InvalidAuth from err return token diff --git a/homeassistant/components/roku/__init__.py b/homeassistant/components/roku/__init__.py index 1baff67f580..b02ad6430e9 100644 --- a/homeassistant/components/roku/__init__.py +++ b/homeassistant/components/roku/__init__.py @@ -146,7 +146,7 @@ class RokuDataUpdateCoordinator(DataUpdateCoordinator[Device]): return data except RokuError as error: - raise UpdateFailed(f"Invalid response from API: {error}") + raise UpdateFailed(f"Invalid response from API: {error}") from error class RokuEntity(Entity): diff --git a/homeassistant/components/roomba/__init__.py b/homeassistant/components/roomba/__init__.py index f2daaa0fbf8..192dc4de537 100644 --- a/homeassistant/components/roomba/__init__.py +++ b/homeassistant/components/roomba/__init__.py @@ -104,8 +104,8 @@ async def async_setup_entry(hass, config_entry): try: if not await async_connect_or_timeout(hass, roomba): return False - except CannotConnect: - raise exceptions.ConfigEntryNotReady + except CannotConnect as err: + raise exceptions.ConfigEntryNotReady from err hass.data[DOMAIN][config_entry.entry_id] = { ROOMBA_SESSION: roomba, @@ -136,14 +136,14 @@ async def async_connect_or_timeout(hass, roomba): if name: break await asyncio.sleep(1) - except RoombaConnectionError: + except RoombaConnectionError as err: _LOGGER.error("Error to connect to vacuum") - raise CannotConnect - except asyncio.TimeoutError: + raise CannotConnect from err + except asyncio.TimeoutError as err: # api looping if user or password incorrect and roomba exist await async_disconnect_or_timeout(hass, roomba) _LOGGER.error("Timeout expired") - raise CannotConnect + raise CannotConnect from err return {ROOMBA_SESSION: roomba, CONF_NAME: name} diff --git a/homeassistant/components/rtorrent/sensor.py b/homeassistant/components/rtorrent/sensor.py index cd27b33271f..3976d8985cd 100644 --- a/homeassistant/components/rtorrent/sensor.py +++ b/homeassistant/components/rtorrent/sensor.py @@ -59,9 +59,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): try: rtorrent = xmlrpc.client.ServerProxy(url) - except (xmlrpc.client.ProtocolError, ConnectionRefusedError): + except (xmlrpc.client.ProtocolError, ConnectionRefusedError) as ex: _LOGGER.error("Connection to rtorrent daemon failed") - raise PlatformNotReady + raise PlatformNotReady from ex dev = [] for variable in config[CONF_MONITORED_VARIABLES]: dev.append(RTorrentSensor(variable, rtorrent, name)) diff --git a/homeassistant/components/schluter/climate.py b/homeassistant/components/schluter/climate.py index 88630cb99db..e41c733e83a 100644 --- a/homeassistant/components/schluter/climate.py +++ b/homeassistant/components/schluter/climate.py @@ -40,7 +40,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= api.get_thermostats, session_id ) except RequestException as err: - raise UpdateFailed(f"Error communicating with Schluter API: {err}") + raise UpdateFailed(f"Error communicating with Schluter API: {err}") from err if thermostats is None: return {} diff --git a/homeassistant/components/sense/__init__.py b/homeassistant/components/sense/__init__.py index f295b0d926c..17d0074c836 100644 --- a/homeassistant/components/sense/__init__.py +++ b/homeassistant/components/sense/__init__.py @@ -104,14 +104,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): except SenseAuthenticationException: _LOGGER.error("Could not authenticate with sense server") return False - except SENSE_TIMEOUT_EXCEPTIONS: - raise ConfigEntryNotReady + except SENSE_TIMEOUT_EXCEPTIONS as err: + raise ConfigEntryNotReady from err sense_devices_data = SenseDevicesData() try: sense_discovered_devices = await gateway.get_discovered_device_data() - except SENSE_TIMEOUT_EXCEPTIONS: - raise ConfigEntryNotReady + except SENSE_TIMEOUT_EXCEPTIONS as err: + raise ConfigEntryNotReady from err trends_coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/sensibo/climate.py b/homeassistant/components/sensibo/climate.py index 29aa0c5380e..26276650752 100644 --- a/homeassistant/components/sensibo/climate.py +++ b/homeassistant/components/sensibo/climate.py @@ -100,9 +100,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= aiohttp.client_exceptions.ClientConnectorError, asyncio.TimeoutError, pysensibo.SensiboError, - ): + ) as err: _LOGGER.exception("Failed to connect to Sensibo servers") - raise PlatformNotReady + raise PlatformNotReady from err if not devices: return diff --git a/homeassistant/components/shelly/__init__.py b/homeassistant/components/shelly/__init__.py index 4829aeb49f2..f9b936898a1 100644 --- a/homeassistant/components/shelly/__init__.py +++ b/homeassistant/components/shelly/__init__.py @@ -37,8 +37,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): device = await aioshelly.Device.create( entry.data["host"], aiohttp_client.async_get_clientsession(hass) ) - except (asyncio.TimeoutError, OSError): - raise ConfigEntryNotReady + except (asyncio.TimeoutError, OSError) as err: + raise ConfigEntryNotReady from err wrapper = hass.data[DOMAIN][entry.entry_id] = ShellyDeviceWrapper( hass, entry, device @@ -78,8 +78,8 @@ class ShellyDeviceWrapper(update_coordinator.DataUpdateCoordinator): try: async with async_timeout.timeout(5): return await self.device.update() - except aiocoap_error.Error: - raise update_coordinator.UpdateFailed("Error fetching data") + except aiocoap_error.Error as err: + raise update_coordinator.UpdateFailed("Error fetching data") from err @property def model(self): diff --git a/homeassistant/components/simplisafe/__init__.py b/homeassistant/components/simplisafe/__init__.py index 07b4942ad34..4b843d6eebe 100644 --- a/homeassistant/components/simplisafe/__init__.py +++ b/homeassistant/components/simplisafe/__init__.py @@ -238,7 +238,7 @@ async def async_setup_entry(hass, config_entry): return False except SimplipyError as err: LOGGER.error("Config entry failed: %s", err) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err _async_save_refresh_token(hass, config_entry, api.refresh_token) diff --git a/homeassistant/components/sisyphus/light.py b/homeassistant/components/sisyphus/light.py index ce0c37174ef..6d5fa2fc835 100644 --- a/homeassistant/components/sisyphus/light.py +++ b/homeassistant/components/sisyphus/light.py @@ -20,8 +20,8 @@ async def async_setup_platform(hass, config, add_entities, discovery_info=None): try: table_holder = hass.data[DATA_SISYPHUS][host] table = await table_holder.get_table() - except aiohttp.ClientError: - raise PlatformNotReady() + except aiohttp.ClientError as err: + raise PlatformNotReady() from err add_entities([SisyphusLight(table_holder.name, table)], update_before_add=True) diff --git a/homeassistant/components/sisyphus/media_player.py b/homeassistant/components/sisyphus/media_player.py index dbc350453b7..27d470ce885 100644 --- a/homeassistant/components/sisyphus/media_player.py +++ b/homeassistant/components/sisyphus/media_player.py @@ -50,8 +50,8 @@ async def async_setup_platform(hass, config, add_entities, discovery_info=None): try: table_holder = hass.data[DATA_SISYPHUS][host] table = await table_holder.get_table() - except aiohttp.ClientError: - raise PlatformNotReady() + except aiohttp.ClientError as err: + raise PlatformNotReady() from err add_entities([SisyphusPlayer(table_holder.name, host, table)], True) diff --git a/homeassistant/components/smart_meter_texas/__init__.py b/homeassistant/components/smart_meter_texas/__init__.py index e286bfb2557..7b1c6cfa9b7 100644 --- a/homeassistant/components/smart_meter_texas/__init__.py +++ b/homeassistant/components/smart_meter_texas/__init__.py @@ -51,8 +51,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): except SmartMeterTexasAuthError: _LOGGER.error("Username or password was not accepted") return False - except asyncio.TimeoutError: - raise ConfigEntryNotReady + except asyncio.TimeoutError as error: + raise ConfigEntryNotReady from error await smart_meter_texas_data.setup() @@ -113,7 +113,7 @@ class SmartMeterTexasData: try: await meter.read_meter(self.client) except (SmartMeterTexasAPIError, SmartMeterTexasAuthError) as error: - raise UpdateFailed(error) + raise UpdateFailed(error) from error return self.meters diff --git a/homeassistant/components/smart_meter_texas/config_flow.py b/homeassistant/components/smart_meter_texas/config_flow.py index ce62be73c41..211957dac9d 100644 --- a/homeassistant/components/smart_meter_texas/config_flow.py +++ b/homeassistant/components/smart_meter_texas/config_flow.py @@ -35,10 +35,10 @@ async def validate_input(hass: core.HomeAssistant, data): try: await client.authenticate() - except (asyncio.TimeoutError, ClientError, SmartMeterTexasAPIError): - raise CannotConnect + except (asyncio.TimeoutError, ClientError, SmartMeterTexasAPIError) as error: + raise CannotConnect from error except SmartMeterTexasAuthError as error: - raise InvalidAuth(error) + raise InvalidAuth(error) from error # Return info that you want to store in the config entry. return {"title": account.username} diff --git a/homeassistant/components/smarthab/__init__.py b/homeassistant/components/smarthab/__init__.py index cc6499f9c8d..2d22841660a 100644 --- a/homeassistant/components/smarthab/__init__.py +++ b/homeassistant/components/smarthab/__init__.py @@ -59,9 +59,9 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): try: await hub.async_login(username, password) - except pysmarthab.RequestFailedException: + except pysmarthab.RequestFailedException as err: _LOGGER.exception("Error while trying to reach SmartHab API") - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err # Pass hub object to child platforms hass.data[DOMAIN][entry.entry_id] = {DATA_HUB: hub} diff --git a/homeassistant/components/smartthings/__init__.py b/homeassistant/components/smartthings/__init__.py index 48e56e74f70..974cde35faf 100644 --- a/homeassistant/components/smartthings/__init__.py +++ b/homeassistant/components/smartthings/__init__.py @@ -166,10 +166,10 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): remove_entry = True else: _LOGGER.debug(ex, exc_info=True) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex except (ClientConnectionError, RuntimeWarning) as ex: _LOGGER.debug(ex, exc_info=True) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex if remove_entry: hass.async_create_task(hass.config_entries.async_remove(entry.entry_id)) diff --git a/homeassistant/components/sms/config_flow.py b/homeassistant/components/sms/config_flow.py index 148360416a2..52f3a403ed1 100644 --- a/homeassistant/components/sms/config_flow.py +++ b/homeassistant/components/sms/config_flow.py @@ -27,8 +27,8 @@ async def get_imei_from_config(hass: core.HomeAssistant, data): raise CannotConnect try: imei = await gateway.get_imei_async() - except gammu.GSMError: # pylint: disable=no-member - raise CannotConnect + except gammu.GSMError as err: # pylint: disable=no-member + raise CannotConnect from err finally: await gateway.terminate_async() diff --git a/homeassistant/components/solax/sensor.py b/homeassistant/components/solax/sensor.py index 8eb61560e63..3084aefd97c 100644 --- a/homeassistant/components/solax/sensor.py +++ b/homeassistant/components/solax/sensor.py @@ -64,11 +64,11 @@ class RealTimeDataEndpoint: try: api_response = await self.api.get_data() self.ready.set() - except InverterError: + except InverterError as err: if now is not None: self.ready.clear() return - raise PlatformNotReady + raise PlatformNotReady from err data = api_response.data for sensor in self.sensors: if sensor.key in data: diff --git a/homeassistant/components/sonarr/__init__.py b/homeassistant/components/sonarr/__init__.py index 4228d6c8400..601509aa575 100644 --- a/homeassistant/components/sonarr/__init__.py +++ b/homeassistant/components/sonarr/__init__.py @@ -69,8 +69,8 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool try: await sonarr.update() - except SonarrError: - raise ConfigEntryNotReady + except SonarrError as err: + raise ConfigEntryNotReady from err undo_listener = entry.add_update_listener(_async_update_listener) diff --git a/homeassistant/components/songpal/media_player.py b/homeassistant/components/songpal/media_player.py index ae633055b83..2a0bde306b7 100644 --- a/homeassistant/components/songpal/media_player.py +++ b/homeassistant/components/songpal/media_player.py @@ -77,7 +77,7 @@ async def async_setup_entry( except (SongpalException, asyncio.TimeoutError) as ex: _LOGGER.warning("[%s(%s)] Unable to connect", name, endpoint) _LOGGER.debug("Unable to get methods from songpal: %s", ex) - raise PlatformNotReady + raise PlatformNotReady from ex songpal_entity = SongpalEntity(name, device) async_add_entities([songpal_entity], True) diff --git a/homeassistant/components/speedtestdotnet/__init__.py b/homeassistant/components/speedtestdotnet/__init__.py index 3d257174328..57557d4558a 100644 --- a/homeassistant/components/speedtestdotnet/__init__.py +++ b/homeassistant/components/speedtestdotnet/__init__.py @@ -169,8 +169,8 @@ class SpeedTestDataCoordinator(DataUpdateCoordinator): """Update Speedtest data.""" try: return await self.hass.async_add_executor_job(self.update_data) - except (speedtest.ConfigRetrievalError, speedtest.NoMatchedServers): - raise UpdateFailed + except (speedtest.ConfigRetrievalError, speedtest.NoMatchedServers) as err: + raise UpdateFailed from err async def async_set_options(self): """Set options for entry.""" @@ -189,8 +189,8 @@ class SpeedTestDataCoordinator(DataUpdateCoordinator): """Set up SpeedTest.""" try: self.api = await self.hass.async_add_executor_job(speedtest.Speedtest) - except speedtest.ConfigRetrievalError: - raise ConfigEntryNotReady + except speedtest.ConfigRetrievalError as err: + raise ConfigEntryNotReady from err async def request_update(call): """Request update.""" diff --git a/homeassistant/components/spotify/__init__.py b/homeassistant/components/spotify/__init__.py index d28875032da..3f1452742f1 100644 --- a/homeassistant/components/spotify/__init__.py +++ b/homeassistant/components/spotify/__init__.py @@ -70,8 +70,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: try: current_user = await hass.async_add_executor_job(spotify.me) - except SpotifyException: - raise ConfigEntryNotReady + except SpotifyException as err: + raise ConfigEntryNotReady from err hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = { diff --git a/homeassistant/components/stream/__init__.py b/homeassistant/components/stream/__init__.py index 520e3047439..476b64b9650 100644 --- a/homeassistant/components/stream/__init__.py +++ b/homeassistant/components/stream/__init__.py @@ -74,8 +74,8 @@ def request_stream(hass, stream_source, *, fmt="hls", keepalive=False, options=N stream.access_token = secrets.token_hex() stream.start() return hass.data[DOMAIN][ATTR_ENDPOINTS][fmt].format(stream.access_token) - except Exception: - raise HomeAssistantError("Unable to get stream") + except Exception as err: + raise HomeAssistantError("Unable to get stream") from err async def async_setup(hass, config): diff --git a/homeassistant/components/tado/__init__.py b/homeassistant/components/tado/__init__.py index 37e92ff5b4f..9927db80a65 100644 --- a/homeassistant/components/tado/__init__.py +++ b/homeassistant/components/tado/__init__.py @@ -95,7 +95,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): if ex.response.status_code > 400 and ex.response.status_code < 500: _LOGGER.error("Failed to login to tado: %s", ex) return False - raise ConfigEntryNotReady + raise ConfigEntryNotReady from ex # Do first update await hass.async_add_executor_job(tadoconnector.update) diff --git a/homeassistant/components/tado/config_flow.py b/homeassistant/components/tado/config_flow.py index fb60b820ab9..0c45cc809af 100644 --- a/homeassistant/components/tado/config_flow.py +++ b/homeassistant/components/tado/config_flow.py @@ -30,14 +30,14 @@ async def validate_input(hass: core.HomeAssistant, data): Tado, data[CONF_USERNAME], data[CONF_PASSWORD] ) tado_me = await hass.async_add_executor_job(tado.getMe) - except KeyError: - raise InvalidAuth - except RuntimeError: - raise CannotConnect + except KeyError as ex: + raise InvalidAuth from ex + except RuntimeError as ex: + raise CannotConnect from ex except requests.exceptions.HTTPError as ex: if ex.response.status_code > 400 and ex.response.status_code < 500: - raise InvalidAuth - raise CannotConnect + raise InvalidAuth from ex + raise CannotConnect from ex if "homes" not in tado_me or len(tado_me["homes"]) == 0: raise NoHomes diff --git a/homeassistant/components/tankerkoenig/sensor.py b/homeassistant/components/tankerkoenig/sensor.py index d78b5eb2641..b6c80de69b7 100644 --- a/homeassistant/components/tankerkoenig/sensor.py +++ b/homeassistant/components/tankerkoenig/sensor.py @@ -35,8 +35,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= """Fetch data from API endpoint.""" try: return await tankerkoenig.fetch_data() - except LookupError: - raise UpdateFailed("Failed to fetch data") + except LookupError as err: + raise UpdateFailed("Failed to fetch data") from err coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/tesla/__init__.py b/homeassistant/components/tesla/__init__.py index bc2a09788e5..9b8962ae196 100644 --- a/homeassistant/components/tesla/__init__.py +++ b/homeassistant/components/tesla/__init__.py @@ -244,7 +244,7 @@ class TeslaDataUpdateCoordinator(DataUpdateCoordinator): async with async_timeout.timeout(30): return await self.controller.update() except TeslaException as err: - raise UpdateFailed(f"Error communicating with API: {err}") + raise UpdateFailed(f"Error communicating with API: {err}") from err class TeslaDevice(Entity): diff --git a/homeassistant/components/tesla/config_flow.py b/homeassistant/components/tesla/config_flow.py index f9a218d2f5f..9e46a30972f 100644 --- a/homeassistant/components/tesla/config_flow.py +++ b/homeassistant/components/tesla/config_flow.py @@ -142,9 +142,9 @@ async def validate_input(hass: core.HomeAssistant, data): except TeslaException as ex: if ex.code == 401: _LOGGER.error("Invalid credentials: %s", ex) - raise InvalidAuth() + raise InvalidAuth() from ex _LOGGER.error("Unable to communicate with Tesla API: %s", ex) - raise CannotConnect() + raise CannotConnect() from ex _LOGGER.debug("Credentials successfully connected to the Tesla API") return config diff --git a/homeassistant/components/tibber/__init__.py b/homeassistant/components/tibber/__init__.py index 657be67c7fc..b4b29a84297 100644 --- a/homeassistant/components/tibber/__init__.py +++ b/homeassistant/components/tibber/__init__.py @@ -64,8 +64,8 @@ async def async_setup_entry(hass, entry): try: await tibber_connection.update_info() - except asyncio.TimeoutError: - raise ConfigEntryNotReady + except asyncio.TimeoutError as err: + raise ConfigEntryNotReady from err except aiohttp.ClientError as err: _LOGGER.error("Error connecting to Tibber: %s ", err) return False diff --git a/homeassistant/components/tibber/sensor.py b/homeassistant/components/tibber/sensor.py index 323267cae6f..939c6d1597d 100644 --- a/homeassistant/components/tibber/sensor.py +++ b/homeassistant/components/tibber/sensor.py @@ -32,10 +32,10 @@ async def async_setup_entry(hass, entry, async_add_entities): await home.update_info() except asyncio.TimeoutError as err: _LOGGER.error("Timeout connecting to Tibber home: %s ", err) - raise PlatformNotReady() + raise PlatformNotReady() from err except aiohttp.ClientError as err: _LOGGER.error("Error connecting to Tibber home: %s ", err) - raise PlatformNotReady() + raise PlatformNotReady() from err if home.has_active_subscription: dev.append(TibberSensorElPrice(home)) if home.has_real_time_consumption: diff --git a/homeassistant/components/tile/__init__.py b/homeassistant/components/tile/__init__.py index 4f6411ed368..58295c98bef 100644 --- a/homeassistant/components/tile/__init__.py +++ b/homeassistant/components/tile/__init__.py @@ -48,7 +48,7 @@ async def async_setup_entry(hass, config_entry): LOGGER.info("Tile session expired; creating a new one") await client.async_init() except TileError as err: - raise UpdateFailed(f"Error while retrieving data: {err}") + raise UpdateFailed(f"Error while retrieving data: {err}") from err coordinator = DataUpdateCoordinator( hass, diff --git a/homeassistant/components/toon/coordinator.py b/homeassistant/components/toon/coordinator.py index fa4cf52a630..359cb5b0ffb 100644 --- a/homeassistant/components/toon/coordinator.py +++ b/homeassistant/components/toon/coordinator.py @@ -141,4 +141,4 @@ class ToonDataUpdateCoordinator(DataUpdateCoordinator[Status]): try: return await self.toon.update() except ToonError as error: - raise UpdateFailed(f"Invalid response from API: {error}") + raise UpdateFailed(f"Invalid response from API: {error}") from error diff --git a/homeassistant/components/tradfri/__init__.py b/homeassistant/components/tradfri/__init__.py index cef22c636c1..7074532e097 100644 --- a/homeassistant/components/tradfri/__init__.py +++ b/homeassistant/components/tradfri/__init__.py @@ -113,9 +113,9 @@ async def async_setup_entry(hass, entry): try: gateway_info = await api(gateway.get_gateway_info()) - except RequestError: + except RequestError as err: await factory.shutdown() - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err hass.data.setdefault(KEY_API, {})[entry.entry_id] = api hass.data.setdefault(KEY_GATEWAY, {})[entry.entry_id] = gateway diff --git a/homeassistant/components/tradfri/config_flow.py b/homeassistant/components/tradfri/config_flow.py index e438fd20170..e72291c8d88 100644 --- a/homeassistant/components/tradfri/config_flow.py +++ b/homeassistant/components/tradfri/config_flow.py @@ -166,10 +166,10 @@ async def authenticate(hass, host, security_code): try: with async_timeout.timeout(5): key = await api_factory.generate_psk(security_code) - except RequestError: - raise AuthError("invalid_security_code") - except asyncio.TimeoutError: - raise AuthError("timeout") + except RequestError as err: + raise AuthError("invalid_security_code") from err + except asyncio.TimeoutError as err: + raise AuthError("timeout") from err return await get_gateway_info(hass, host, identity, key) @@ -185,10 +185,10 @@ async def get_gateway_info(hass, host, identity, key): gateway_info_result = await api(gateway.get_gateway_info()) await factory.shutdown() - except (OSError, RequestError): + except (OSError, RequestError) as err: # We're also catching OSError as PyTradfri doesn't catch that one yet # Upstream PR: https://github.com/ggravlingen/pytradfri/pull/189 - raise AuthError("cannot_connect") + raise AuthError("cannot_connect") from err return { CONF_HOST: host, diff --git a/homeassistant/components/transmission/__init__.py b/homeassistant/components/transmission/__init__.py index 2fd7e60cf31..00fc2d1b3b5 100644 --- a/homeassistant/components/transmission/__init__.py +++ b/homeassistant/components/transmission/__init__.py @@ -136,13 +136,13 @@ async def get_api(hass, entry): except TransmissionError as error: if "401: Unauthorized" in str(error): _LOGGER.error("Credentials for Transmission client are not valid") - raise AuthenticationError + raise AuthenticationError from error if "111: Connection refused" in str(error): _LOGGER.error("Connecting to the Transmission client %s failed", host) - raise CannotConnect + raise CannotConnect from error _LOGGER.error(error) - raise UnknownError + raise UnknownError from error class TransmissionClient: @@ -166,8 +166,8 @@ class TransmissionClient: try: self.tm_api = await get_api(self.hass, self.config_entry.data) - except CannotConnect: - raise ConfigEntryNotReady + except CannotConnect as error: + raise ConfigEntryNotReady from error except (AuthenticationError, UnknownError): return False diff --git a/homeassistant/components/tts/__init__.py b/homeassistant/components/tts/__init__.py index d1e2d910790..0f758d4a2eb 100644 --- a/homeassistant/components/tts/__init__.py +++ b/homeassistant/components/tts/__init__.py @@ -254,14 +254,14 @@ class SpeechManager: _init_tts_cache_dir, self.hass, cache_dir ) except OSError as err: - raise HomeAssistantError(f"Can't init cache dir {err}") + raise HomeAssistantError(f"Can't init cache dir {err}") from err try: cache_files = await self.hass.async_add_executor_job( _get_cache_files, self.cache_dir ) except OSError as err: - raise HomeAssistantError(f"Can't read cache dir {err}") + raise HomeAssistantError(f"Can't read cache dir {err}") from err if cache_files: self.file_cache.update(cache_files) @@ -408,9 +408,9 @@ class SpeechManager: try: data = await self.hass.async_add_executor_job(load_speech) - except OSError: + except OSError as err: del self.file_cache[key] - raise HomeAssistantError(f"Can't read {voice_file}") + raise HomeAssistantError(f"Can't read {voice_file}") from err self._async_store_to_memcache(key, filename, data) diff --git a/homeassistant/components/tuya/__init__.py b/homeassistant/components/tuya/__init__.py index 6524c026fcf..9d8bb873836 100644 --- a/homeassistant/components/tuya/__init__.py +++ b/homeassistant/components/tuya/__init__.py @@ -95,8 +95,8 @@ async def async_setup_entry(hass, entry): await hass.async_add_executor_job( tuya.init, username, password, country_code, platform ) - except (TuyaNetException, TuyaServerException): - raise ConfigEntryNotReady() + except (TuyaNetException, TuyaServerException) as exc: + raise ConfigEntryNotReady() from exc except TuyaAPIException as exc: _LOGGER.error( diff --git a/homeassistant/components/unifi/controller.py b/homeassistant/components/unifi/controller.py index 3a3229415ab..7c30a34f58f 100644 --- a/homeassistant/components/unifi/controller.py +++ b/homeassistant/components/unifi/controller.py @@ -295,8 +295,8 @@ class UniFiController: description = await self.api.site_description() self._site_role = description[0]["site_role"] - except CannotConnect: - raise ConfigEntryNotReady + except CannotConnect as err: + raise ConfigEntryNotReady from err except Exception as err: # pylint: disable=broad-except LOGGER.error("Unknown error connecting with UniFi controller: %s", err) @@ -428,14 +428,14 @@ async def get_controller( await controller.login() return controller - except aiounifi.Unauthorized: + except aiounifi.Unauthorized as err: LOGGER.warning("Connected to UniFi at %s but not registered.", host) - raise AuthenticationRequired + raise AuthenticationRequired from err - except (asyncio.TimeoutError, aiounifi.RequestError): + except (asyncio.TimeoutError, aiounifi.RequestError) as err: LOGGER.error("Error connecting to the UniFi controller at %s", host) - raise CannotConnect + raise CannotConnect from err - except aiounifi.AiounifiException: + except aiounifi.AiounifiException as err: LOGGER.exception("Unknown UniFi communication error occurred") - raise AuthenticationRequired + raise AuthenticationRequired from err diff --git a/homeassistant/components/updater/__init__.py b/homeassistant/components/updater/__init__.py index f3c9483e4a8..3d7b8b626c9 100644 --- a/homeassistant/components/updater/__init__.py +++ b/homeassistant/components/updater/__init__.py @@ -148,13 +148,15 @@ async def get_newest_version(hass, huuid, include_components): try: res = await req.json() - except ValueError: + except ValueError as err: raise update_coordinator.UpdateFailed( "Received invalid JSON from Home Assistant Update" - ) + ) from err try: res = RESPONSE_SCHEMA(res) return res["version"], res["release-notes"] except vol.Invalid as err: - raise update_coordinator.UpdateFailed(f"Got unexpected response: {err}") + raise update_coordinator.UpdateFailed( + f"Got unexpected response: {err}" + ) from err diff --git a/homeassistant/components/upnp/__init__.py b/homeassistant/components/upnp/__init__.py index 8479bd06518..52cada89333 100644 --- a/homeassistant/components/upnp/__init__.py +++ b/homeassistant/components/upnp/__init__.py @@ -109,8 +109,8 @@ async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry) st = config_entry.data.get(CONFIG_ENTRY_ST) # pylint: disable=invalid-name try: device = await async_discover_and_construct(hass, udn, st) - except asyncio.TimeoutError: - raise ConfigEntryNotReady + except asyncio.TimeoutError as err: + raise ConfigEntryNotReady from err if not device: _LOGGER.info("Unable to create UPnP/IGD, aborting") diff --git a/homeassistant/components/uvc/camera.py b/homeassistant/components/uvc/camera.py index 3e0363f4f35..e07fac28d1f 100644 --- a/homeassistant/components/uvc/camera.py +++ b/homeassistant/components/uvc/camera.py @@ -58,10 +58,10 @@ def setup_platform(hass, config, add_entities, discovery_info=None): return False except nvr.NvrError as ex: _LOGGER.error("NVR refuses to talk to me: %s", str(ex)) - raise PlatformNotReady + raise PlatformNotReady from ex except requests.exceptions.ConnectionError as ex: _LOGGER.error("Unable to connect to NVR: %s", str(ex)) - raise PlatformNotReady + raise PlatformNotReady from ex add_entities( [ diff --git a/homeassistant/components/velbus/__init__.py b/homeassistant/components/velbus/__init__.py index 72ffda48b57..a859567e219 100644 --- a/homeassistant/components/velbus/__init__.py +++ b/homeassistant/components/velbus/__init__.py @@ -70,7 +70,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): controller.scan(callback) except velbus.util.VelbusException as err: _LOGGER.error("An error occurred: %s", err) - raise ConfigEntryNotReady + raise ConfigEntryNotReady from err def syn_clock(self, service=None): try: diff --git a/homeassistant/components/waqi/sensor.py b/homeassistant/components/waqi/sensor.py index 90e55ea08a0..ec18880b5ba 100644 --- a/homeassistant/components/waqi/sensor.py +++ b/homeassistant/components/waqi/sensor.py @@ -84,9 +84,12 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= & set(station_filter) ): dev.append(waqi_sensor) - except (aiohttp.client_exceptions.ClientConnectorError, asyncio.TimeoutError): + except ( + aiohttp.client_exceptions.ClientConnectorError, + asyncio.TimeoutError, + ) as err: _LOGGER.exception("Failed to connect to WAQI servers") - raise PlatformNotReady + raise PlatformNotReady from err async_add_entities(dev, True) diff --git a/homeassistant/components/websocket_api/auth.py b/homeassistant/components/websocket_api/auth.py index f5b29f49b1e..3c795902900 100644 --- a/homeassistant/components/websocket_api/auth.py +++ b/homeassistant/components/websocket_api/auth.py @@ -62,7 +62,7 @@ class AuthPhase: ) self._logger.warning(error_msg) self._send_message(auth_invalid_message(error_msg)) - raise Disconnect + raise Disconnect from err if "access_token" in msg: self._logger.debug("Received access_token") diff --git a/homeassistant/components/websocket_api/http.py b/homeassistant/components/websocket_api/http.py index ab412e06583..7c56fcbc606 100644 --- a/homeassistant/components/websocket_api/http.py +++ b/homeassistant/components/websocket_api/http.py @@ -180,9 +180,9 @@ class WebSocketHandler: try: with async_timeout.timeout(10): msg = await wsock.receive() - except asyncio.TimeoutError: + except asyncio.TimeoutError as err: disconnect_warn = "Did not receive auth message within 10 seconds" - raise Disconnect + raise Disconnect from err if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING): raise Disconnect @@ -193,9 +193,9 @@ class WebSocketHandler: try: msg_data = msg.json() - except ValueError: + except ValueError as err: disconnect_warn = "Received invalid JSON." - raise Disconnect + raise Disconnect from err self._logger.debug("Received %s", msg_data) connection = await auth.async_handle(msg_data) diff --git a/homeassistant/components/wled/__init__.py b/homeassistant/components/wled/__init__.py index 76b61dd7808..5da55d0e3bd 100644 --- a/homeassistant/components/wled/__init__.py +++ b/homeassistant/components/wled/__init__.py @@ -136,7 +136,7 @@ class WLEDDataUpdateCoordinator(DataUpdateCoordinator[WLEDDevice]): try: return await self.wled.update(full_update=not self.last_update_success) except WLEDError as error: - raise UpdateFailed(f"Invalid response from API: {error}") + raise UpdateFailed(f"Invalid response from API: {error}") from error class WLEDEntity(Entity): diff --git a/homeassistant/components/wolflink/__init__.py b/homeassistant/components/wolflink/__init__.py index cce9d542446..9a272c502a0 100644 --- a/homeassistant/components/wolflink/__init__.py +++ b/homeassistant/components/wolflink/__init__.py @@ -53,9 +53,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): values = await wolf_client.fetch_value(gateway_id, device_id, parameters) return {v.value_id: v.value for v in values} except ConnectError as exception: - raise UpdateFailed(f"Error communicating with API: {exception}") - except InvalidAuth: - raise UpdateFailed("Invalid authentication during update.") + raise UpdateFailed( + f"Error communicating with API: {exception}" + ) from exception + except InvalidAuth as exception: + raise UpdateFailed("Invalid authentication during update.") from exception coordinator = DataUpdateCoordinator( hass, @@ -98,6 +100,6 @@ async def fetch_parameters(client: WolfClient, gateway_id: int, device_id: int): fetched_parameters = await client.fetch_parameters(gateway_id, device_id) return [param for param in fetched_parameters if param.name != "Reglertyp"] except ConnectError as exception: - raise UpdateFailed(f"Error communicating with API: {exception}") - except InvalidAuth: - raise UpdateFailed("Invalid authentication during update.") + raise UpdateFailed(f"Error communicating with API: {exception}") from exception + except InvalidAuth as exception: + raise UpdateFailed("Invalid authentication during update.") from exception diff --git a/homeassistant/components/workday/binary_sensor.py b/homeassistant/components/workday/binary_sensor.py index 1613f10d66a..8f8b794515e 100644 --- a/homeassistant/components/workday/binary_sensor.py +++ b/homeassistant/components/workday/binary_sensor.py @@ -36,10 +36,10 @@ def valid_country(value: Any) -> str: try: raw_value = value.encode("utf-8") - except UnicodeError: + except UnicodeError as err: raise vol.Invalid( "The country name or the abbreviation must be a valid UTF-8 string." - ) + ) from err if not raw_value: raise vol.Invalid("Country name or the abbreviation must not be empty.") if value not in all_supported_countries: diff --git a/homeassistant/components/xiaomi_miio/air_quality.py b/homeassistant/components/xiaomi_miio/air_quality.py index 7da4da9c05d..baeb0bf39e5 100644 --- a/homeassistant/components/xiaomi_miio/air_quality.py +++ b/homeassistant/components/xiaomi_miio/air_quality.py @@ -53,8 +53,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= try: device_info = await hass.async_add_executor_job(miio_device.info) - except DeviceException: - raise PlatformNotReady + except DeviceException as ex: + raise PlatformNotReady from ex model = device_info.model unique_id = f"{model}-{device_info.mac_address}" diff --git a/homeassistant/components/xiaomi_miio/fan.py b/homeassistant/components/xiaomi_miio/fan.py index 6be4831b6e0..3382ca910c3 100644 --- a/homeassistant/components/xiaomi_miio/fan.py +++ b/homeassistant/components/xiaomi_miio/fan.py @@ -523,8 +523,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= device_info.firmware_version, device_info.hardware_version, ) - except DeviceException: - raise PlatformNotReady + except DeviceException as ex: + raise PlatformNotReady from ex if model in PURIFIER_MIOT: air_purifier = AirPurifierMiot(host, token) diff --git a/homeassistant/components/xiaomi_miio/light.py b/homeassistant/components/xiaomi_miio/light.py index 967ea8043f3..a148b98ee22 100644 --- a/homeassistant/components/xiaomi_miio/light.py +++ b/homeassistant/components/xiaomi_miio/light.py @@ -150,8 +150,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= device_info.firmware_version, device_info.hardware_version, ) - except DeviceException: - raise PlatformNotReady + except DeviceException as ex: + raise PlatformNotReady from ex if model == "philips.light.sread1": light = PhilipsEyecare(host, token) diff --git a/homeassistant/components/xiaomi_miio/remote.py b/homeassistant/components/xiaomi_miio/remote.py index 9c8d06e0b0d..c88b2d3663c 100644 --- a/homeassistant/components/xiaomi_miio/remote.py +++ b/homeassistant/components/xiaomi_miio/remote.py @@ -86,7 +86,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= ) except DeviceException as ex: _LOGGER.error("Device unavailable or token incorrect: %s", ex) - raise PlatformNotReady + raise PlatformNotReady from ex if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} diff --git a/homeassistant/components/xiaomi_miio/sensor.py b/homeassistant/components/xiaomi_miio/sensor.py index 4b1442a8c55..924d6d8a23d 100644 --- a/homeassistant/components/xiaomi_miio/sensor.py +++ b/homeassistant/components/xiaomi_miio/sensor.py @@ -122,8 +122,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= device_info.hardware_version, ) device = XiaomiAirQualityMonitor(name, air_quality_monitor, model, unique_id) - except DeviceException: - raise PlatformNotReady + except DeviceException as ex: + raise PlatformNotReady from ex hass.data[DATA_KEY][host] = device async_add_entities([device], update_before_add=True) diff --git a/homeassistant/components/xiaomi_miio/switch.py b/homeassistant/components/xiaomi_miio/switch.py index d8552244ce8..26ffb7e578f 100644 --- a/homeassistant/components/xiaomi_miio/switch.py +++ b/homeassistant/components/xiaomi_miio/switch.py @@ -139,8 +139,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= device_info.firmware_version, device_info.hardware_version, ) - except DeviceException: - raise PlatformNotReady + except DeviceException as ex: + raise PlatformNotReady from ex if model in ["chuangmi.plug.v1", "chuangmi.plug.v3"]: plug = ChuangmiPlug(host, token, model=model) diff --git a/homeassistant/components/yi/camera.py b/homeassistant/components/yi/camera.py index 4273b5294ed..e669f530197 100644 --- a/homeassistant/components/yi/camera.py +++ b/homeassistant/components/yi/camera.py @@ -90,7 +90,7 @@ class YiCamera(Camera): await ftp.connect(self.host) await ftp.login(self.user, self.passwd) except (ConnectionRefusedError, StatusCodeError) as err: - raise PlatformNotReady(err) + raise PlatformNotReady(err) from err try: await ftp.change_directory(self.path) diff --git a/homeassistant/components/zha/api.py b/homeassistant/components/zha/api.py index 1ba9ada5413..bdfeb7815c5 100644 --- a/homeassistant/components/zha/api.py +++ b/homeassistant/components/zha/api.py @@ -316,8 +316,8 @@ def cv_group_member(value: Any) -> GroupMember: group_member = GroupMember( ieee=EUI64.convert(value["ieee"]), endpoint_id=value["endpoint_id"] ) - except KeyError: - raise vol.Invalid("Not a group member") + except KeyError as err: + raise vol.Invalid("Not a group member") from err return group_member @@ -724,8 +724,8 @@ def is_cluster_binding(value: Any) -> ClusterBinding: id=value["id"], endpoint_id=value["endpoint_id"], ) - except KeyError: - raise vol.Invalid("Not a cluster binding") + except KeyError as err: + raise vol.Invalid("Not a cluster binding") from err return cluster_binding diff --git a/homeassistant/components/zha/device_trigger.py b/homeassistant/components/zha/device_trigger.py index e92d0fb3028..9d04d36f748 100644 --- a/homeassistant/components/zha/device_trigger.py +++ b/homeassistant/components/zha/device_trigger.py @@ -29,8 +29,8 @@ async def async_validate_trigger_config(hass, config): trigger = (config[CONF_TYPE], config[CONF_SUBTYPE]) try: zha_device = await async_get_zha_device(hass, config[CONF_DEVICE_ID]) - except (KeyError, AttributeError): - raise InvalidDeviceAutomationConfig + except (KeyError, AttributeError) as err: + raise InvalidDeviceAutomationConfig from err if ( zha_device.device_automation_triggers is None or trigger not in zha_device.device_automation_triggers diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index 878d162c2ff..f708f138f88 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -516,9 +516,9 @@ class ConfigEntriesFlowManager(data_entry_flow.FlowManager): """ try: integration = await loader.async_get_integration(self.hass, handler_key) - except loader.IntegrationNotFound: + except loader.IntegrationNotFound as err: _LOGGER.error("Cannot find integration %s", handler_key) - raise data_entry_flow.UnknownHandler + raise data_entry_flow.UnknownHandler from err # Make sure requirements and dependencies of component are resolved await async_process_deps_reqs(self.hass, self._hass_config, integration) diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index 46b309815ab..394500b5170 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -173,8 +173,8 @@ def isdevice(value: Any) -> str: try: os.stat(value) return str(value) - except OSError: - raise vol.Invalid(f"No device at {value} found") + except OSError as err: + raise vol.Invalid(f"No device at {value} found") from err def matches_regex(regex: str) -> Callable[[Any], str]: @@ -201,12 +201,12 @@ def is_regex(value: Any) -> Pattern[Any]: try: r = re.compile(value) return r - except TypeError: + except TypeError as err: raise vol.Invalid( f"value {value} is of the wrong type for a regular expression" - ) - except re.error: - raise vol.Invalid(f"value {value} is not a valid regular expression") + ) from err + except re.error as err: + raise vol.Invalid(f"value {value} is not a valid regular expression") from err def isfile(value: Any) -> str: @@ -331,8 +331,8 @@ def time(value: Any) -> time_sys: try: time_val = dt_util.parse_time(value) - except TypeError: - raise vol.Invalid("Not a parseable type") + except TypeError as err: + raise vol.Invalid("Not a parseable type") from err if time_val is None: raise vol.Invalid(f"Invalid time specified: {value}") @@ -347,8 +347,8 @@ def date(value: Any) -> date_sys: try: date_val = dt_util.parse_date(value) - except TypeError: - raise vol.Invalid("Not a parseable type") + except TypeError as err: + raise vol.Invalid("Not a parseable type") from err if date_val is None: raise vol.Invalid("Could not parse date") @@ -380,8 +380,8 @@ def time_period_str(value: str) -> timedelta: second = float(parsed[2]) except IndexError: second = 0 - except ValueError: - raise vol.Invalid(TIME_PERIOD_ERROR.format(value)) + except ValueError as err: + raise vol.Invalid(TIME_PERIOD_ERROR.format(value)) from err offset = timedelta(hours=hour, minutes=minute, seconds=second) @@ -395,8 +395,8 @@ def time_period_seconds(value: Union[float, str]) -> timedelta: """Validate and transform seconds to a time offset.""" try: return timedelta(seconds=float(value)) - except (ValueError, TypeError): - raise vol.Invalid(f"Expected seconds, got {value}") + except (ValueError, TypeError) as err: + raise vol.Invalid(f"Expected seconds, got {value}") from err time_period = vol.Any(time_period_str, time_period_seconds, timedelta, time_period_dict) @@ -525,7 +525,7 @@ def template(value: Optional[Any]) -> template_helper.Template: template_value.ensure_valid() return cast(template_helper.Template, template_value) except TemplateError as ex: - raise vol.Invalid(f"invalid template ({ex})") + raise vol.Invalid(f"invalid template ({ex})") from ex def dynamic_template(value: Optional[Any]) -> template_helper.Template: @@ -543,7 +543,7 @@ def dynamic_template(value: Optional[Any]) -> template_helper.Template: template_value.ensure_valid() return cast(template_helper.Template, template_value) except TemplateError as ex: - raise vol.Invalid(f"invalid template ({ex})") + raise vol.Invalid(f"invalid template ({ex})") from ex def template_complex(value: Any) -> Any: diff --git a/homeassistant/helpers/frame.py b/homeassistant/helpers/frame.py index 35f7b3fab9f..def2508ff92 100644 --- a/homeassistant/helpers/frame.py +++ b/homeassistant/helpers/frame.py @@ -54,9 +54,11 @@ def report(what: str) -> None: """ try: integration_frame = get_integration_frame() - except MissingIntegrationFrame: + except MissingIntegrationFrame as err: # Did not source from an integration? Hard error. - raise RuntimeError(f"Detected code that {what}. Please report this issue.") + raise RuntimeError( + f"Detected code that {what}. Please report this issue." + ) from err report_integration(what, integration_frame) diff --git a/homeassistant/helpers/network.py b/homeassistant/helpers/network.py index 471cabd0032..d40fd9fad2b 100644 --- a/homeassistant/helpers/network.py +++ b/homeassistant/helpers/network.py @@ -199,8 +199,8 @@ def _get_cloud_url(hass: HomeAssistant, require_current_request: bool = False) - if "cloud" in hass.config.components: try: cloud_url = yarl.URL(cast(str, hass.components.cloud.async_remote_ui_url())) - except hass.components.cloud.CloudNotAvailable: - raise NoURLAvailableError + except hass.components.cloud.CloudNotAvailable as err: + raise NoURLAvailableError from err if not require_current_request or cloud_url.host == _get_request_host(): return normalize_url(str(cloud_url)) diff --git a/homeassistant/helpers/script.py b/homeassistant/helpers/script.py index 7148f633dfb..ad0536ff3f9 100644 --- a/homeassistant/helpers/script.py +++ b/homeassistant/helpers/script.py @@ -264,7 +264,7 @@ class _ScriptRun: ex, level=logging.ERROR, ) - raise _StopScript + raise _StopScript from ex async def _async_delay_step(self): """Handle delay.""" @@ -327,10 +327,10 @@ class _ScriptRun: try: async with timeout(delay) as to_context: await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) - except asyncio.TimeoutError: + except asyncio.TimeoutError as ex: if not self._action.get(CONF_CONTINUE_ON_TIMEOUT, True): self._log(_TIMEOUT_MSG) - raise _StopScript + raise _StopScript from ex self._variables["wait"]["remaining"] = 0.0 finally: for task in tasks: @@ -502,7 +502,7 @@ class _ScriptRun: ex, level=logging.ERROR, ) - raise _StopScript + raise _StopScript from ex extra_msg = f" of {count}" for iteration in range(1, count + 1): set_repeat_var(iteration, count) @@ -600,10 +600,10 @@ class _ScriptRun: try: async with timeout(delay) as to_context: await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) - except asyncio.TimeoutError: + except asyncio.TimeoutError as ex: if not self._action.get(CONF_CONTINUE_ON_TIMEOUT, True): self._log(_TIMEOUT_MSG) - raise _StopScript + raise _StopScript from ex self._variables["wait"]["remaining"] = 0.0 finally: for task in tasks: diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 2403967e3cf..fddd32c8760 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -232,7 +232,7 @@ class Template: try: self._compiled_code = self._env.compile(self.template) except jinja2.exceptions.TemplateSyntaxError as err: - raise TemplateError(err) + raise TemplateError(err) from err def extract_entities( self, variables: TemplateVarsType = None @@ -272,7 +272,7 @@ class Template: try: return compiled.render(kwargs).strip() except jinja2.TemplateError as err: - raise TemplateError(err) + raise TemplateError(err) from err @callback def async_render_to_info( diff --git a/homeassistant/scripts/check_config.py b/homeassistant/scripts/check_config.py index 487d97ffdd8..8d0235413db 100644 --- a/homeassistant/scripts/check_config.py +++ b/homeassistant/scripts/check_config.py @@ -45,7 +45,7 @@ def color(the_color, *args, reset=None): return parse_colors(the_color) return parse_colors(the_color) + " ".join(args) + escape_codes[reset or "reset"] except KeyError as k: - raise ValueError(f"Invalid color {k!s} in {the_color}") + raise ValueError(f"Invalid color {k!s} in {the_color}") from k def run(script_args: List) -> int: diff --git a/homeassistant/util/json.py b/homeassistant/util/json.py index 7b6da837c49..e906462a250 100644 --- a/homeassistant/util/json.py +++ b/homeassistant/util/json.py @@ -35,10 +35,10 @@ def load_json( _LOGGER.debug("JSON file not found: %s", filename) except ValueError as error: _LOGGER.exception("Could not parse JSON content: %s", filename) - raise HomeAssistantError(error) + raise HomeAssistantError(error) from error except OSError as error: _LOGGER.exception("JSON file reading failed: %s", filename) - raise HomeAssistantError(error) + raise HomeAssistantError(error) from error return {} if default is None else default @@ -55,10 +55,10 @@ def save_json( """ try: json_data = json.dumps(data, indent=4, cls=encoder) - except TypeError: + except TypeError as error: msg = f"Failed to serialize to JSON: {filename}. Bad data at {format_unserializable_data(find_paths_unserializable_data(data))}" _LOGGER.error(msg) - raise SerializationError(msg) + raise SerializationError(msg) from error tmp_filename = "" tmp_path = os.path.split(filename)[0] @@ -74,7 +74,7 @@ def save_json( os.replace(tmp_filename, filename) except OSError as error: _LOGGER.exception("Saving JSON file failed: %s", filename) - raise WriteError(error) + raise WriteError(error) from error finally: if os.path.exists(tmp_filename): try: diff --git a/homeassistant/util/ruamel_yaml.py b/homeassistant/util/ruamel_yaml.py index 8635de00fe4..496ca377936 100644 --- a/homeassistant/util/ruamel_yaml.py +++ b/homeassistant/util/ruamel_yaml.py @@ -70,7 +70,7 @@ def object_to_yaml(data: JSON_TYPE) -> str: return result except YAMLError as exc: _LOGGER.error("YAML error: %s", exc) - raise HomeAssistantError(exc) + raise HomeAssistantError(exc) from exc def yaml_to_object(data: str) -> JSON_TYPE: @@ -81,7 +81,7 @@ def yaml_to_object(data: str) -> JSON_TYPE: return result except YAMLError as exc: _LOGGER.error("YAML error: %s", exc) - raise HomeAssistantError(exc) + raise HomeAssistantError(exc) from exc def load_yaml(fname: str, round_trip: bool = False) -> JSON_TYPE: @@ -102,10 +102,10 @@ def load_yaml(fname: str, round_trip: bool = False) -> JSON_TYPE: return yaml.load(conf_file) or OrderedDict() except YAMLError as exc: _LOGGER.error("YAML error in %s: %s", fname, exc) - raise HomeAssistantError(exc) + raise HomeAssistantError(exc) from exc except UnicodeDecodeError as exc: _LOGGER.error("Unable to read file %s: %s", fname, exc) - raise HomeAssistantError(exc) + raise HomeAssistantError(exc) from exc def save_yaml(fname: str, data: JSON_TYPE) -> None: @@ -132,10 +132,10 @@ def save_yaml(fname: str, data: JSON_TYPE) -> None: pass except YAMLError as exc: _LOGGER.error(str(exc)) - raise HomeAssistantError(exc) + raise HomeAssistantError(exc) from exc except OSError as exc: _LOGGER.exception("Saving YAML file %s failed: %s", fname, exc) - raise WriteError(exc) + raise WriteError(exc) from exc finally: if os.path.exists(tmp_fname): try: diff --git a/homeassistant/util/yaml/loader.py b/homeassistant/util/yaml/loader.py index a58480e26b7..7e954f21e1a 100644 --- a/homeassistant/util/yaml/loader.py +++ b/homeassistant/util/yaml/loader.py @@ -61,10 +61,10 @@ def load_yaml(fname: str) -> JSON_TYPE: return yaml.load(conf_file, Loader=SafeLineLoader) or OrderedDict() except yaml.YAMLError as exc: _LOGGER.error(str(exc)) - raise HomeAssistantError(exc) + raise HomeAssistantError(exc) from exc except UnicodeDecodeError as exc: _LOGGER.error("Unable to read file %s: %s", fname, exc) - raise HomeAssistantError(exc) + raise HomeAssistantError(exc) from exc @overload @@ -109,8 +109,10 @@ def _include_yaml(loader: SafeLineLoader, node: yaml.nodes.Node) -> JSON_TYPE: fname = os.path.join(os.path.dirname(loader.name), node.value) try: return _add_reference(load_yaml(fname), loader, node) - except FileNotFoundError: - raise HomeAssistantError(f"{node.start_mark}: Unable to read file {fname}.") + except FileNotFoundError as exc: + raise HomeAssistantError( + f"{node.start_mark}: Unable to read file {fname}." + ) from exc def _is_file_valid(name: str) -> bool: @@ -195,12 +197,12 @@ def _ordered_dict(loader: SafeLineLoader, node: yaml.nodes.MappingNode) -> Order try: hash(key) - except TypeError: + except TypeError as exc: fname = getattr(loader.stream, "name", "") raise yaml.MarkedYAMLError( context=f'invalid key: "{key}"', context_mark=yaml.Mark(fname, 0, line, -1, None, None), - ) + ) from exc if key in seen: fname = getattr(loader.stream, "name", "")