|
6 | 6 | import logging
|
7 | 7 | from asyncio import timeout as asyncio_timeout
|
8 | 8 | from collections.abc import Callable, Coroutine
|
| 9 | +from dataclasses import dataclass, field |
9 | 10 | from datetime import date
|
10 |
| -from typing import TYPE_CHECKING |
| 11 | +from typing import TYPE_CHECKING, Annotated |
11 | 12 |
|
12 |
| -from pydantic.v1 import BaseModel, Field, validator |
| 13 | +from mashumaro import DataClassDictMixin, field_options |
| 14 | +from mashumaro.types import Alias |
13 | 15 |
|
14 | 16 | from ...exceptions import KasaException
|
15 | 17 | from ...feature import Feature
|
|
22 | 24 | _LOGGER = logging.getLogger(__name__)
|
23 | 25 |
|
24 | 26 |
|
25 |
| -class DownloadState(BaseModel): |
| 27 | +@dataclass |
| 28 | +class DownloadState(DataClassDictMixin): |
26 | 29 | """Download state."""
|
27 | 30 |
|
28 | 31 | # Example:
|
29 | 32 | # {'status': 0, 'download_progress': 0, 'reboot_time': 5,
|
30 | 33 | # 'upgrade_time': 5, 'auto_upgrade': False}
|
31 | 34 | status: int
|
32 |
| - progress: int = Field(alias="download_progress") |
| 35 | + progress: Annotated[int, Alias("download_progress")] |
33 | 36 | reboot_time: int
|
34 | 37 | upgrade_time: int
|
35 | 38 | auto_upgrade: bool
|
36 | 39 |
|
37 | 40 |
|
38 |
| -class UpdateInfo(BaseModel): |
| 41 | +@dataclass |
| 42 | +class UpdateInfo(DataClassDictMixin): |
39 | 43 | """Update info status object."""
|
40 | 44 |
|
41 |
| - status: int = Field(alias="type") |
42 |
| - version: str | None = Field(alias="fw_ver", default=None) |
43 |
| - release_date: date | None = None |
44 |
| - release_notes: str | None = Field(alias="release_note", default=None) |
| 45 | + status: Annotated[int, Alias("type")] |
| 46 | + needs_upgrade: Annotated[bool, Alias("need_to_upgrade")] |
| 47 | + version: Annotated[str | None, Alias("fw_ver")] = None |
| 48 | + release_date: date | None = field( |
| 49 | + default=None, |
| 50 | + metadata=field_options( |
| 51 | + deserialize=lambda x: date.fromisoformat(x) if x else None |
| 52 | + ), |
| 53 | + ) |
| 54 | + release_notes: Annotated[str | None, Alias("release_note")] = None |
45 | 55 | fw_size: int | None = None
|
46 | 56 | oem_id: str | None = None
|
47 |
| - needs_upgrade: bool = Field(alias="need_to_upgrade") |
48 |
| - |
49 |
| - @validator("release_date", pre=True) |
50 |
| - def _release_date_optional(cls, v: str) -> str | None: |
51 |
| - if not v: |
52 |
| - return None |
53 |
| - |
54 |
| - return v |
55 | 57 |
|
56 | 58 | @property
|
57 | 59 | def update_available(self) -> bool:
|
@@ -139,7 +141,7 @@ async def check_latest_firmware(self) -> UpdateInfo | None:
|
139 | 141 | """Check for the latest firmware for the device."""
|
140 | 142 | try:
|
141 | 143 | fw = await self.call("get_latest_fw")
|
142 |
| - self._firmware_update_info = UpdateInfo.parse_obj(fw["get_latest_fw"]) |
| 144 | + self._firmware_update_info = UpdateInfo.from_dict(fw["get_latest_fw"]) |
143 | 145 | return self._firmware_update_info
|
144 | 146 | except Exception:
|
145 | 147 | _LOGGER.exception("Error getting latest firmware for %s:", self._device)
|
@@ -174,7 +176,7 @@ async def get_update_state(self) -> DownloadState:
|
174 | 176 | """Return update state."""
|
175 | 177 | resp = await self.call("get_fw_download_state")
|
176 | 178 | state = resp["get_fw_download_state"]
|
177 |
| - return DownloadState(**state) |
| 179 | + return DownloadState.from_dict(state) |
178 | 180 |
|
179 | 181 | @allow_update_after
|
180 | 182 | async def update(
|
@@ -232,7 +234,7 @@ async def update(
|
232 | 234 | else:
|
233 | 235 | _LOGGER.warning("Unhandled state code: %s", state)
|
234 | 236 |
|
235 |
| - return state.dict() |
| 237 | + return state.to_dict() |
236 | 238 |
|
237 | 239 | @property
|
238 | 240 | def auto_update_enabled(self) -> bool:
|
|
0 commit comments