10000 Migrate TurnOnBehaviours to mashumaro (#1285) · python-kasa/python-kasa@3e397f1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3e397f1

Browse files
sdb9696rytilahti
authored andcommitted
Migrate TurnOnBehaviours to mashumaro (#1285)
1 parent b2ecfed commit 3e397f1

File tree

3 files changed

+54
-25
lines changed

3 files changed

+54
-25
lines changed

kasa/iot/iotbulb.py

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
import logging
66
import re
7+
from dataclasses import dataclass
78
from enum import Enum
8-
from typing import cast
9+
from typing import Annotated, cast
910

10-
from pydantic.v1 import BaseModel, Field, root_validator
11+
from mashumaro import DataClassDictMixin
12+
from mashumaro.config import BaseConfig
13+
from mashumaro.types import Alias
1114

1215
from ..device_type import DeviceType
1316
from ..deviceconfig import DeviceConfig
@@ -35,9 +38,12 @@ class BehaviorMode(str, Enum):
3538
Last = "last_status"
3639
#: Use chosen preset.
3740
Preset = "customize_preset"
41+
#: Circadian
42+
Circadian = "circadian"
3843

3944

40-
class TurnOnBehavior(BaseModel):
45+
@dataclass
46+
class TurnOnBehavior(DataClassDictMixin):
4147
"""Model to present a single turn on behavior.
4248
4349
:param int preset: the index number of wanted preset.
@@ -48,34 +54,30 @@ class TurnOnBehavior(BaseModel):
4854
to contain either the preset index, or ``None`` for the last known state.
4955
"""
5056

51-
#: Index of preset to use, or ``None`` for the last known state.
52-
preset: int | None = Field(alias="index", default=None)
53-
#: Wanted behavior
54-
mode: BehaviorMode
55-
56-
@root_validator
57-
def _mode_based_on_preset(cls, values: dict) -> dict:
58-
"""Set the mode based on the preset value."""
59-
if values["preset"] is not None:
60-
values["mode"] = BehaviorMode.Preset
61-
else:
62-
values["mode"] = BehaviorMode.Last
57+
class Config(BaseConfig):
58+
"""Serialization config."""
6359

64-
return values
60+
omit_none = True
61+
serialize_by_alias = True
6562

66-
class Config:
67-
"""Configuration to make the validator run when changing the values."""
68-
69-
validate_assignment = True
63+
#: Wanted behavior
64+
mode: BehaviorMode
65+
#: Index of preset to use, or ``None`` for the last known state.
66+
preset: Annotated[int | None, Alias("index")] = None
67+
brightness: int | None = None
68+
color_temp: int | None = None
69+
hue: int | None = None
70+
saturation: int | None = None
7071

7172

72-
class TurnOnBehaviors(BaseModel):
73+
@dataclass
74+
class TurnOnBehaviors(DataClassDictMixin):
7375
"""Model to contain turn on behaviors."""
7476

7577
#: The behavior when the bulb is turned on programmatically.
76-
soft: TurnOnBehavior = Field(alias="soft_on")
78+
soft: Annotated[TurnOnBehavior, Alias("soft_on")]
7779
#: The behavior when the bulb has been off from mains power.
78-
hard: TurnOnBehavior = Field(alias="hard_on")
80+
hard: Annotated[TurnOnBehavior, Alias("hard_on")]
7981

8082

8183
TPLINK_KELVIN = {
@@ -303,7 +305,7 @@ async def get_light_details(self) -> dict[str, int]:
303305

304306
async def get_turn_on_behavior(self) -> TurnOnBehaviors:
305307
"""Return the behavior for turning the bulb on."""
306-
return TurnOnBehaviors.parse_obj(
308+
return TurnOnBehaviors.from_dict(
307309
await self._query_helper(self.LIGHT_SERVICE, "get_default_behavior")
308310
)
309311

@@ -314,7 +316,7 @@ async def set_turn_on_behavior(self, behavior: TurnOnBehaviors) -> dict:
314316
you should use :func:`get_turn_on_behavior` to get the current settings.
315317
"""
316318
return await self._query_helper(
317-
self.LIGHT_SERVICE, "set_default_behavior", behavior.dict(by_alias=True)
319+
self.LIGHT_SERVICE, "set_default_behavior", behavior.to_dict()
318320
)
319321

320322
async def get_light_state(self) -> dict[str, dict]:

tests/fakeprotocol_iot.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,23 @@ def success(res):
176176
}
177177
}
178178

179+
LIGHT_DETAILS = {
180+
"color_rendering_index": 80,
181+
"err_code": 0,
182+
"incandescent_equivalent": 60,
183+
"lamp_beam_angle": 150,
184+
"max_lumens": 800,
185+
"max_voltage": 120,
186+
"min_voltage": 110,
187+
"wattage": 10,
188+
}
189+
190+
DEFAULT_BEHAVIOR = {
191+
"err_code": 0,
192+
"hard_on": {"mode": "circadian"},
193+
"soft_on": {"mode": "last_status"},
194+
}
195+
179196

180197
class FakeIotProtocol(IotProtocol):
181198
def __init__(self, info, fixture_name=None, *, verbatim=False):
@@ -399,6 +416,8 @@ def set_time(self, new_state: dict, *args):
399416
},
400417
"smartlife.iot.smartbulb.lightingservice": {
401418
"get_light_state": light_state,
419+
"get_light_details": LIGHT_DETAILS,
420+
"get_default_behavior": DEFAULT_BEHAVIOR,
402421
"transition_light_state": transition_light_state,
403422
"set_preferred_state": set_preferred_state,
404423
},
@@ -409,6 +428,8 @@ def set_time(self, new_state: dict, *args):
409428
"smartlife.iot.lightStrip": {
410429
"set_light_state": transition_light_state,
411430
"get_light_state": light_state,
431+
"get_light_details": LIGHT_DETAILS,
432+
"get_default_behavior": DEFAULT_BEHAVIOR,
412433
"set_preferred_state": set_preferred_state,
413434
},
414435
"smartlife.iot.common.system": {

tests/test_bulb.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,3 +497,9 @@ async def test_modify_preset_payloads(dev: IotBulb, preset, payload, mocker):
497497
@bulb
498498
def test_device_type_bulb(dev: Device):
499499
assert dev.device_type in {DeviceType.Bulb, DeviceType.LightStrip}
500+
501+
502+
@bulb_iot
503+
async def test_turn_on_behaviours(dev: IotBulb):
504+
behavior = await dev.get_turn_on_behavior()
505+
assert behavior

0 commit comments

Comments
 (0)
0