Exception chaining and wrapping improvements (#39320)

* Remove unnecessary exception re-wraps

* Preserve exception chains on re-raise

We slap "from cause" to almost all possible cases here. In some cases it
could conceivably be better to do "from None" if we really want to hide
the cause. However those should be in the minority, and "from cause"
should be an improvement over the corresponding raise without a "from"
in all cases anyway.

The only case where we raise from None here is in plex, where the
exception for an original invalid SSL cert is not the root cause for
failure to validate a newly fetched one.

Follow local convention on exception variable names if there is a
consistent one, otherwise `err` to match with majority of codebase.

* Fix mistaken re-wrap in homematicip_cloud/hap.py

Missed the difference between HmipConnectionError and
HmipcConnectionError.

* Do not hide original error on plex new cert validation error

Original is not the cause for the new one, but showing old in the
traceback is useful nevertheless.
This commit is contained in:
Ville Skyttä 2020-08-28 14:50:32 +03:00 committed by GitHub
parent d768fd4de9
commit b4bac0f7a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
204 changed files with 550 additions and 518 deletions

View file

@ -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

View file

@ -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

View file

@ -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(

View file

@ -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(

View file

@ -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}}

View file

@ -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

View file

@ -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]

View file

@ -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,

View file

@ -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": [

View file

@ -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()):

View file

@ -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()

View file

@ -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)

View file

@ -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."""

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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."""

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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")

View file

@ -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(

View file

@ -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):

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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):

View file

@ -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",

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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))

View file

@ -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)])

View file

@ -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

View file

@ -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(

View file

@ -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(

View file

@ -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

View file

@ -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)

View file

@ -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(

View file

@ -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

View file

@ -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]:

View file

@ -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."""

View file

@ -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

View file

@ -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):

View file

@ -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))

View file

@ -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

View file

@ -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)

View file

@ -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"]

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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):

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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])

View file

@ -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):

View file

@ -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,

View file

@ -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]}"}

View file

@ -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"]

View file

@ -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

View file

@ -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)

View file

@ -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()

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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())

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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):

View file

@ -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

View file

@ -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."""

View file

@ -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)

View file

@ -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

View file

@ -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,

View file

@ -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())

View file

@ -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']}"

View file

@ -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

View file

@ -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."""

View file

@ -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:

View file

@ -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 = {}

View file

@ -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):

View file

@ -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):

View file

@ -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)

View file

@ -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())

View file

@ -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")

View file

@ -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"}

View file

@ -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(

View file

@ -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

View file

@ -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")

View file

@ -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"]

View file

@ -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."""

View file

@ -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

View file

@ -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()

Some files were not shown because too many files have changed in this diff Show more