diff --git a/.pylintrc b/.pylintrc index f350fd7..5071b8a 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,7 +1,9 @@ [MESSAGES CONTROL] -disable=C,R +disable=missing-docstring [FORMAT] +max-args=6 +max-attributes=8 max-line-length=88 diff --git a/pyhon/__main__.py b/pyhon/__main__.py index c6460f5..9e9b25b 100755 --- a/pyhon/__main__.py +++ b/pyhon/__main__.py @@ -11,6 +11,7 @@ from typing import Tuple, Dict, Any if __name__ == "__main__": sys.path.insert(0, str(Path(__file__).parent.parent)) +# pylint: disable=wrong-import-position from pyhon import Hon, HonAPI, diagnose, printer _LOGGER = logging.getLogger(__name__) @@ -91,11 +92,9 @@ async def main() -> None: data = device.data.copy() attr = "get" if args.get("all") else "pop" print( - printer.key_print( - data["attributes"].__getattribute__(attr)("parameters") - ) + printer.key_print(getattr(data["attributes"], attr)("parameters")) ) - print(printer.key_print(data.__getattribute__(attr)("appliance"))) + print(printer.key_print(getattr(data, attr)("appliance"))) print(printer.key_print(data)) print( printer.pretty_print( diff --git a/pyhon/appliance.py b/pyhon/appliance.py index f1a4c8c..86d39db 100644 --- a/pyhon/appliance.py +++ b/pyhon/appliance.py @@ -21,6 +21,7 @@ if TYPE_CHECKING: _LOGGER = logging.getLogger(__name__) +# pylint: disable=too-many-public-methods,too-many-instance-attributes class HonAppliance: _MINIMAL_UPDATE_INTERVAL = 5 # seconds diff --git a/pyhon/appliances/dw.py b/pyhon/appliances/dw.py index 8c08da3..5d0465d 100644 --- a/pyhon/appliances/dw.py +++ b/pyhon/appliances/dw.py @@ -1,3 +1,4 @@ +# pylint: disable=duplicate-code from typing import Any, Dict from pyhon.appliances.base import ApplianceBase diff --git a/pyhon/appliances/td.py b/pyhon/appliances/td.py index 1b623f8..1f33044 100644 --- a/pyhon/appliances/td.py +++ b/pyhon/appliances/td.py @@ -1,3 +1,4 @@ +# pylint: disable=duplicate-code from typing import Any, Dict from pyhon.appliances.base import ApplianceBase diff --git a/pyhon/appliances/wd.py b/pyhon/appliances/wd.py index e2a274b..6ae0388 100644 --- a/pyhon/appliances/wd.py +++ b/pyhon/appliances/wd.py @@ -1,3 +1,4 @@ +# pylint: disable=duplicate-code from typing import Dict, Any from pyhon.appliances.base import ApplianceBase diff --git a/pyhon/appliances/wm.py b/pyhon/appliances/wm.py index 1fc95c0..27572fa 100644 --- a/pyhon/appliances/wm.py +++ b/pyhon/appliances/wm.py @@ -1,3 +1,4 @@ +# pylint: disable=duplicate-code from typing import Any, Dict from pyhon.appliances.base import ApplianceBase diff --git a/pyhon/command_loader.py b/pyhon/command_loader.py index 127dd08..476eeb2 100644 --- a/pyhon/command_loader.py +++ b/pyhon/command_loader.py @@ -17,12 +17,12 @@ class HonCommandLoader: """Loads and parses hOn command data""" def __init__(self, api: "HonAPI", appliance: "HonAppliance") -> None: + self._api: "HonAPI" = api + self._appliance: "HonAppliance" = appliance self._api_commands: Dict[str, Any] = {} self._favourites: List[Dict[str, Any]] = [] self._command_history: List[Dict[str, Any]] = [] self._commands: Dict[str, HonCommand] = {} - self._api: "HonAPI" = api - self._appliance: "HonAppliance" = appliance self._appliance_data: Dict[str, Any] = {} self._additional_data: Dict[str, Any] = {} diff --git a/pyhon/commands.py b/pyhon/commands.py index 70dc74d..442dc10 100644 --- a/pyhon/commands.py +++ b/pyhon/commands.py @@ -27,17 +27,16 @@ class HonCommand: categories: Optional[Dict[str, "HonCommand"]] = None, category_name: str = "", ): + self._name: str = name self._api: Optional[HonAPI] = appliance.api self._appliance: "HonAppliance" = appliance - self._name: str = name self._categories: Optional[Dict[str, "HonCommand"]] = categories self._category_name: str = category_name - self._description: str = attributes.pop("description", "") - self._protocol_type: str = attributes.pop("protocolType", "") - self._parameters: Dict[str, HonParameter] = {} + self._parameters: Dict[str, Parameter] = {} self._data: Dict[str, Any] = {} - self._available_settings: Dict[str, HonParameter] = {} self._rules: List[HonRuleSet] = [] + attributes.pop("description", "") + attributes.pop("protocolType", "") self._load_parameters(attributes) def __repr__(self) -> str: diff --git a/pyhon/connection/auth.py b/pyhon/connection/auth.py index 2629dfb..cf75410 100644 --- a/pyhon/connection/auth.py +++ b/pyhon/connection/auth.py @@ -30,6 +30,14 @@ class HonLoginData: loaded: Optional[Dict[str, Any]] = None +@dataclass +class HonAuthData: + access_token: str = "" + refresh_token: str = "" + cognito_token: str = "" + id_token: str = "" + + class HonAuth: _TOKEN_EXPIRES_AFTER_HOURS = 8 _TOKEN_EXPIRE_WARNING_HOURS = 7 @@ -46,28 +54,25 @@ class HonAuth: self._login_data = HonLoginData() self._login_data.email = email self._login_data.password = password - self._access_token = "" - self._refresh_token = "" - self._cognito_token = "" - self._id_token = "" self._device = device self._expires: datetime = datetime.utcnow() + self._auth = HonAuthData() @property def cognito_token(self) -> str: - return self._cognito_token + return self._auth.cognito_token @property def id_token(self) -> str: - return self._id_token + return self._auth.id_token @property def access_token(self) -> str: - return self._access_token + return self._auth.access_token @property def refresh_token(self) -> str: - return self._refresh_token + return self._auth.refresh_token def _check_token_expiration(self, hours: int) -> bool: return datetime.utcnow() >= self._expires + timedelta(hours=hours) @@ -192,12 +197,12 @@ class HonAuth: def _parse_token_data(self, text: str) -> bool: if access_token := re.findall("access_token=(.*?)&", text): - self._access_token = access_token[0] + self._auth.access_token = access_token[0] if refresh_token := re.findall("refresh_token=(.*?)&", text): - self._refresh_token = refresh_token[0] + self._auth.refresh_token = refresh_token[0] if id_token := re.findall("id_token=(.*?)&", text): - self._id_token = id_token[0] - return True if access_token and refresh_token and id_token else False + self._auth.id_token = id_token[0] + return bool(access_token and refresh_token and id_token) async def _get_token(self, url: str) -> bool: async with self._request.get(url) as response: @@ -229,7 +234,7 @@ class HonAuth: return True async def _api_auth(self) -> bool: - post_headers = {"id-token": self._id_token} + post_headers = {"id-token": self._auth.id_token} data = self._device.get() async with self._request.post( f"{const.API_URL}/auth/v1/login", headers=post_headers, json=data @@ -239,8 +244,8 @@ class HonAuth: except json.JSONDecodeError: await self._error_logger(response) return False - self._cognito_token = json_data.get("cognitoUser", {}).get("Token", "") - if not self._cognito_token: + self._auth.cognito_token = json_data.get("cognitoUser", {}).get("Token", "") + if not self._auth.cognito_token: _LOGGER.error(json_data) raise exceptions.HonAuthenticationError() return True @@ -262,7 +267,7 @@ class HonAuth: async def refresh(self) -> bool: params = { "client_id": const.CLIENT_ID, - "refresh_token": self._refresh_token, + "refresh_token": self._auth.refresh_token, "grant_type": "refresh_token", } async with self._request.post( @@ -273,14 +278,14 @@ class HonAuth: return False data = await response.json() self._expires = datetime.utcnow() - self._id_token = data["id_token"] - self._access_token = data["access_token"] + self._auth.id_token = data["id_token"] + self._auth.access_token = data["access_token"] return await self._api_auth() def clear(self) -> None: self._session.cookie_jar.clear_domain(const.AUTH_API.split("/")[-2]) self._request.called_urls = [] - self._cognito_token = "" - self._id_token = "" - self._access_token = "" - self._refresh_token = "" + self._auth.cognito_token = "" + self._auth.id_token = "" + self._auth.access_token = "" + self._auth.refresh_token = "" diff --git a/pyhon/hon.py b/pyhon/hon.py index b207b87..d6c73e2 100644 --- a/pyhon/hon.py +++ b/pyhon/hon.py @@ -7,9 +7,10 @@ from typing import List, Optional, Dict, Any, Type from aiohttp import ClientSession from typing_extensions import Self -from pyhon import HonAPI, exceptions from pyhon.appliance import HonAppliance +from pyhon.connection.api import HonAPI from pyhon.connection.api import TestAPI +from pyhon.exceptions import NoAuthenticationException _LOGGER = logging.getLogger(__name__) @@ -43,7 +44,7 @@ class Hon: @property def api(self) -> HonAPI: if self._api is None: - raise exceptions.NoAuthenticationException + raise NoAuthenticationException return self._api @property diff --git a/pyhon/printer.py b/pyhon/printer.py index ac7d66e..9c84815 100644 --- a/pyhon/printer.py +++ b/pyhon/printer.py @@ -30,7 +30,7 @@ def pretty_print( ) -> str: result = "" space = whitespace * intend - if (isinstance(data, list) or isinstance(data, dict)) and key: + if isinstance(data, (dict, list)) and key: result += f"{space}{'- ' if is_list else ''}{key}:\n" intend += 1 if isinstance(data, list): @@ -39,10 +39,10 @@ def pretty_print( value, intend=intend, is_list=True, whitespace=whitespace ) elif isinstance(data, dict): - for i, (key, value) in enumerate(sorted(data.items())): + for i, (list_key, value) in enumerate(sorted(data.items())): result += pretty_print( value, - key=key, + key=list_key, intend=intend + (is_list if i else 0), is_list=is_list and not i, whitespace=whitespace, diff --git a/pyhon/rules.py b/pyhon/rules.py index 5dadad7..57d6de5 100644 --- a/pyhon/rules.py +++ b/pyhon/rules.py @@ -25,6 +25,10 @@ class HonRuleSet: self._rules: Dict[str, List[HonRule]] = {} self._parse_rule(rule) + @property + def rules(self) -> Dict[str, List[HonRule]]: + return self._rules + def _parse_rule(self, rule: Dict[str, Any]) -> None: for param_key, params in rule.items(): param_key = self._command.appliance.options.get(param_key, param_key) diff --git a/pyhon/typedefs.py b/pyhon/typedefs.py index 2a22319..51a137b 100644 --- a/pyhon/typedefs.py +++ b/pyhon/typedefs.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: from pyhon.parameter.range import HonParameterRange -class Callback(Protocol): +class Callback(Protocol): # pylint: disable=too-few-public-methods def __call__( self, url: str | URL, *args: Any, **kwargs: Any ) -> aiohttp.client._RequestContextManager: diff --git a/requirements_dev.txt b/requirements_dev.txt index 9bb012e..a28b33e 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,4 +1,4 @@ -black==23.3.0 +black==23.7.0 flake8==6.0.0 -mypy==1.2.0 -pylint==2.17.2 +mypy==1.4.1 +pylint==2.17.4