From f259a8f16218a46785f4d1fa3469826668438ef6 Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Sat, 11 May 2024 19:28:18 +0100 Subject: [PATCH] Make module names consistent and remove redundant module casting (#909) Address the inconsistent naming of smart modules by removing all "Module" suffixes and aligning filenames with class names. Removes the casting of modules to the correct module type now that is is redundant. Update the adding of iot modules to use the ModuleName class rather than a free string. --- kasa/iot/iotbulb.py | 19 +++-- kasa/iot/iotdevice.py | 28 ++++---- kasa/iot/iotdimmer.py | 5 +- kasa/iot/iotlightstrip.py | 4 +- kasa/iot/iotplug.py | 14 ++-- kasa/iot/iotstrip.py | 11 +-- kasa/iot/modules/__init__.py | 6 +- kasa/iot/modules/{ledmodule.py => led.py} | 4 +- .../{lighteffectmodule.py => lighteffect.py} | 4 +- kasa/module.py | 50 ++++++------- kasa/smart/modules/__init__.py | 66 ++++++++--------- .../modules/{alarmmodule.py => alarm.py} | 2 +- .../modules/{autooffmodule.py => autooff.py} | 2 +- .../modules/{battery.py => batterysensor.py} | 0 .../{childdevicemodule.py => childdevice.py} | 2 +- .../modules/{cloudmodule.py => cloud.py} | 2 +- .../modules/{colormodule.py => color.py} | 2 +- .../{colortemp.py => colortemperature.py} | 2 +- .../modules/{contact.py => contactsensor.py} | 0 .../modules/{energymodule.py => energy.py} | 2 +- kasa/smart/modules/{fanmodule.py => fan.py} | 2 +- kasa/smart/modules/frostprotection.py | 2 +- .../{humidity.py => humiditysensor.py} | 0 kasa/smart/modules/{ledmodule.py => led.py} | 4 +- .../{lighteffectmodule.py => lighteffect.py} | 4 +- ...transitionmodule.py => lighttransition.py} | 2 +- .../{reportmodule.py => reportmode.py} | 2 +- .../{temperature.py => temperaturesensor.py} | 0 kasa/smart/modules/{timemodule.py => time.py} | 2 +- .../{waterleak.py => waterleaksensor.py} | 0 kasa/smart/smartdevice.py | 72 ++++++++----------- kasa/tests/smart/modules/test_light_effect.py | 6 +- kasa/tests/test_cli.py | 2 +- kasa/tests/test_smartdevice.py | 10 +-- 34 files changed, 162 insertions(+), 171 deletions(-) rename kasa/iot/modules/{ledmodule.py => led.py} (89%) rename kasa/iot/modules/{lighteffectmodule.py => lighteffect.py} (95%) rename kasa/smart/modules/{alarmmodule.py => alarm.py} (99%) rename kasa/smart/modules/{autooffmodule.py => autooff.py} (98%) rename kasa/smart/modules/{battery.py => batterysensor.py} (100%) rename kasa/smart/modules/{childdevicemodule.py => childdevice.py} (84%) rename kasa/smart/modules/{cloudmodule.py => cloud.py} (97%) rename kasa/smart/modules/{colormodule.py => color.py} (98%) rename kasa/smart/modules/{colortemp.py => colortemperature.py} (98%) rename kasa/smart/modules/{contact.py => contactsensor.py} (100%) rename kasa/smart/modules/{energymodule.py => energy.py} (98%) rename kasa/smart/modules/{fanmodule.py => fan.py} (98%) rename kasa/smart/modules/{humidity.py => humiditysensor.py} (100%) rename kasa/smart/modules/{ledmodule.py => led.py} (93%) rename kasa/smart/modules/{lighteffectmodule.py => lighteffect.py} (96%) rename kasa/smart/modules/{lighttransitionmodule.py => lighttransition.py} (99%) rename kasa/smart/modules/{reportmodule.py => reportmode.py} (96%) rename kasa/smart/modules/{temperature.py => temperaturesensor.py} (100%) rename kasa/smart/modules/{timemodule.py => time.py} (98%) rename kasa/smart/modules/{waterleak.py => waterleaksensor.py} (100%) diff --git a/kasa/iot/iotbulb.py b/kasa/iot/iotbulb.py index 6819d94b..92bf9814 100644 --- a/kasa/iot/iotbulb.py +++ b/kasa/iot/iotbulb.py @@ -13,6 +13,7 @@ from ..bulb import HSV, Bulb, BulbPreset, ColorTempRange from ..device_type import DeviceType from ..deviceconfig import DeviceConfig from ..feature import Feature +from ..module import Module from ..protocol import BaseProtocol from .iotdevice import IotDevice, KasaException, requires_update from .modules import Antitheft, Cloud, Countdown, Emeter, Schedule, Time, Usage @@ -198,13 +199,17 @@ class IotBulb(IotDevice, Bulb): ) -> None: super().__init__(host=host, config=config, protocol=protocol) self._device_type = DeviceType.Bulb - self.add_module("schedule", Schedule(self, "smartlife.iot.common.schedule")) - self.add_module("usage", Usage(self, "smartlife.iot.common.schedule")) - self.add_module("antitheft", Antitheft(self, "smartlife.iot.common.anti_theft")) - self.add_module("time", Time(self, "smartlife.iot.common.timesetting")) - self.add_module("emeter", Emeter(self, self.emeter_type)) - self.add_module("countdown", Countdown(self, "countdown")) - self.add_module("cloud", Cloud(self, "smartlife.iot.common.cloud")) + self.add_module( + Module.IotSchedule, Schedule(self, "smartlife.iot.common.schedule") + ) + self.add_module(Module.IotUsage, Usage(self, "smartlife.iot.common.schedule")) + self.add_module( + Module.IotAntitheft, Antitheft(self, "smartlife.iot.common.anti_theft") + ) + self.add_module(Module.IotTime, Time(self, "smartlife.iot.common.timesetting")) + self.add_module(Module.IotEmeter, Emeter(self, self.emeter_type)) + self.add_module(Module.IotCountdown, Countdown(self, "countdown")) + self.add_module(Module.IotCloud, Cloud(self, "smartlife.iot.common.cloud")) async def _initialize_features(self): await super()._initialize_features() diff --git a/kasa/iot/iotdevice.py b/kasa/iot/iotdevice.py index 762fc06c..e4c1bb13 100755 --- a/kasa/iot/iotdevice.py +++ b/kasa/iot/iotdevice.py @@ -30,7 +30,7 @@ from ..module import Module from ..modulemapping import ModuleMapping, ModuleName from ..protocol import BaseProtocol from .iotmodule import IotModule -from .modules import Emeter, Time +from .modules import Emeter _LOGGER = logging.getLogger(__name__) @@ -347,7 +347,7 @@ class IotDevice(Device): _LOGGER.debug( "The device has emeter, querying its information along sysinfo" ) - self.add_module("emeter", Emeter(self, self.emeter_type)) + self.add_module(Module.IotEmeter, Emeter(self, self.emeter_type)) # TODO: perhaps modules should not have unsupported modules, # making separate handling for this unnecessary @@ -440,27 +440,27 @@ class IotDevice(Device): @requires_update def time(self) -> datetime: """Return current time from the device.""" - return cast(Time, self.modules["time"]).time + return self.modules[Module.IotTime].time @property @requires_update def timezone(self) -> dict: """Return the current timezone.""" - return cast(Time, self.modules["time"]).timezone + return self.modules[Module.IotTime].timezone async def get_time(self) -> datetime | None: """Return current time from the device, if available.""" _LOGGER.warning( "Use `time` property instead, this call will be removed in the future." ) - return await cast(Time, self.modules["time"]).get_time() + return await self.modules[Module.IotTime].get_time() async def get_timezone(self) -> dict: """Return timezone information.""" _LOGGER.warning( "Use `timezone` property instead, this call will be removed in the future." ) - return await cast(Time, self.modules["time"]).get_timezone() + return await self.modules[Module.IotTime].get_timezone() @property # type: ignore @requires_update @@ -541,26 +541,26 @@ class IotDevice(Device): def emeter_realtime(self) -> EmeterStatus: """Return current energy readings.""" self._verify_emeter() - return EmeterStatus(cast(Emeter, self.modules["emeter"]).realtime) + return EmeterStatus(self.modules[Module.IotEmeter].realtime) async def get_emeter_realtime(self) -> EmeterStatus: """Retrieve current energy readings.""" self._verify_emeter() - return EmeterStatus(await cast(Emeter, self.modules["emeter"]).get_realtime()) + return EmeterStatus(await self.modules[Module.IotEmeter].get_realtime()) @property @requires_update def emeter_today(self) -> float | None: """Return today's energy consumption in kWh.""" self._verify_emeter() - return cast(Emeter, self.modules["emeter"]).emeter_today + return self.modules[Module.IotEmeter].emeter_today @property @requires_update def emeter_this_month(self) -> float | None: """Return this month's energy consumption in kWh.""" self._verify_emeter() - return cast(Emeter, self.modules["emeter"]).emeter_this_month + return self.modules[Module.IotEmeter].emeter_this_month async def get_emeter_daily( self, year: int | None = None, month: int | None = None, kwh: bool = True @@ -574,7 +574,7 @@ class IotDevice(Device): :return: mapping of day of month to value """ self._verify_emeter() - return await cast(Emeter, self.modules["emeter"]).get_daystat( + return await self.modules[Module.IotEmeter].get_daystat( year=year, month=month, kwh=kwh ) @@ -589,15 +589,13 @@ class IotDevice(Device): :return: dict: mapping of month to value """ self._verify_emeter() - return await cast(Emeter, self.modules["emeter"]).get_monthstat( - year=year, kwh=kwh - ) + return await self.modules[Module.IotEmeter].get_monthstat(year=year, kwh=kwh) @requires_update async def erase_emeter_stats(self) -> dict: """Erase energy meter statistics.""" self._verify_emeter() - return await cast(Emeter, self.modules["emeter"]).erase_stats() + return await self.modules[Module.IotEmeter].erase_stats() @requires_update async def current_consumption(self) -> float: diff --git a/kasa/iot/iotdimmer.py b/kasa/iot/iotdimmer.py index cfe937b8..fed9e7e7 100644 --- a/kasa/iot/iotdimmer.py +++ b/kasa/iot/iotdimmer.py @@ -8,6 +8,7 @@ from typing import Any from ..device_type import DeviceType from ..deviceconfig import DeviceConfig from ..feature import Feature +from ..module import Module from ..protocol import BaseProtocol from .iotdevice import KasaException, requires_update from .iotplug import IotPlug @@ -81,8 +82,8 @@ class IotDimmer(IotPlug): self._device_type = DeviceType.Dimmer # TODO: need to be verified if it's okay to call these on HS220 w/o these # TODO: need to be figured out what's the best approach to detect support - self.add_module("motion", Motion(self, "smartlife.iot.PIR")) - self.add_module("ambient", AmbientLight(self, "smartlife.iot.LAS")) + self.add_module(Module.IotMotion, Motion(self, "smartlife.iot.PIR")) + self.add_module(Module.IotAmbientLight, AmbientLight(self, "smartlife.iot.LAS")) async def _initialize_features(self): await super()._initialize_features() diff --git a/kasa/iot/iotlightstrip.py b/kasa/iot/iotlightstrip.py index a120be7a..7cdbe43b 100644 --- a/kasa/iot/iotlightstrip.py +++ b/kasa/iot/iotlightstrip.py @@ -9,7 +9,7 @@ from ..protocol import BaseProtocol from .effects import EFFECT_NAMES_V1 from .iotbulb import IotBulb from .iotdevice import KasaException, requires_update -from .modules.lighteffectmodule import LightEffectModule +from .modules.lighteffect import LightEffect class IotLightStrip(IotBulb): @@ -58,7 +58,7 @@ class IotLightStrip(IotBulb): self._device_type = DeviceType.LightStrip self.add_module( Module.LightEffect, - LightEffectModule(self, "smartlife.iot.lighting_effect"), + LightEffect(self, "smartlife.iot.lighting_effect"), ) @property # type: ignore diff --git a/kasa/iot/iotplug.py b/kasa/iot/iotplug.py index 22238c7a..6aace4f8 100644 --- a/kasa/iot/iotplug.py +++ b/kasa/iot/iotplug.py @@ -9,7 +9,7 @@ from ..deviceconfig import DeviceConfig from ..module import Module from ..protocol import BaseProtocol from .iotdevice import IotDevice, requires_update -from .modules import Antitheft, Cloud, LedModule, Schedule, Time, Usage +from .modules import Antitheft, Cloud, Led, Schedule, Time, Usage _LOGGER = logging.getLogger(__name__) @@ -53,12 +53,12 @@ class IotPlug(IotDevice): ) -> None: super().__init__(host=host, config=config, protocol=protocol) self._device_type = DeviceType.Plug - self.add_module("schedule", Schedule(self, "schedule")) - self.add_module("usage", Usage(self, "schedule")) - self.add_module("antitheft", Antitheft(self, "anti_theft")) - self.add_module("time", Time(self, "time")) - self.add_module("cloud", Cloud(self, "cnCloud")) - self.add_module(Module.Led, LedModule(self, "system")) + self.add_module(Module.IotSchedule, Schedule(self, "schedule")) + self.add_module(Module.IotUsage, Usage(self, "schedule")) + self.add_module(Module.IotAntitheft, Antitheft(self, "anti_theft")) + self.add_module(Module.IotTime, Time(self, "time")) + self.add_module(Module.IotCloud, Cloud(self, "cnCloud")) + self.add_module(Module.Led, Led(self, "system")) @property # type: ignore @requires_update diff --git a/kasa/iot/iotstrip.py b/kasa/iot/iotstrip.py index ab14abb0..4aa966e1 100755 --- a/kasa/iot/iotstrip.py +++ b/kasa/iot/iotstrip.py @@ -10,6 +10,7 @@ from typing import Any from ..device_type import DeviceType from ..deviceconfig import DeviceConfig from ..exceptions import KasaException +from ..module import Module from ..protocol import BaseProtocol from .iotdevice import ( EmeterStatus, @@ -95,11 +96,11 @@ class IotStrip(IotDevice): super().__init__(host=host, config=config, protocol=protocol) self.emeter_type = "emeter" self._device_type = DeviceType.Strip - self.add_module("antitheft", Antitheft(self, "anti_theft")) - self.add_module("schedule", Schedule(self, "schedule")) - self.add_module("usage", Usage(self, "schedule")) - self.add_module("time", Time(self, "time")) - self.add_module("countdown", Countdown(self, "countdown")) + self.add_module(Module.IotAntitheft, Antitheft(self, "anti_theft")) + self.add_module(Module.IotSchedule, Schedule(self, "schedule")) + self.add_module(Module.IotUsage, Usage(self, "schedule")) + self.add_module(Module.IotTime, Time(self, "time")) + self.add_module(Module.IotCountdown, Countdown(self, "countdown")) @property # type: ignore @requires_update diff --git a/kasa/iot/modules/__init__.py b/kasa/iot/modules/__init__.py index f061e607..e0febfd4 100644 --- a/kasa/iot/modules/__init__.py +++ b/kasa/iot/modules/__init__.py @@ -5,7 +5,8 @@ from .antitheft import Antitheft from .cloud import Cloud from .countdown import Countdown from .emeter import Emeter -from .ledmodule import LedModule +from .led import Led +from .lighteffect import LightEffect from .motion import Motion from .rulemodule import Rule, RuleModule from .schedule import Schedule @@ -18,7 +19,8 @@ __all__ = [ "Cloud", "Countdown", "Emeter", - "LedModule", + "Led", + "LightEffect", "Motion", "Rule", "RuleModule", diff --git a/kasa/iot/modules/ledmodule.py b/kasa/iot/modules/led.py similarity index 89% rename from kasa/iot/modules/ledmodule.py rename to kasa/iot/modules/led.py index 6b3c6194..6c4ca02a 100644 --- a/kasa/iot/modules/ledmodule.py +++ b/kasa/iot/modules/led.py @@ -2,11 +2,11 @@ from __future__ import annotations -from ...interfaces.led import Led +from ...interfaces.led import Led as LedInterface from ..iotmodule import IotModule -class LedModule(IotModule, Led): +class Led(IotModule, LedInterface): """Implementation of led controls.""" def query(self) -> dict: diff --git a/kasa/iot/modules/lighteffectmodule.py b/kasa/iot/modules/lighteffect.py similarity index 95% rename from kasa/iot/modules/lighteffectmodule.py rename to kasa/iot/modules/lighteffect.py index c53de192..2d40fb54 100644 --- a/kasa/iot/modules/lighteffectmodule.py +++ b/kasa/iot/modules/lighteffect.py @@ -2,12 +2,12 @@ from __future__ import annotations -from ...interfaces.lighteffect import LightEffect +from ...interfaces.lighteffect import LightEffect as LightEffectInterface from ..effects import EFFECT_MAPPING_V1, EFFECT_NAMES_V1 from ..iotmodule import IotModule -class LightEffectModule(IotModule, LightEffect): +class LightEffect(IotModule, LightEffectInterface): """Implementation of dynamic light effects.""" @property diff --git a/kasa/module.py b/kasa/module.py index b65f0499..55eeea18 100644 --- a/kasa/module.py +++ b/kasa/module.py @@ -15,7 +15,7 @@ from .feature import Feature from .modulemapping import ModuleName if TYPE_CHECKING: - from .device import Device as DeviceType # avoid name clash with Device module + from .device import Device from .interfaces.led import Led from .interfaces.lighteffect import LightEffect from .iot import modules as iot @@ -34,8 +34,8 @@ class Module(ABC): """ # Common Modules - LightEffect: Final[ModuleName[LightEffect]] = ModuleName("LightEffectModule") - Led: Final[ModuleName[Led]] = ModuleName("LedModule") + LightEffect: Final[ModuleName[LightEffect]] = ModuleName("LightEffect") + Led: Final[ModuleName[Led]] = ModuleName("Led") # IOT only Modules IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = ModuleName("ambient") @@ -49,43 +49,43 @@ class Module(ABC): IotTime: Final[ModuleName[iot.Time]] = ModuleName("time") # SMART only Modules - Alarm: Final[ModuleName[smart.AlarmModule]] = ModuleName("AlarmModule") - AutoOff: Final[ModuleName[smart.AutoOffModule]] = ModuleName("AutoOffModule") + Alarm: Final[ModuleName[smart.Alarm]] = ModuleName("Alarm") + AutoOff: Final[ModuleName[smart.AutoOff]] = ModuleName("AutoOff") BatterySensor: Final[ModuleName[smart.BatterySensor]] = ModuleName("BatterySensor") Brightness: Final[ModuleName[smart.Brightness]] = ModuleName("Brightness") - ChildDevice: Final[ModuleName[smart.ChildDeviceModule]] = ModuleName( - "ChildDeviceModule" - ) - Cloud: Final[ModuleName[smart.CloudModule]] = ModuleName("CloudModule") - Color: Final[ModuleName[smart.ColorModule]] = ModuleName("ColorModule") - ColorTemp: Final[ModuleName[smart.ColorTemperatureModule]] = ModuleName( - "ColorTemperatureModule" + ChildDevice: Final[ModuleName[smart.ChildDevice]] = ModuleName("ChildDevice") + Cloud: Final[ModuleName[smart.Cloud]] = ModuleName("Cloud") + Color: Final[ModuleName[smart.Color]] = ModuleName("Color") + ColorTemperature: Final[ModuleName[smart.ColorTemperature]] = ModuleName( + "ColorTemperature" ) ContactSensor: Final[ModuleName[smart.ContactSensor]] = ModuleName("ContactSensor") - Device: Final[ModuleName[smart.DeviceModule]] = ModuleName("DeviceModule") - Energy: Final[ModuleName[smart.EnergyModule]] = ModuleName("EnergyModule") - Fan: Final[ModuleName[smart.FanModule]] = ModuleName("FanModule") + DeviceModule: Final[ModuleName[smart.DeviceModule]] = ModuleName("DeviceModule") + Energy: Final[ModuleName[smart.Energy]] = ModuleName("Energy") + Fan: Final[ModuleName[smart.Fan]] = ModuleName("Fan") Firmware: Final[ModuleName[smart.Firmware]] = ModuleName("Firmware") - FrostProtection: Final[ModuleName[smart.FrostProtectionModule]] = ModuleName( - "FrostProtectionModule" + FrostProtection: Final[ModuleName[smart.FrostProtection]] = ModuleName( + "FrostProtection" ) - Humidity: Final[ModuleName[smart.HumiditySensor]] = ModuleName("HumiditySensor") - LightTransition: Final[ModuleName[smart.LightTransitionModule]] = ModuleName( - "LightTransitionModule" + HumiditySensor: Final[ModuleName[smart.HumiditySensor]] = ModuleName( + "HumiditySensor" ) - Report: Final[ModuleName[smart.ReportModule]] = ModuleName("ReportModule") - Temperature: Final[ModuleName[smart.TemperatureSensor]] = ModuleName( + LightTransition: Final[ModuleName[smart.LightTransition]] = ModuleName( + "LightTransition" + ) + ReportMode: Final[ModuleName[smart.ReportMode]] = ModuleName("ReportMode") + TemperatureSensor: Final[ModuleName[smart.TemperatureSensor]] = ModuleName( "TemperatureSensor" ) - TemperatureSensor: Final[ModuleName[smart.TemperatureControl]] = ModuleName( + TemperatureControl: Final[ModuleName[smart.TemperatureControl]] = ModuleName( "TemperatureControl" ) - Time: Final[ModuleName[smart.TimeModule]] = ModuleName("TimeModule") + Time: Final[ModuleName[smart.Time]] = ModuleName("Time") WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = ModuleName( "WaterleakSensor" ) - def __init__(self, device: DeviceType, module: str): + def __init__(self, device: Device, module: str): self._device = device self._module = module self._module_features: dict[str, Feature] = {} diff --git a/kasa/smart/modules/__init__.py b/kasa/smart/modules/__init__.py index b0956b80..e119e067 100644 --- a/kasa/smart/modules/__init__.py +++ b/kasa/smart/modules/__init__.py @@ -1,51 +1,51 @@ """Modules for SMART devices.""" -from .alarmmodule import AlarmModule -from .autooffmodule import AutoOffModule -from .battery import BatterySensor +from .alarm import Alarm +from .autooff import AutoOff +from .batterysensor import BatterySensor from .brightness import Brightness -from .childdevicemodule import ChildDeviceModule -from .cloudmodule import CloudModule -from .colormodule import ColorModule -from .colortemp import ColorTemperatureModule -from .contact import ContactSensor +from .childdevice import ChildDevice +from .cloud import Cloud +from .color import Color +from .colortemperature import ColorTemperature +from .contactsensor import ContactSensor from .devicemodule import DeviceModule -from .energymodule import EnergyModule -from .fanmodule import FanModule +from .energy import Energy +from .fan import Fan from .firmware import Firmware -from .frostprotection import FrostProtectionModule -from .humidity import HumiditySensor -from .ledmodule import LedModule -from .lighteffectmodule import LightEffectModule -from .lighttransitionmodule import LightTransitionModule -from .reportmodule import ReportModule -from .temperature import TemperatureSensor +from .frostprotection import FrostProtection +from .humiditysensor import HumiditySensor +from .led import Led +from .lighteffect import LightEffect +from .lighttransition import LightTransition +from .reportmode import ReportMode from .temperaturecontrol import TemperatureControl -from .timemodule import TimeModule -from .waterleak import WaterleakSensor +from .temperaturesensor import TemperatureSensor +from .time import Time +from .waterleaksensor import WaterleakSensor __all__ = [ - "AlarmModule", - "TimeModule", - "EnergyModule", + "Alarm", + "Time", + "Energy", "DeviceModule", - "ChildDeviceModule", + "ChildDevice", "BatterySensor", "HumiditySensor", "TemperatureSensor", "TemperatureControl", - "ReportModule", - "AutoOffModule", - "LedModule", + "ReportMode", + "AutoOff", + "Led", "Brightness", - "FanModule", + "Fan", "Firmware", - "CloudModule", - "LightEffectModule", - "LightTransitionModule", - "ColorTemperatureModule", - "ColorModule", + "Cloud", + "LightEffect", + "LightTransition", + "ColorTemperature", + "Color", "WaterleakSensor", "ContactSensor", - "FrostProtectionModule", + "FrostProtection", ] diff --git a/kasa/smart/modules/alarmmodule.py b/kasa/smart/modules/alarm.py similarity index 99% rename from kasa/smart/modules/alarmmodule.py rename to kasa/smart/modules/alarm.py index 845eb65a..f033496a 100644 --- a/kasa/smart/modules/alarmmodule.py +++ b/kasa/smart/modules/alarm.py @@ -6,7 +6,7 @@ from ...feature import Feature from ..smartmodule import SmartModule -class AlarmModule(SmartModule): +class Alarm(SmartModule): """Implementation of alarm module.""" REQUIRED_COMPONENT = "alarm" diff --git a/kasa/smart/modules/autooffmodule.py b/kasa/smart/modules/autooff.py similarity index 98% rename from kasa/smart/modules/autooffmodule.py rename to kasa/smart/modules/autooff.py index cb8d5e57..385364fa 100644 --- a/kasa/smart/modules/autooffmodule.py +++ b/kasa/smart/modules/autooff.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class AutoOffModule(SmartModule): +class AutoOff(SmartModule): """Implementation of auto off module.""" REQUIRED_COMPONENT = "auto_off" diff --git a/kasa/smart/modules/battery.py b/kasa/smart/modules/batterysensor.py similarity index 100% rename from kasa/smart/modules/battery.py rename to kasa/smart/modules/batterysensor.py diff --git a/kasa/smart/modules/childdevicemodule.py b/kasa/smart/modules/childdevice.py similarity index 84% rename from kasa/smart/modules/childdevicemodule.py rename to kasa/smart/modules/childdevice.py index 9f4710b2..5713eff4 100644 --- a/kasa/smart/modules/childdevicemodule.py +++ b/kasa/smart/modules/childdevice.py @@ -3,7 +3,7 @@ from ..smartmodule import SmartModule -class ChildDeviceModule(SmartModule): +class ChildDevice(SmartModule): """Implementation for child devices.""" REQUIRED_COMPONENT = "child_device" diff --git a/kasa/smart/modules/cloudmodule.py b/kasa/smart/modules/cloud.py similarity index 97% rename from kasa/smart/modules/cloudmodule.py rename to kasa/smart/modules/cloud.py index 8b9d8f41..1b64f090 100644 --- a/kasa/smart/modules/cloudmodule.py +++ b/kasa/smart/modules/cloud.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class CloudModule(SmartModule): +class Cloud(SmartModule): """Implementation of cloud module.""" QUERY_GETTER_NAME = "get_connect_cloud_state" diff --git a/kasa/smart/modules/colormodule.py b/kasa/smart/modules/color.py similarity index 98% rename from kasa/smart/modules/colormodule.py rename to kasa/smart/modules/color.py index 716d4c44..979d4fec 100644 --- a/kasa/smart/modules/colormodule.py +++ b/kasa/smart/modules/color.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class ColorModule(SmartModule): +class Color(SmartModule): """Implementation of color module.""" REQUIRED_COMPONENT = "color" diff --git a/kasa/smart/modules/colortemp.py b/kasa/smart/modules/colortemperature.py similarity index 98% rename from kasa/smart/modules/colortemp.py rename to kasa/smart/modules/colortemperature.py index d6b43d02..88d5ea21 100644 --- a/kasa/smart/modules/colortemp.py +++ b/kasa/smart/modules/colortemperature.py @@ -18,7 +18,7 @@ _LOGGER = logging.getLogger(__name__) DEFAULT_TEMP_RANGE = [2500, 6500] -class ColorTemperatureModule(SmartModule): +class ColorTemperature(SmartModule): """Implementation of color temp module.""" REQUIRED_COMPONENT = "color_temperature" diff --git a/kasa/smart/modules/contact.py b/kasa/smart/modules/contactsensor.py similarity index 100% rename from kasa/smart/modules/contact.py rename to kasa/smart/modules/contactsensor.py diff --git a/kasa/smart/modules/energymodule.py b/kasa/smart/modules/energy.py similarity index 98% rename from kasa/smart/modules/energymodule.py rename to kasa/smart/modules/energy.py index 9cfe8cfb..55b5088e 100644 --- a/kasa/smart/modules/energymodule.py +++ b/kasa/smart/modules/energy.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class EnergyModule(SmartModule): +class Energy(SmartModule): """Implementation of energy monitoring module.""" REQUIRED_COMPONENT = "energy_monitoring" diff --git a/kasa/smart/modules/fanmodule.py b/kasa/smart/modules/fan.py similarity index 98% rename from kasa/smart/modules/fanmodule.py rename to kasa/smart/modules/fan.py index 6eeaa4d4..3d8cc7eb 100644 --- a/kasa/smart/modules/fanmodule.py +++ b/kasa/smart/modules/fan.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class FanModule(SmartModule): +class Fan(SmartModule): """Implementation of fan_control module.""" REQUIRED_COMPONENT = "fan_control" diff --git a/kasa/smart/modules/frostprotection.py b/kasa/smart/modules/frostprotection.py index cedaf78b..ee93d299 100644 --- a/kasa/smart/modules/frostprotection.py +++ b/kasa/smart/modules/frostprotection.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class FrostProtectionModule(SmartModule): +class FrostProtection(SmartModule): """Implementation for frost protection module. This basically turns the thermostat on and off. diff --git a/kasa/smart/modules/humidity.py b/kasa/smart/modules/humiditysensor.py similarity index 100% rename from kasa/smart/modules/humidity.py rename to kasa/smart/modules/humiditysensor.py diff --git a/kasa/smart/modules/ledmodule.py b/kasa/smart/modules/led.py similarity index 93% rename from kasa/smart/modules/ledmodule.py rename to kasa/smart/modules/led.py index 587be51c..230b83d9 100644 --- a/kasa/smart/modules/ledmodule.py +++ b/kasa/smart/modules/led.py @@ -2,11 +2,11 @@ from __future__ import annotations -from ...interfaces.led import Led +from ...interfaces.led import Led as LedInterface from ..smartmodule import SmartModule -class LedModule(SmartModule, Led): +class Led(SmartModule, LedInterface): """Implementation of led controls.""" REQUIRED_COMPONENT = "led" diff --git a/kasa/smart/modules/lighteffectmodule.py b/kasa/smart/modules/lighteffect.py similarity index 96% rename from kasa/smart/modules/lighteffectmodule.py rename to kasa/smart/modules/lighteffect.py index a06e979a..4f049576 100644 --- a/kasa/smart/modules/lighteffectmodule.py +++ b/kasa/smart/modules/lighteffect.py @@ -6,14 +6,14 @@ import base64 import copy from typing import TYPE_CHECKING, Any -from ...interfaces.lighteffect import LightEffect +from ...interfaces.lighteffect import LightEffect as LightEffectInterface from ..smartmodule import SmartModule if TYPE_CHECKING: from ..smartdevice import SmartDevice -class LightEffectModule(SmartModule, LightEffect): +class LightEffect(SmartModule, LightEffectInterface): """Implementation of dynamic light effects.""" REQUIRED_COMPONENT = "light_effect" diff --git a/kasa/smart/modules/lighttransitionmodule.py b/kasa/smart/modules/lighttransition.py similarity index 99% rename from kasa/smart/modules/lighttransitionmodule.py rename to kasa/smart/modules/lighttransition.py index f213d9ac..a11c7d95 100644 --- a/kasa/smart/modules/lighttransitionmodule.py +++ b/kasa/smart/modules/lighttransition.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class LightTransitionModule(SmartModule): +class LightTransition(SmartModule): """Implementation of gradual on/off.""" REQUIRED_COMPONENT = "on_off_gradually" diff --git a/kasa/smart/modules/reportmodule.py b/kasa/smart/modules/reportmode.py similarity index 96% rename from kasa/smart/modules/reportmodule.py rename to kasa/smart/modules/reportmode.py index 16827a8c..f0af4c1c 100644 --- a/kasa/smart/modules/reportmodule.py +++ b/kasa/smart/modules/reportmode.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class ReportModule(SmartModule): +class ReportMode(SmartModule): """Implementation of report module.""" REQUIRED_COMPONENT = "report_mode" diff --git a/kasa/smart/modules/temperature.py b/kasa/smart/modules/temperaturesensor.py similarity index 100% rename from kasa/smart/modules/temperature.py rename to kasa/smart/modules/temperaturesensor.py diff --git a/kasa/smart/modules/timemodule.py b/kasa/smart/modules/time.py similarity index 98% rename from kasa/smart/modules/timemodule.py rename to kasa/smart/modules/time.py index 23814f57..958cf9e2 100644 --- a/kasa/smart/modules/timemodule.py +++ b/kasa/smart/modules/time.py @@ -13,7 +13,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class TimeModule(SmartModule): +class Time(SmartModule): """Implementation of device_local_time.""" REQUIRED_COMPONENT = "time" diff --git a/kasa/smart/modules/waterleak.py b/kasa/smart/modules/waterleaksensor.py similarity index 100% rename from kasa/smart/modules/waterleak.py rename to kasa/smart/modules/waterleaksensor.py diff --git a/kasa/smart/smartdevice.py b/kasa/smart/smartdevice.py index 194e7c17..122c943b 100644 --- a/kasa/smart/smartdevice.py +++ b/kasa/smart/smartdevice.py @@ -20,15 +20,10 @@ from ..module import Module from ..modulemapping import ModuleMapping, ModuleName from ..smartprotocol import SmartProtocol from .modules import ( - Brightness, - CloudModule, - ColorModule, - ColorTemperatureModule, + Cloud, DeviceModule, - EnergyModule, - FanModule, Firmware, - TimeModule, + Time, ) from .smartmodule import SmartModule @@ -39,7 +34,7 @@ _LOGGER = logging.getLogger(__name__) # the child but only work on the parent. See longer note below in _initialize_modules. # This list should be updated when creating new modules that could have the # same issue, homekit perhaps? -WALL_SWITCH_PARENT_ONLY_MODULES = [DeviceModule, TimeModule, Firmware, CloudModule] +WALL_SWITCH_PARENT_ONLY_MODULES = [DeviceModule, Time, Firmware, Cloud] # Device must go last as the other interfaces also inherit Device @@ -329,11 +324,11 @@ class SmartDevice(Bulb, Fan, Device): self._add_feature(feat) @property - def is_cloud_connected(self): + def is_cloud_connected(self) -> bool: """Returns if the device is connected to the cloud.""" - if "CloudModule" not in self.modules: + if Module.Cloud not in self.modules: return False - return self.modules["CloudModule"].is_connected + return self.modules[Module.Cloud].is_connected @property def sys_info(self) -> dict[str, Any]: @@ -357,10 +352,10 @@ class SmartDevice(Bulb, Fan, Device): def time(self) -> datetime: """Return the time.""" # TODO: Default to parent's time module for child devices - if self._parent and "TimeModule" in self.modules: - _timemod = cast(TimeModule, self._parent.modules["TimeModule"]) # noqa: F405 + if self._parent and Module.Time in self.modules: + _timemod = self._parent.modules[Module.Time] else: - _timemod = cast(TimeModule, self.modules["TimeModule"]) # noqa: F405 + _timemod = self.modules[Module.Time] return _timemod.time @@ -437,7 +432,7 @@ class SmartDevice(Bulb, Fan, Device): @property def has_emeter(self) -> bool: """Return if the device has emeter.""" - return "EnergyModule" in self.modules + return Module.Energy in self.modules @property def is_dimmer(self) -> bool: @@ -479,19 +474,19 @@ class SmartDevice(Bulb, Fan, Device): @property def emeter_realtime(self) -> EmeterStatus: """Get the emeter status.""" - energy = cast(EnergyModule, self.modules["EnergyModule"]) + energy = self.modules[Module.Energy] return energy.emeter_realtime @property def emeter_this_month(self) -> float | None: """Get the emeter value for this month.""" - energy = cast(EnergyModule, self.modules["EnergyModule"]) + energy = self.modules[Module.Energy] return energy.emeter_this_month @property def emeter_today(self) -> float | None: """Get the emeter value for today.""" - energy = cast(EnergyModule, self.modules["EnergyModule"]) + energy = self.modules[Module.Energy] return energy.emeter_today @property @@ -503,8 +498,7 @@ class SmartDevice(Bulb, Fan, Device): ): return None on_time = cast(float, on_time) - if (timemod := self.modules.get("TimeModule")) is not None: - timemod = cast(TimeModule, timemod) # noqa: F405 + if (timemod := self.modules.get(Module.Time)) is not None: return timemod.time - timedelta(seconds=on_time) else: # We have no device time, use current local time. return datetime.now().replace(microsecond=0) - timedelta(seconds=on_time) @@ -650,37 +644,37 @@ class SmartDevice(Bulb, Fan, Device): @property def is_fan(self) -> bool: """Return True if the device is a fan.""" - return "FanModule" in self.modules + return Module.Fan in self.modules @property def fan_speed_level(self) -> int: """Return fan speed level.""" if not self.is_fan: raise KasaException("Device is not a Fan") - return cast(FanModule, self.modules["FanModule"]).fan_speed_level + return self.modules[Module.Fan].fan_speed_level async def set_fan_speed_level(self, level: int): """Set fan speed level.""" if not self.is_fan: raise KasaException("Device is not a Fan") - await cast(FanModule, self.modules["FanModule"]).set_fan_speed_level(level) + await self.modules[Module.Fan].set_fan_speed_level(level) # Bulb interface methods @property def is_color(self) -> bool: """Whether the bulb supports color changes.""" - return "ColorModule" in self.modules + return Module.Color in self.modules @property def is_dimmable(self) -> bool: """Whether the bulb supports brightness changes.""" - return "Brightness" in self.modules + return Module.Brightness in self.modules @property def is_variable_color_temp(self) -> bool: """Whether the bulb supports color temperature changes.""" - return "ColorTemperatureModule" in self.modules + return Module.ColorTemperature in self.modules @property def valid_temperature_range(self) -> ColorTempRange: @@ -691,9 +685,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_variable_color_temp: raise KasaException("Color temperature not supported") - return cast( - ColorTemperatureModule, self.modules["ColorTemperatureModule"] - ).valid_temperature_range + return self.modules[Module.ColorTemperature].valid_temperature_range @property def hsv(self) -> HSV: @@ -704,7 +696,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_color: raise KasaException("Bulb does not support color.") - return cast(ColorModule, self.modules["ColorModule"]).hsv + return self.modules[Module.Color].hsv @property def color_temp(self) -> int: @@ -712,9 +704,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_variable_color_temp: raise KasaException("Bulb does not support colortemp.") - return cast( - ColorTemperatureModule, self.modules["ColorTemperatureModule"] - ).color_temp + return self.modules[Module.ColorTemperature].color_temp @property def brightness(self) -> int: @@ -722,7 +712,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_dimmable: # pragma: no cover raise KasaException("Bulb is not dimmable.") - return cast(Brightness, self.modules["Brightness"]).brightness + return self.modules[Module.Brightness].brightness async def set_hsv( self, @@ -744,9 +734,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_color: raise KasaException("Bulb does not support color.") - return await cast(ColorModule, self.modules["ColorModule"]).set_hsv( - hue, saturation, value - ) + return await self.modules[Module.Color].set_hsv(hue, saturation, value) async def set_color_temp( self, temp: int, *, brightness=None, transition: int | None = None @@ -760,9 +748,7 @@ class SmartDevice(Bulb, Fan, Device): """ if not self.is_variable_color_temp: raise KasaException("Bulb does not support colortemp.") - return await cast( - ColorTemperatureModule, self.modules["ColorTemperatureModule"] - ).set_color_temp(temp) + return await self.modules[Module.ColorTemperature].set_color_temp(temp) async def set_brightness( self, brightness: int, *, transition: int | None = None @@ -777,9 +763,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_dimmable: # pragma: no cover raise KasaException("Bulb is not dimmable.") - return await cast(Brightness, self.modules["Brightness"]).set_brightness( - brightness - ) + return await self.modules[Module.Brightness].set_brightness(brightness) @property def presets(self) -> list[BulbPreset]: @@ -789,4 +773,4 @@ class SmartDevice(Bulb, Fan, Device): @property def has_effects(self) -> bool: """Return True if the device supports effects.""" - return "LightEffectModule" in self.modules + return Module.LightEffect in self.modules diff --git a/kasa/tests/smart/modules/test_light_effect.py b/kasa/tests/smart/modules/test_light_effect.py index cc0eee8a..56c3f096 100644 --- a/kasa/tests/smart/modules/test_light_effect.py +++ b/kasa/tests/smart/modules/test_light_effect.py @@ -6,7 +6,7 @@ import pytest from pytest_mock import MockerFixture from kasa import Device, Feature, Module -from kasa.smart.modules import LightEffectModule +from kasa.smart.modules import LightEffect from kasa.tests.device_fixtures import parametrize light_effect = parametrize( @@ -18,7 +18,7 @@ light_effect = parametrize( async def test_light_effect(dev: Device, mocker: MockerFixture): """Test light effect.""" light_effect = dev.modules.get(Module.LightEffect) - assert isinstance(light_effect, LightEffectModule) + assert isinstance(light_effect, LightEffect) feature = light_effect._module_features["light_effect"] assert feature.type == Feature.Type.Choice @@ -28,7 +28,7 @@ async def test_light_effect(dev: Device, mocker: MockerFixture): assert feature.choices for effect in chain(reversed(feature.choices), feature.choices): await light_effect.set_effect(effect) - enable = effect != LightEffectModule.LIGHT_EFFECTS_OFF + enable = effect != LightEffect.LIGHT_EFFECTS_OFF params: dict[str, bool | str] = {"enable": enable} if enable: params["id"] = light_effect._scenes_names_to_id[effect] diff --git a/kasa/tests/test_cli.py b/kasa/tests/test_cli.py index 7addd434..a438aa97 100644 --- a/kasa/tests/test_cli.py +++ b/kasa/tests/test_cli.py @@ -737,7 +737,7 @@ async def test_feature_set(mocker, runner): dummy_device = await get_device_for_fixture_protocol( "P300(EU)_1.0_1.0.13.json", "SMART" ) - led_setter = mocker.patch("kasa.smart.modules.ledmodule.LedModule.set_led") + led_setter = mocker.patch("kasa.smart.modules.led.Led.set_led") mocker.patch("kasa.discover.Discover.discover_single", return_value=dummy_device) res = await runner.invoke( diff --git a/kasa/tests/test_smartdevice.py b/kasa/tests/test_smartdevice.py index a0af2cb1..ed9e5721 100644 --- a/kasa/tests/test_smartdevice.py +++ b/kasa/tests/test_smartdevice.py @@ -127,21 +127,21 @@ async def test_get_modules(): dummy_device = await get_device_for_fixture_protocol( "KS240(US)_1.0_1.0.5.json", "SMART" ) - from kasa.smart.modules import CloudModule + from kasa.smart.modules import Cloud # Modules on device - module = dummy_device.modules.get("CloudModule") + module = dummy_device.modules.get("Cloud") assert module assert module._device == dummy_device - assert isinstance(module, CloudModule) + assert isinstance(module, Cloud) module = dummy_device.modules.get(Module.Cloud) assert module assert module._device == dummy_device - assert isinstance(module, CloudModule) + assert isinstance(module, Cloud) # Modules on child - module = dummy_device.modules.get("FanModule") + module = dummy_device.modules.get("Fan") assert module assert module._device != dummy_device assert module._device._parent == dummy_device