mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
c5d65b624b
Passing in a string still works and returns either `IotModule` or `SmartModule` type when called on `IotDevice` or `SmartDevice` respectively. When calling on `Device` will return `Module` type. Passing in a module type is then typed to that module, i.e.: ```py smartdev.get_module(FanModule) # type is FanModule smartdev.get_module("FanModule") # type is SmartModule ``` Only thing this doesn't do is check that you can't pass an `IotModule` to a `SmartDevice.get_module()`. However there is a runtime check which will return null if the passed `ModuleType` is not a subclass of `SmartModule`. Many thanks to @cdce8p for helping with this.
70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
"""Base class for all module implementations."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from abc import ABC, abstractmethod
|
|
from typing import (
|
|
TYPE_CHECKING,
|
|
TypeVar,
|
|
)
|
|
|
|
from .exceptions import KasaException
|
|
from .feature import Feature
|
|
|
|
if TYPE_CHECKING:
|
|
from .device import Device
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
ModuleT = TypeVar("ModuleT", bound="Module")
|
|
|
|
|
|
class Module(ABC):
|
|
"""Base class implemention for all modules.
|
|
|
|
The base classes should implement `query` to return the query they want to be
|
|
executed during the regular update cycle.
|
|
"""
|
|
|
|
def __init__(self, device: Device, module: str):
|
|
self._device = device
|
|
self._module = module
|
|
self._module_features: dict[str, Feature] = {}
|
|
|
|
@abstractmethod
|
|
def query(self):
|
|
"""Query to execute during the update cycle.
|
|
|
|
The inheriting modules implement this to include their wanted
|
|
queries to the query that gets executed when Device.update() gets called.
|
|
"""
|
|
|
|
@property
|
|
@abstractmethod
|
|
def data(self):
|
|
"""Return the module specific raw data from the last update."""
|
|
|
|
def _initialize_features(self): # noqa: B027
|
|
"""Initialize features after the initial update.
|
|
|
|
This can be implemented if features depend on module query responses.
|
|
"""
|
|
|
|
def _add_feature(self, feature: Feature):
|
|
"""Add module feature."""
|
|
|
|
def _slugified_name(name):
|
|
return name.lower().replace(" ", "_").replace("'", "_")
|
|
|
|
feat_name = _slugified_name(feature.name)
|
|
if feat_name in self._module_features:
|
|
raise KasaException("Duplicate name detected %s" % feat_name)
|
|
self._module_features[feat_name] = feature
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<Module {self.__class__.__name__} ({self._module})"
|
|
f" for {self._device.host}>"
|
|
)
|