Rename and deprecate exception classes (#739)

# Public #
SmartDeviceException -> KasaException
UnsupportedDeviceException(SmartDeviceException) -> UnsupportedDeviceError(KasaException)
TimeoutException(SmartDeviceException, asyncio.TimeoutError) -> TimeoutError(KasaException, asyncio.TimeoutError)

Add new exception for error codes -> DeviceError(KasaException)
AuthenticationException(SmartDeviceException) -> AuthenticationError(DeviceError)

# Internal #
RetryableException(SmartDeviceException) -> _RetryableError(DeviceError)
ConnectionException(SmartDeviceException) -> _ConnectionError(KasaException)
This commit is contained in:
Steven B
2024-02-21 15:52:55 +00:00
committed by GitHub
parent 4beff228c9
commit 8c39e81a40
44 changed files with 393 additions and 361 deletions

View File

@@ -13,7 +13,7 @@ from ..bulb import HSV, Bulb, BulbPreset, ColorTempRange
from ..device_type import DeviceType
from ..deviceconfig import DeviceConfig
from ..protocol import BaseProtocol
from .iotdevice import IotDevice, SmartDeviceException, requires_update
from .iotdevice import IotDevice, KasaException, requires_update
from .modules import Antitheft, Cloud, Countdown, Emeter, Schedule, Time, Usage
@@ -97,7 +97,7 @@ class IotBulb(IotDevice, Bulb):
so you must await :func:`update()` to fetch updates values from the device.
Errors reported by the device are raised as
:class:`SmartDeviceExceptions <kasa.exceptions.SmartDeviceException>`,
:class:`KasaException <kasa.exceptions.KasaException>`,
and should be handled by the user of the library.
Examples:
@@ -233,7 +233,7 @@ class IotBulb(IotDevice, Bulb):
:return: White temperature range in Kelvin (minimum, maximum)
"""
if not self.is_variable_color_temp:
raise SmartDeviceException("Color temperature not supported")
raise KasaException("Color temperature not supported")
for model, temp_range in TPLINK_KELVIN.items():
sys_info = self.sys_info
@@ -249,7 +249,7 @@ class IotBulb(IotDevice, Bulb):
"""Query the light state."""
light_state = self.sys_info["light_state"]
if light_state is None:
raise SmartDeviceException(
raise KasaException(
"The device has no light_state or you have not called update()"
)
@@ -333,7 +333,7 @@ class IotBulb(IotDevice, Bulb):
:return: hue, saturation and value (degrees, %, %)
"""
if not self.is_color:
raise SmartDeviceException("Bulb does not support color.")
raise KasaException("Bulb does not support color.")
light_state = cast(dict, self.light_state)
@@ -360,7 +360,7 @@ class IotBulb(IotDevice, Bulb):
:param int transition: transition in milliseconds.
"""
if not self.is_color:
raise SmartDeviceException("Bulb does not support color.")
raise KasaException("Bulb does not support color.")
if not isinstance(hue, int) or not (0 <= hue <= 360):
raise ValueError(f"Invalid hue value: {hue} (valid range: 0-360)")
@@ -387,7 +387,7 @@ class IotBulb(IotDevice, Bulb):
def color_temp(self) -> int:
"""Return color temperature of the device in kelvin."""
if not self.is_variable_color_temp:
raise SmartDeviceException("Bulb does not support colortemp.")
raise KasaException("Bulb does not support colortemp.")
light_state = self.light_state
return int(light_state["color_temp"])
@@ -402,7 +402,7 @@ class IotBulb(IotDevice, Bulb):
:param int transition: transition in milliseconds.
"""
if not self.is_variable_color_temp:
raise SmartDeviceException("Bulb does not support colortemp.")
raise KasaException("Bulb does not support colortemp.")
valid_temperature_range = self.valid_temperature_range
if temp < valid_temperature_range[0] or temp > valid_temperature_range[1]:
@@ -423,7 +423,7 @@ class IotBulb(IotDevice, Bulb):
def brightness(self) -> int:
"""Return the current brightness in percentage."""
if not self.is_dimmable: # pragma: no cover
raise SmartDeviceException("Bulb is not dimmable.")
raise KasaException("Bulb is not dimmable.")
light_state = self.light_state
return int(light_state["brightness"])
@@ -438,7 +438,7 @@ class IotBulb(IotDevice, Bulb):
:param int transition: transition in milliseconds.
"""
if not self.is_dimmable: # pragma: no cover
raise SmartDeviceException("Bulb is not dimmable.")
raise KasaException("Bulb is not dimmable.")
self._raise_for_invalid_brightness(brightness)
@@ -511,10 +511,10 @@ class IotBulb(IotDevice, Bulb):
obtained using :func:`presets`.
"""
if len(self.presets) == 0:
raise SmartDeviceException("Device does not supported saving presets")
raise KasaException("Device does not supported saving presets")
if preset.index >= len(self.presets):
raise SmartDeviceException("Invalid preset index")
raise KasaException("Invalid preset index")
return await self._query_helper(
self.LIGHT_SERVICE, "set_preferred_state", preset.dict(exclude_none=True)

View File

@@ -21,7 +21,7 @@ from typing import Any, Dict, List, Optional, Sequence, Set
from ..device import Device, WifiNetwork
from ..deviceconfig import DeviceConfig
from ..emeterstatus import EmeterStatus
from ..exceptions import SmartDeviceException
from ..exceptions import KasaException
from ..feature import Feature
from ..protocol import BaseProtocol
from .iotmodule import IotModule
@@ -48,9 +48,7 @@ def requires_update(f):
async def wrapped(*args, **kwargs):
self = args[0]
if self._last_update is None and f.__name__ not in self._sys_info:
raise SmartDeviceException(
"You need to await update() to access the data"
)
raise KasaException("You need to await update() to access the data")
return await f(*args, **kwargs)
else:
@@ -59,9 +57,7 @@ def requires_update(f):
def wrapped(*args, **kwargs):
self = args[0]
if self._last_update is None and f.__name__ not in self._sys_info:
raise SmartDeviceException(
"You need to await update() to access the data"
)
raise KasaException("You need to await update() to access the data")
return f(*args, **kwargs)
f.requires_update = True
@@ -92,7 +88,8 @@ class IotDevice(Device):
All changes to the device are done using awaitable methods,
which will not change the cached values, but you must await update() separately.
Errors reported by the device are raised as SmartDeviceExceptions,
Errors reported by the device are raised as
:class:`KasaException <kasa.exceptions.KasaException>`,
and should be handled by the user of the library.
Examples:
@@ -221,9 +218,9 @@ class IotDevice(Device):
def _verify_emeter(self) -> None:
"""Raise an exception if there is no emeter."""
if not self.has_emeter:
raise SmartDeviceException("Device has no emeter")
raise KasaException("Device has no emeter")
if self.emeter_type not in self._last_update:
raise SmartDeviceException("update() required prior accessing emeter")
raise KasaException("update() required prior accessing emeter")
async def _query_helper(
self, target: str, cmd: str, arg: Optional[Dict] = None, child_ids=None
@@ -241,20 +238,20 @@ class IotDevice(Device):
try:
response = await self._raw_query(request=request)
except Exception as ex:
raise SmartDeviceException(f"Communication error on {target}:{cmd}") from ex
raise KasaException(f"Communication error on {target}:{cmd}") from ex
if target not in response:
raise SmartDeviceException(f"No required {target} in response: {response}")
raise KasaException(f"No required {target} in response: {response}")
result = response[target]
if "err_code" in result and result["err_code"] != 0:
raise SmartDeviceException(f"Error on {target}.{cmd}: {result}")
raise KasaException(f"Error on {target}.{cmd}: {result}")
if cmd not in result:
raise SmartDeviceException(f"No command in response: {response}")
raise KasaException(f"No command in response: {response}")
result = result[cmd]
if "err_code" in result and result["err_code"] != 0:
raise SmartDeviceException(f"Error on {target} {cmd}: {result}")
raise KasaException(f"Error on {target} {cmd}: {result}")
if "err_code" in result:
del result["err_code"]
@@ -513,7 +510,7 @@ class IotDevice(Device):
sys_info = self._sys_info
mac = sys_info.get("mac", sys_info.get("mic_mac"))
if not mac:
raise SmartDeviceException(
raise KasaException(
"Unknown mac, please submit a bug report with sys_info output."
)
mac = mac.replace("-", ":")
@@ -656,14 +653,14 @@ class IotDevice(Device):
try:
info = await _scan("netif")
except SmartDeviceException as ex:
except KasaException as ex:
_LOGGER.debug(
"Unable to scan using 'netif', retrying with 'softaponboarding': %s", ex
)
info = await _scan("smartlife.iot.common.softaponboarding")
if "ap_list" not in info:
raise SmartDeviceException("Invalid response for wifi scan: %s" % info)
raise KasaException("Invalid response for wifi scan: %s" % info)
return [WifiNetwork(**x) for x in info["ap_list"]]
@@ -679,7 +676,7 @@ class IotDevice(Device):
payload = {"ssid": ssid, "password": password, "key_type": int(keytype)}
try:
return await _join("netif", payload)
except SmartDeviceException as ex:
except KasaException as ex:
_LOGGER.debug(
"Unable to join using 'netif', retrying with 'softaponboarding': %s", ex
)

View File

@@ -5,7 +5,7 @@ from typing import Any, Dict, Optional
from ..device_type import DeviceType
from ..deviceconfig import DeviceConfig
from ..protocol import BaseProtocol
from .iotdevice import SmartDeviceException, requires_update
from .iotdevice import KasaException, requires_update
from .iotplug import IotPlug
from .modules import AmbientLight, Motion
@@ -46,7 +46,7 @@ class IotDimmer(IotPlug):
which will not change the cached values,
but you must await :func:`update()` separately.
Errors reported by the device are raised as :class:`SmartDeviceException`\s,
Errors reported by the device are raised as :class:`KasaException`\s,
and should be handled by the user of the library.
Examples:
@@ -88,7 +88,7 @@ class IotDimmer(IotPlug):
Will return a range between 0 - 100.
"""
if not self.is_dimmable:
raise SmartDeviceException("Device is not dimmable.")
raise KasaException("Device is not dimmable.")
sys_info = self.sys_info
return int(sys_info["brightness"])
@@ -103,7 +103,7 @@ class IotDimmer(IotPlug):
Using a transition will cause the dimmer to turn on.
"""
if not self.is_dimmable:
raise SmartDeviceException("Device is not dimmable.")
raise KasaException("Device is not dimmable.")
if not isinstance(brightness, int):
raise ValueError(

View File

@@ -6,7 +6,7 @@ from ..deviceconfig import DeviceConfig
from ..effects import EFFECT_MAPPING_V1, EFFECT_NAMES_V1
from ..protocol import BaseProtocol
from .iotbulb import IotBulb
from .iotdevice import SmartDeviceException, requires_update
from .iotdevice import KasaException, requires_update
class IotLightStrip(IotBulb):
@@ -117,7 +117,7 @@ class IotLightStrip(IotBulb):
:param int transition: The wanted transition time
"""
if effect not in EFFECT_MAPPING_V1:
raise SmartDeviceException(f"The effect {effect} is not a built in effect.")
raise KasaException(f"The effect {effect} is not a built in effect.")
effect_dict = EFFECT_MAPPING_V1[effect]
if brightness is not None:
effect_dict["brightness"] = brightness
@@ -136,7 +136,7 @@ class IotLightStrip(IotBulb):
:param str effect_dict: The custom effect dict to set
"""
if not self.has_effects:
raise SmartDeviceException("Bulb does not support effects.")
raise KasaException("Bulb does not support effects.")
await self._query_helper(
"smartlife.iot.lighting_effect",
"set_lighting_effect",

View File

@@ -2,7 +2,7 @@
import collections
import logging
from ..exceptions import SmartDeviceException
from ..exceptions import KasaException
from ..module import Module
_LOGGER = logging.getLogger(__name__)
@@ -43,7 +43,7 @@ class IotModule(Module):
def data(self):
"""Return the module specific raw data from the last update."""
if self._module not in self._device._last_update:
raise SmartDeviceException(
raise KasaException(
f"You need to call update() prior accessing module data"
f" for '{self._module}'"
)

View File

@@ -22,7 +22,7 @@ class IotPlug(IotDevice):
which will not change the cached values,
but you must await :func:`update()` separately.
Errors reported by the device are raised as :class:`SmartDeviceException`\s,
Errors reported by the device are raised as :class:`KasaException`\s,
and should be handled by the user of the library.
Examples:

View File

@@ -6,7 +6,7 @@ from typing import Any, DefaultDict, Dict, Optional
from ..device_type import DeviceType
from ..deviceconfig import DeviceConfig
from ..exceptions import SmartDeviceException
from ..exceptions import KasaException
from ..protocol import BaseProtocol
from .iotdevice import (
EmeterStatus,
@@ -43,7 +43,7 @@ class IotStrip(IotDevice):
which will not change the cached values,
but you must await :func:`update()` separately.
Errors reported by the device are raised as :class:`SmartDeviceException`\s,
Errors reported by the device are raised as :class:`KasaException`\s,
and should be handled by the user of the library.
Examples:
@@ -375,4 +375,4 @@ class IotStripPlug(IotPlug):
if plug["id"] == self.child_id:
return plug
raise SmartDeviceException(f"Unable to find children {self.child_id}")
raise KasaException(f"Unable to find children {self.child_id}")

View File

@@ -2,7 +2,7 @@
from enum import Enum
from typing import Optional
from ...exceptions import SmartDeviceException
from ...exceptions import KasaException
from ..iotmodule import IotModule
@@ -54,9 +54,7 @@ class Motion(IotModule):
elif range is not None:
payload = {"index": range.value}
else:
raise SmartDeviceException(
"Either range or custom_range need to be defined"
)
raise KasaException("Either range or custom_range need to be defined")
return await self.call("set_trigger_sens", payload)

View File

@@ -1,7 +1,7 @@
"""Provides the current time and timezone information."""
from datetime import datetime
from ...exceptions import SmartDeviceException
from ...exceptions import KasaException
from ..iotmodule import IotModule, merge
@@ -46,7 +46,7 @@ class Time(IotModule):
res["min"],
res["sec"],
)
except SmartDeviceException:
except KasaException:
return None
async def get_timezone(self):