Skip to content

Commit cfef7c5

Browse files
authored
Don't assume that attrs exists for every dynamic component (#785)
* Use get for virtual components attrs * Add basic tests * Remove unused `noqa`
1 parent b2571cb commit cfef7c5

File tree

4 files changed

+67
-3
lines changed

4 files changed

+67
-3
lines changed

aioshelly/rpc_device/device.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ def _parse_dynamic_components(self, components: dict[str, Any]) -> None:
562562

563563
self._config.update(
564564
{
565-
item["key"]: {**item["config"], **item["attrs"]}
565+
item["key"]: {**item["config"], **item.get("attrs", {})}
566566
for item in self._dynamic_components
567567
}
568568
)

ruff.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ lint.ignore = [
3737
"D103",
3838
"D104",
3939
"S101",
40+
"SLF001",
4041
]
4142

4243
[lint.mccabe]

tests/rpc_device/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,5 +137,5 @@ async def ws_rpc(
137137
@pytest_asyncio.fixture
138138
async def ws_rpc_with_auth(ws_rpc: WsRPCMocker) -> AsyncGenerator[WsRPCMocker, None]:
139139
"""Fixture for an RPC WebSocket with authentication."""
140-
ws_rpc._auth_data = AuthData("any", "any", "any") # noqa: SLF001
140+
ws_rpc._auth_data = AuthData("any", "any", "any")
141141
yield ws_rpc

tests/rpc_device/test_device.py

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
"""Tests for rpc_device.device module."""
22

3-
from aioshelly.rpc_device.device import mergedicts
3+
from unittest.mock import Mock
4+
5+
import pytest
6+
7+
from aioshelly.rpc_device.device import RpcDevice, mergedicts
8+
9+
VIRT_COMP_STATUS = {"value": 0}
10+
VIRT_COMP_CONFIG = {
11+
"id": 200,
12+
"name": "Test",
13+
"min": 0,
14+
"max": 100,
15+
"meta": {"ui": {"view": "slider", "unit": "%", "step": 1}},
16+
}
17+
VIRT_COMP_ATTRS = {"role": "current_humidity"}
418

519

620
def test_mergedicts() -> None:
@@ -9,3 +23,52 @@ def test_mergedicts() -> None:
923
source = {"b": {"c": 4, "e": 5}}
1024
mergedicts(dest, source)
1125
assert dest == {"a": 1, "b": {"c": 4, "d": 3, "e": 5}}
26+
27+
28+
@pytest.mark.asyncio
29+
async def test_parse_dynamic_components() -> None:
30+
"""Test RPC device _parse_dynamic_components() method."""
31+
device = await RpcDevice.create(Mock(), Mock(), "10.10.10.10")
32+
33+
device._status = {}
34+
device._config = {}
35+
36+
device._parse_dynamic_components(
37+
{
38+
"components": [
39+
{
40+
"key": "number:200",
41+
"status": VIRT_COMP_STATUS,
42+
"config": VIRT_COMP_CONFIG,
43+
}
44+
]
45+
}
46+
)
47+
48+
assert device._status["number:200"] == VIRT_COMP_STATUS
49+
assert device._config["number:200"] == VIRT_COMP_CONFIG
50+
51+
52+
@pytest.mark.asyncio
53+
async def test_parse_dynamic_components_with_attrs() -> None:
54+
"""Test RPC device _parse_dynamic_components() method with attrs."""
55+
device = await RpcDevice.create(Mock(), Mock(), "10.10.10.10")
56+
57+
device._status = {}
58+
device._config = {}
59+
60+
device._parse_dynamic_components(
61+
{
62+
"components": [
63+
{
64+
"key": "number:200",
65+
"status": VIRT_COMP_STATUS,
66+
"config": VIRT_COMP_CONFIG,
67+
"attrs": VIRT_COMP_ATTRS,
68+
}
69+
]
70+
}
71+
)
72+
73+
assert device._status["number:200"] == VIRT_COMP_STATUS
74+
assert device._config["number:200"] == {**VIRT_COMP_CONFIG, **VIRT_COMP_ATTRS}

0 commit comments

Comments
 (0)