tplink: forward compatible typing and test changes for kasa 0.8 (#131623)
parent
2edcda47b0
commit
f3964596de
|
@ -148,7 +148,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: TPLinkConfigEntry) -> bo
|
|||
if conn_params_dict := entry.data.get(CONF_CONNECTION_PARAMETERS):
|
||||
try:
|
||||
conn_params = Device.ConnectionParameters.from_dict(conn_params_dict)
|
||||
except KasaException:
|
||||
except (KasaException, TypeError, ValueError, LookupError):
|
||||
_LOGGER.warning(
|
||||
"Invalid connection parameters dict for %s: %s", host, conn_params_dict
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Final
|
||||
from typing import Final, cast
|
||||
|
||||
from kasa import Feature
|
||||
|
||||
|
@ -98,4 +98,4 @@ class TPLinkBinarySensorEntity(CoordinatedTPLinkFeatureEntity, BinarySensorEntit
|
|||
@callback
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the entity's attributes."""
|
||||
self._attr_is_on = self._feature.value
|
||||
self._attr_is_on = cast(bool | None, self._feature.value)
|
||||
|
|
|
@ -116,8 +116,8 @@ class TPLinkClimateEntity(CoordinatedTPLinkEntity, ClimateEntity):
|
|||
@callback
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the entity's attributes."""
|
||||
self._attr_current_temperature = self._temp_feature.value
|
||||
self._attr_target_temperature = self._target_feature.value
|
||||
self._attr_current_temperature = cast(float | None, self._temp_feature.value)
|
||||
self._attr_target_temperature = cast(float | None, self._target_feature.value)
|
||||
|
||||
self._attr_hvac_mode = (
|
||||
HVACMode.HEAT if self._state_feature.value else HVACMode.OFF
|
||||
|
@ -134,7 +134,9 @@ class TPLinkClimateEntity(CoordinatedTPLinkEntity, ClimateEntity):
|
|||
self._attr_hvac_action = HVACAction.OFF
|
||||
return
|
||||
|
||||
self._attr_hvac_action = STATE_TO_ACTION[self._mode_feature.value]
|
||||
self._attr_hvac_action = STATE_TO_ACTION[
|
||||
cast(ThermostatState, self._mode_feature.value)
|
||||
]
|
||||
|
||||
def _get_unique_id(self) -> str:
|
||||
"""Return unique id."""
|
||||
|
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
from typing import Final
|
||||
from typing import Final, cast
|
||||
|
||||
from kasa import Device, Feature
|
||||
|
||||
|
@ -108,4 +108,4 @@ class TPLinkNumberEntity(CoordinatedTPLinkFeatureEntity, NumberEntity):
|
|||
@callback
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the entity's attributes."""
|
||||
self._attr_native_value = self._feature.value
|
||||
self._attr_native_value = cast(float | None, self._feature.value)
|
||||
|
|
|
@ -93,4 +93,4 @@ class TPLinkSelectEntity(CoordinatedTPLinkFeatureEntity, SelectEntity):
|
|||
@callback
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the entity's attributes."""
|
||||
self._attr_current_option = self._feature.value
|
||||
self._attr_current_option = cast(str | None, self._feature.value)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import cast
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
from kasa import Feature
|
||||
|
||||
|
@ -161,6 +161,12 @@ class TPLinkSensorEntity(CoordinatedTPLinkFeatureEntity, SensorEntity):
|
|||
# We probably do not need this, when we are rounding already?
|
||||
self._attr_suggested_display_precision = self._feature.precision_hint
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# pylint: disable-next=import-outside-toplevel
|
||||
from datetime import date, datetime
|
||||
|
||||
assert isinstance(value, str | int | float | date | datetime | None)
|
||||
|
||||
self._attr_native_value = value
|
||||
# Map to homeassistant units and fallback to upstream one if none found
|
||||
if (unit := self._feature.unit) is not None:
|
||||
|
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import Any, cast
|
||||
|
||||
from kasa import Feature
|
||||
|
||||
|
@ -99,4 +99,4 @@ class TPLinkSwitch(CoordinatedTPLinkFeatureEntity, SwitchEntity):
|
|||
@callback
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the entity's attributes."""
|
||||
self._attr_is_on = self._feature.value
|
||||
self._attr_is_on = cast(bool | None, self._feature.value)
|
||||
|
|
|
@ -6,6 +6,7 @@ from typing import Any
|
|||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from kasa import (
|
||||
BaseProtocol,
|
||||
Device,
|
||||
DeviceConfig,
|
||||
DeviceConnectionParameters,
|
||||
|
@ -17,7 +18,6 @@ from kasa import (
|
|||
Module,
|
||||
)
|
||||
from kasa.interfaces import Fan, Light, LightEffect, LightState
|
||||
from kasa.protocol import BaseProtocol
|
||||
from kasa.smart.modules.alarm import Alarm
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
|
@ -62,7 +62,9 @@ CONN_PARAMS_LEGACY = DeviceConnectionParameters(
|
|||
DeviceFamily.IotSmartPlugSwitch, DeviceEncryptionType.Xor
|
||||
)
|
||||
DEVICE_CONFIG_LEGACY = DeviceConfig(IP_ADDRESS)
|
||||
DEVICE_CONFIG_DICT_LEGACY = DEVICE_CONFIG_LEGACY.to_dict(exclude_credentials=True)
|
||||
DEVICE_CONFIG_DICT_LEGACY = {
|
||||
k: v for k, v in DEVICE_CONFIG_LEGACY.to_dict().items() if k != "credentials"
|
||||
}
|
||||
CREDENTIALS = Credentials("foo", "bar")
|
||||
CREDENTIALS_HASH_AES = "AES/abcdefghijklmnopqrstuvabcdefghijklmnopqrstuv=="
|
||||
CREDENTIALS_HASH_KLAP = "KLAP/abcdefghijklmnopqrstuv=="
|
||||
|
@ -86,8 +88,12 @@ DEVICE_CONFIG_AES = DeviceConfig(
|
|||
uses_http=True,
|
||||
aes_keys=AES_KEYS,
|
||||
)
|
||||
DEVICE_CONFIG_DICT_KLAP = DEVICE_CONFIG_KLAP.to_dict(exclude_credentials=True)
|
||||
DEVICE_CONFIG_DICT_AES = DEVICE_CONFIG_AES.to_dict(exclude_credentials=True)
|
||||
DEVICE_CONFIG_DICT_KLAP = {
|
||||
k: v for k, v in DEVICE_CONFIG_KLAP.to_dict().items() if k != "credentials"
|
||||
}
|
||||
DEVICE_CONFIG_DICT_AES = {
|
||||
k: v for k, v in DEVICE_CONFIG_AES.to_dict().items() if k != "credentials"
|
||||
}
|
||||
CREATE_ENTRY_DATA_LEGACY = {
|
||||
CONF_HOST: IP_ADDRESS,
|
||||
CONF_ALIAS: ALIAS,
|
||||
|
|
|
@ -45,6 +45,7 @@ from . import (
|
|||
CREDENTIALS_HASH_AES,
|
||||
CREDENTIALS_HASH_KLAP,
|
||||
DEVICE_CONFIG_AES,
|
||||
DEVICE_CONFIG_DICT_KLAP,
|
||||
DEVICE_CONFIG_KLAP,
|
||||
DEVICE_CONFIG_LEGACY,
|
||||
DEVICE_ID,
|
||||
|
@ -538,9 +539,8 @@ async def test_move_credentials_hash(
|
|||
from the device.
|
||||
"""
|
||||
device_config = {
|
||||
**DEVICE_CONFIG_KLAP.to_dict(
|
||||
exclude_credentials=True, credentials_hash="theHash"
|
||||
)
|
||||
**DEVICE_CONFIG_DICT_KLAP,
|
||||
"credentials_hash": "theHash",
|
||||
}
|
||||
entry_data = {**CREATE_ENTRY_DATA_KLAP, CONF_DEVICE_CONFIG: device_config}
|
||||
|
||||
|
@ -586,9 +586,8 @@ async def test_move_credentials_hash_auth_error(
|
|||
in async_setup_entry.
|
||||
"""
|
||||
device_config = {
|
||||
**DEVICE_CONFIG_KLAP.to_dict(
|
||||
exclude_credentials=True, credentials_hash="theHash"
|
||||
)
|
||||
**DEVICE_CONFIG_DICT_KLAP,
|
||||
"credentials_hash": "theHash",
|
||||
}
|
||||
entry_data = {**CREATE_ENTRY_DATA_KLAP, CONF_DEVICE_CONFIG: device_config}
|
||||
|
||||
|
@ -630,9 +629,8 @@ async def test_move_credentials_hash_other_error(
|
|||
at the end of the test.
|
||||
"""
|
||||
device_config = {
|
||||
**DEVICE_CONFIG_KLAP.to_dict(
|
||||
exclude_credentials=True, credentials_hash="theHash"
|
||||
)
|
||||
**DEVICE_CONFIG_DICT_KLAP,
|
||||
"credentials_hash": "theHash",
|
||||
}
|
||||
entry_data = {**CREATE_ENTRY_DATA_KLAP, CONF_DEVICE_CONFIG: device_config}
|
||||
|
||||
|
@ -729,7 +727,7 @@ async def test_credentials_hash_auth_error(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
expected_config = DeviceConfig.from_dict(
|
||||
DEVICE_CONFIG_KLAP.to_dict(exclude_credentials=True, credentials_hash="theHash")
|
||||
{**DEVICE_CONFIG_DICT_KLAP, "credentials_hash": "theHash"}
|
||||
)
|
||||
expected_config.uses_http = False
|
||||
expected_config.http_client = "Foo"
|
||||
|
@ -767,7 +765,9 @@ async def test_migrate_remove_device_config(
|
|||
CONF_HOST: expected_entry_data[CONF_HOST],
|
||||
CONF_ALIAS: ALIAS,
|
||||
CONF_MODEL: MODEL,
|
||||
CONF_DEVICE_CONFIG: device_config.to_dict(exclude_credentials=True),
|
||||
CONF_DEVICE_CONFIG: {
|
||||
k: v for k, v in device_config.to_dict().items() if k != "credentials"
|
||||
},
|
||||
}
|
||||
|
||||
entry = MockConfigEntry(
|
||||
|
|
Loading…
Reference in New Issue