mirror of
				https://github.com/python-kasa/python-kasa.git
				synced 2025-11-04 06:32:07 +00:00 
			
		
		
		
	Raise SmartDeviceException on invalid config dicts (#640)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
		@@ -37,11 +37,16 @@ def _dataclass_from_dict(klass, in_val):
 | 
			
		||||
        fieldtypes = {f.name: f.type for f in fields(klass)}
 | 
			
		||||
        val = {}
 | 
			
		||||
        for dict_key in in_val:
 | 
			
		||||
            if dict_key in fieldtypes and hasattr(fieldtypes[dict_key], "from_dict"):
 | 
			
		||||
                val[dict_key] = fieldtypes[dict_key].from_dict(in_val[dict_key])
 | 
			
		||||
            if dict_key in fieldtypes:
 | 
			
		||||
                if hasattr(fieldtypes[dict_key], "from_dict"):
 | 
			
		||||
                    val[dict_key] = fieldtypes[dict_key].from_dict(in_val[dict_key])
 | 
			
		||||
                else:
 | 
			
		||||
                    val[dict_key] = _dataclass_from_dict(
 | 
			
		||||
                        fieldtypes[dict_key], in_val[dict_key]
 | 
			
		||||
                    )
 | 
			
		||||
            else:
 | 
			
		||||
                val[dict_key] = _dataclass_from_dict(
 | 
			
		||||
                    fieldtypes[dict_key], in_val[dict_key]
 | 
			
		||||
                raise SmartDeviceException(
 | 
			
		||||
                    f"Cannot create dataclass from dict, unknown key: {dict_key}"
 | 
			
		||||
                )
 | 
			
		||||
        return klass(**val)
 | 
			
		||||
    else:
 | 
			
		||||
@@ -173,6 +178,8 @@ class DeviceConfig:
 | 
			
		||||
        return _dataclass_to_dict(self)
 | 
			
		||||
 | 
			
		||||
    @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 _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}")
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ from json import dumps as json_dumps
 | 
			
		||||
from json import loads as json_loads
 | 
			
		||||
 | 
			
		||||
import aiohttp
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from kasa.credentials import Credentials
 | 
			
		||||
from kasa.deviceconfig import (
 | 
			
		||||
@@ -10,6 +11,7 @@ from kasa.deviceconfig import (
 | 
			
		||||
    DeviceFamilyType,
 | 
			
		||||
    EncryptType,
 | 
			
		||||
)
 | 
			
		||||
from kasa.exceptions import SmartDeviceException
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def test_serialization():
 | 
			
		||||
@@ -21,6 +23,19 @@ async def test_serialization():
 | 
			
		||||
    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():
 | 
			
		||||
    config = DeviceConfig(
 | 
			
		||||
        host="Foo",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user