Skip to content

Commit 1519e9b

Browse files
committed
chore: move parsing to the container
1 parent 1cd66b8 commit 1519e9b

File tree

3 files changed

+30
-11
lines changed

3 files changed

+30
-11
lines changed

roborock/data/b01_q7/b01_q7_containers.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import datetime
2+
import json
23
from dataclasses import dataclass, field
4+
from functools import cached_property
35

6+
from ...exceptions import RoborockException
47
from ..containers import RoborockBase
58
from .b01_q7_code_mappings import (
69
B01Fault,
@@ -246,6 +249,17 @@ class CleanRecordListItem(RoborockBase):
246249
url: str | None = None
247250
detail: str | None = None
248251

252+
@cached_property
253+
def detail_parsed(self) -> CleanRecordDetail | None:
254+
"""Parse and return the detail as a CleanRecordDetail object."""
255+
if self.detail is None:
256+
return None
257+
try:
258+
parsed = json.loads(self.detail)
259+
except json.JSONDecodeError as ex:
260+
raise RoborockException(f"Invalid B01 record detail JSON: {self.detail!r}") from ex
261+
return CleanRecordDetail.from_dict(parsed)
262+
249263

250264
@dataclass
251265
class CleanRecordList(RoborockBase):

roborock/devices/traits/b01/q7/clean_summary.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from __future__ import annotations
88

9-
import json
9+
import logging
1010

1111
from roborock import CleanRecordDetail, CleanRecordList, CleanRecordSummary
1212
from roborock.devices.rpc.b01_q7_channel import send_decoded_command
@@ -20,6 +20,8 @@
2020
"CleanSummaryTrait",
2121
]
2222

23+
_LOGGER = logging.getLogger(__name__)
24+
2325

2426
class CleanSummaryTrait(CleanRecordSummary, Trait):
2527
"""B01/Q7 clean summary + clean record access (via record list service)."""
@@ -59,14 +61,12 @@ async def _get_clean_record_details(self, *, record_list: CleanRecordList) -> li
5961
"""Return parsed record detail objects (newest-first)."""
6062
details: list[CleanRecordDetail] = []
6163
for item in record_list.record_list:
62-
if item.detail is None:
63-
continue
6464
try:
65-
parsed = json.loads(item.detail)
66-
except json.JSONDecodeError as ex:
67-
raise RoborockException(f"Invalid B01 record detail JSON: {item.detail!r}") from ex
68-
parsed = CleanRecordDetail.from_dict(parsed)
69-
65+
parsed = item.detail_parsed
66+
except RoborockException as ex:
67+
# Rather than failing if something goes wrong here, we should fail and log to tell the user.
68+
_LOGGER.debug("Failed to parse record detail: %s", ex)
69+
continue
7070
if parsed is not None:
7171
details.append(parsed)
7272

tests/devices/traits/b01/q7/test_clean_summary.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Tests for CleanSummaryTrait class for B01/Q7 devices."""
22

33
import json
4+
import logging
45

56
import pytest
67

@@ -156,8 +157,9 @@ async def test_get_clean_record_details_with_none_detail(
156157

157158
async def test_get_clean_record_details_invalid_json(
158159
clean_summary_trait: CleanSummaryTrait,
160+
caplog: pytest.LogCaptureFixture,
159161
) -> None:
160-
"""Test that invalid JSON in detail raises RoborockException."""
162+
"""Test that invalid JSON in detail is logged and skipped."""
161163
response_with_invalid_json = {
162164
"total_time": 34980,
163165
"total_area": 28540,
@@ -170,7 +172,10 @@ async def test_get_clean_record_details_invalid_json(
170172
],
171173
}
172174

173-
with pytest.raises(RoborockException, match="Invalid B01 record detail JSON"):
174-
await clean_summary_trait._get_clean_record_details(
175+
with caplog.at_level(logging.DEBUG):
176+
details = await clean_summary_trait._get_clean_record_details(
175177
record_list=CleanRecordList.from_dict(response_with_invalid_json)
176178
)
179+
180+
assert len(details) == 0
181+
assert any("Failed to parse record detail" in record.message for record in caplog.records)

0 commit comments

Comments
 (0)