From fd603ac807df9ab3653b82f1d196d4353d4dae1d Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:31:16 +0000 Subject: [PATCH 1/3] Do not error when accessing smart device_type before update --- kasa/smart/smartdevice.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kasa/smart/smartdevice.py b/kasa/smart/smartdevice.py index 0989842ab..9f883ee66 100644 --- a/kasa/smart/smartdevice.py +++ b/kasa/smart/smartdevice.py @@ -765,10 +765,10 @@ def device_type(self) -> DeviceType: if self._device_type is not DeviceType.Unknown: return self._device_type - # Fallback to device_type (from disco info) - type_str = self._info.get("type", self._info.get("device_type")) - - if not type_str: # no update or discovery info + if not self._components or not ( + type_str := self._info.get("type", self._info.get("device_type")) + ): + # no update or discovery info return self._device_type self._device_type = self._get_device_type_from_components( From a0ae526820b5f431969a4a6f2a0ef4f74365389e Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:36:45 +0000 Subject: [PATCH 2/3] Add test --- kasa/smart/smartdevice.py | 5 +++-- tests/discovery_fixtures.py | 2 ++ tests/smart/test_smartdevice.py | 13 +++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/kasa/smart/smartdevice.py b/kasa/smart/smartdevice.py index 3ec6cb59f..176efb710 100644 --- a/kasa/smart/smartdevice.py +++ b/kasa/smart/smartdevice.py @@ -765,8 +765,9 @@ def device_type(self) -> DeviceType: if self._device_type is not DeviceType.Unknown: return self._device_type - if not self._components or not ( - type_str := self._info.get("type", self._info.get("device_type")) + if ( + not (type_str := self._info.get("type", self._info.get("device_type"))) + or not self._components ): # no update or discovery info return self._device_type diff --git a/tests/discovery_fixtures.py b/tests/discovery_fixtures.py index c65d47bda..939215365 100644 --- a/tests/discovery_fixtures.py +++ b/tests/discovery_fixtures.py @@ -130,6 +130,8 @@ def parametrize_discovery( "new discovery", data_root_filter="discovery_result" ) +smart_discovery = parametrize_discovery("smart discovery", protocol_filter={"SMART"}) + @pytest.fixture( params=filter_fixtures("discoverable", protocol_filter={"SMART", "IOT"}), diff --git a/tests/smart/test_smartdevice.py b/tests/smart/test_smartdevice.py index c53193a32..0b0ca155a 100644 --- a/tests/smart/test_smartdevice.py +++ b/tests/smart/test_smartdevice.py @@ -18,9 +18,11 @@ from kasa.smart.modules.energy import Energy from kasa.smart.smartmodule import SmartModule from tests.conftest import ( + DISCOVERY_MOCK_IP, device_smart, get_device_for_fixture_protocol, get_parent_and_child_modules, + smart_discovery, ) from tests.device_fixtures import variable_temp_smart @@ -51,6 +53,17 @@ async def test_update_no_device_info(dev: SmartDevice, mocker: MockerFixture): await dev.update() +@smart_discovery +async def test_repr_no_update(discovery_mock): + dev = SmartDevice(DISCOVERY_MOCK_IP) + assert repr(dev) == f"" + dev.update_from_discover_info(discovery_mock.discovery_data["result"]) + assert ( + repr(dev) + == f"" + ) + + @device_smart async def test_initial_update(dev: SmartDevice, mocker: MockerFixture): """Test the initial update cycle.""" From d026ffd48c2687ca717bc36c5198ab118007a348 Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Thu, 5 Dec 2024 09:03:19 +0000 Subject: [PATCH 3/3] Add test for unknown device_family --- tests/smart/test_smartdevice.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/smart/test_smartdevice.py b/tests/smart/test_smartdevice.py index 0b0ca155a..81707a11a 100644 --- a/tests/smart/test_smartdevice.py +++ b/tests/smart/test_smartdevice.py @@ -2,6 +2,7 @@ from __future__ import annotations +import copy import logging import time from typing import Any, cast @@ -11,7 +12,7 @@ from freezegun.api import FrozenDateTimeFactory from pytest_mock import MockerFixture -from kasa import Device, KasaException, Module +from kasa import Device, DeviceType, KasaException, Module from kasa.exceptions import DeviceError, SmartErrorCode from kasa.protocols.smartprotocol import _ChildProtocolWrapper from kasa.smart import SmartDevice @@ -54,14 +55,28 @@ async def test_update_no_device_info(dev: SmartDevice, mocker: MockerFixture): @smart_discovery -async def test_repr_no_update(discovery_mock): +async def test_device_type_no_update(discovery_mock, caplog: pytest.LogCaptureFixture): + """Test device type and repr when device not updated.""" dev = SmartDevice(DISCOVERY_MOCK_IP) + assert dev.device_type is DeviceType.Unknown assert repr(dev) == f"" - dev.update_from_discover_info(discovery_mock.discovery_data["result"]) + + discovery_result = copy.deepcopy(discovery_mock.discovery_data["result"]) + dev.update_from_discover_info(discovery_result) + assert dev.device_type is DeviceType.Unknown assert ( repr(dev) == f"" ) + discovery_result["device_type"] = "SMART.FOOBAR" + dev.update_from_discover_info(discovery_result) + dev._components = {"dummy": 1} + assert dev.device_type is DeviceType.Plug + assert ( + repr(dev) + == f"" + ) + assert "Unknown device type, falling back to plug" in caplog.text @device_smart