Merge branch 'master' into defer_expensive_log_formatting

This commit is contained in:
J. Nick Koston 2024-01-18 07:52:14 -10:00 committed by GitHub
commit 24fc2820f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 6 deletions

View File

@ -37,12 +37,17 @@ def _dataclass_from_dict(klass, in_val):
fieldtypes = {f.name: f.type for f in fields(klass)} fieldtypes = {f.name: f.type for f in fields(klass)}
val = {} val = {}
for dict_key in in_val: for dict_key in in_val:
if dict_key in fieldtypes and hasattr(fieldtypes[dict_key], "from_dict"): if dict_key in fieldtypes:
if hasattr(fieldtypes[dict_key], "from_dict"):
val[dict_key] = fieldtypes[dict_key].from_dict(in_val[dict_key]) val[dict_key] = fieldtypes[dict_key].from_dict(in_val[dict_key])
else: else:
val[dict_key] = _dataclass_from_dict( val[dict_key] = _dataclass_from_dict(
fieldtypes[dict_key], in_val[dict_key] fieldtypes[dict_key], in_val[dict_key]
) )
else:
raise SmartDeviceException(
f"Cannot create dataclass from dict, unknown key: {dict_key}"
)
return klass(**val) return klass(**val)
else: else:
return in_val return in_val
@ -173,6 +178,8 @@ class DeviceConfig:
return _dataclass_to_dict(self) return _dataclass_to_dict(self)
@staticmethod @staticmethod
def from_dict(cparam_dict: Dict[str, Dict[str, str]]) -> "DeviceConfig": def from_dict(config_dict: Dict[str, Dict[str, str]]) -> "DeviceConfig":
"""Return device config from dict.""" """Return device config from dict."""
return _dataclass_from_dict(DeviceConfig, cparam_dict) if isinstance(config_dict, dict):
return _dataclass_from_dict(DeviceConfig, config_dict)
raise SmartDeviceException(f"Invalid device config data: {config_dict}")

View File

@ -2,6 +2,7 @@ from json import dumps as json_dumps
from json import loads as json_loads from json import loads as json_loads
import aiohttp import aiohttp
import pytest
from kasa.credentials import Credentials from kasa.credentials import Credentials
from kasa.deviceconfig import ( from kasa.deviceconfig import (
@ -10,6 +11,7 @@ from kasa.deviceconfig import (
DeviceFamilyType, DeviceFamilyType,
EncryptType, EncryptType,
) )
from kasa.exceptions import SmartDeviceException
async def test_serialization(): async def test_serialization():
@ -21,6 +23,19 @@ async def test_serialization():
assert config == config2 assert config == config2
@pytest.mark.parametrize(
("input_value", "expected_msg"),
[
({"Foo": "Bar"}, "Cannot create dataclass from dict, unknown key: Foo"),
("foobar", "Invalid device config data: foobar"),
],
ids=["invalid-dict", "not-dict"],
)
def test_deserialization_errors(input_value, expected_msg):
with pytest.raises(SmartDeviceException, match=expected_msg):
DeviceConfig.from_dict(input_value)
async def test_credentials_hash(): async def test_credentials_hash():
config = DeviceConfig( config = DeviceConfig(
host="Foo", host="Foo",