Skip to content

Commit 4725574

Browse files
authored
feat: Allow RoborockModeEnum parsing by either enum name, value name, or code. (#711)
* feat: Allow RoborockModeEnum parsing by either enum name, value name, or code This will be used for command line parsing for Q10 commands. Adds the first tests in the tests/data directory since we moved many containers here. * chore: Fix lint errors in code mappings test
1 parent bf31b9b commit 4725574

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

roborock/data/code_mappings.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,28 @@ def __new__(cls, value: str, code: int) -> RoborockModeEnum:
6464
return member
6565

6666
@classmethod
67-
def from_code(cls, code: int):
67+
def from_code(cls, code: int) -> RoborockModeEnum:
6868
for member in cls:
6969
if member.code == code:
7070
return member
7171
raise ValueError(f"{code} is not a valid code for {cls.__name__}")
7272

73+
@classmethod
74+
def from_value(cls, value: str) -> RoborockModeEnum:
75+
"""Find enum member by string value (case-insensitive)."""
76+
for member in cls:
77+
if member.value.lower() == value.lower():
78+
return member
79+
raise ValueError(f"{value} is not a valid value for {cls.__name__}")
80+
81+
@classmethod
82+
def from_name(cls, name: str) -> RoborockModeEnum:
83+
"""Find enum member by name (case-insensitive)."""
84+
for member in cls:
85+
if member.name.lower() == name.lower():
86+
return member
87+
raise ValueError(f"{name} is not a valid name for {cls.__name__}")
88+
7389
@classmethod
7490
def keys(cls) -> list[str]:
7591
"""Returns a list of all member values."""

tests/data/test_code_mappings.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""Tests for code mappings.
2+
These tests exercise the custom enum methods using arbitrary enum values.
3+
"""
4+
5+
import pytest
6+
7+
from roborock.data.b01_q10.b01_q10_code_mappings import B01_Q10_DP
8+
9+
10+
def test_from_code() -> None:
11+
"""Test from_code method."""
12+
assert B01_Q10_DP.START_CLEAN == B01_Q10_DP.from_code(201)
13+
assert B01_Q10_DP.PAUSE == B01_Q10_DP.from_code(204)
14+
assert B01_Q10_DP.STOP == B01_Q10_DP.from_code(206)
15+
16+
17+
def test_invalid_from_code() -> None:
18+
"""Test invalid from_code method."""
19+
with pytest.raises(ValueError, match="999999 is not a valid code for B01_Q10_DP"):
20+
B01_Q10_DP.from_code(999999)
21+
22+
23+
def test_from_name() -> None:
24+
"""Test from_name method."""
25+
assert B01_Q10_DP.START_CLEAN == B01_Q10_DP.from_name("START_CLEAN")
26+
assert B01_Q10_DP.PAUSE == B01_Q10_DP.from_name("pause")
27+
assert B01_Q10_DP.STOP == B01_Q10_DP.from_name("Stop")
28+
29+
30+
def test_invalid_from_name() -> None:
31+
"""Test invalid from_name method."""
32+
with pytest.raises(ValueError, match="INVALID_NAME is not a valid name for B01_Q10_DP"):
33+
B01_Q10_DP.from_name("INVALID_NAME")
34+
35+
36+
def test_from_value() -> None:
37+
"""Test from_value method."""
38+
assert B01_Q10_DP.START_CLEAN == B01_Q10_DP.from_value("dpStartClean")
39+
assert B01_Q10_DP.PAUSE == B01_Q10_DP.from_value("dpPause")
40+
assert B01_Q10_DP.STOP == B01_Q10_DP.from_value("dpStop")
41+
42+
43+
def test_invalid_from_value() -> None:
44+
"""Test invalid from_value method."""
45+
with pytest.raises(ValueError, match="invalid_value is not a valid value for B01_Q10_DP"):
46+
B01_Q10_DP.from_value("invalid_value")

0 commit comments

Comments
 (0)