Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 96
Add an approach for determining if a dataclass field is supported#740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
718646f88f0ef9fda76b4afc9f81c5fe198deadd70File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import datetime | ||
| import logging | ||
| from dataclasses import dataclass | ||
| from dataclasses import dataclass, field | ||
| from enum import StrEnum | ||
| from typing import Any | ||
| from roborock.const import ( | ||
| @@ -91,12 +92,39 @@ | ||
| _LOGGER = logging.getLogger(__name__) | ||
| class FieldNameBase(StrEnum): | ||
| """A base enum class that represents a field name in a RoborockBase dataclass.""" | ||
| class StatusField(FieldNameBase): | ||
| """An enum that represents a field in the `Status` class. | ||
| This is used with `roborock.devices.traits.v1.status.DeviceFeaturesTrait` | ||
| to understand if a feature is supported by the device using `is_field_supported`. | ||
| The enum values are names of fields in the `Status` class. Each field is | ||
| annotated with `requires_schema_code` metadata to map the field to a schema | ||
| code in the product schema, which may have a different name than the field/attribute name. | ||
| """ | ||
| STATE = "state" | ||
| BATTERY = "battery" | ||
| FAN_POWER = "fan_power" | ||
| WATER_BOX_MODE = "water_box_mode" | ||
| CHARGE_STATUS = "charge_status" | ||
| DRY_STATUS = "dry_status" | ||
Lash-L marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| def _requires_schema_code(requires_schema_code: str, default=None) -> Any: | ||
| return field(metadata={"requires_schema_code": requires_schema_code}, default=default) | ||
| @dataclass | ||
| class Status(RoborockBase): | ||
| msg_ver: int | None = None | ||
| msg_seq: int | None = None | ||
| state: RoborockStateCode | None = None | ||
| battery: int | None = None | ||
| state: RoborockStateCode | None = _requires_schema_code("state", default=None) | ||
| battery: int | None = _requires_schema_code("battery", default=None) | ||
| clean_time: int | None = None | ||
| clean_area: int | None = None | ||
| error_code: RoborockErrorCode | None = None | ||
| @@ -109,12 +137,12 @@ class Status(RoborockBase): | ||
| back_type: int | None = None | ||
| wash_phase: int | None = None | ||
| wash_ready: int | None = None | ||
| fan_power: RoborockFanPowerCode | None = None | ||
| fan_power: RoborockFanPowerCode | None = _requires_schema_code("fan_power", default=None) | ||
| dnd_enabled: int | None = None | ||
| map_status: int | None = None | ||
| is_locating: int | None = None | ||
| lock_status: int | None = None | ||
| water_box_mode: RoborockMopIntensityCode | None = None | ||
| water_box_mode: RoborockMopIntensityCode | None = _requires_schema_code("water_box_mode", default=None) | ||
| water_box_carriage_status: int | None = None | ||
| mop_forbidden_enable: int | None = None | ||
| camera_status: int | None = None | ||
| @@ -132,13 +160,13 @@ class Status(RoborockBase): | ||
| collision_avoid_status: int | None = None | ||
| switch_map_mode: int | None = None | ||
| dock_error_status: RoborockDockErrorCode | None = None | ||
| charge_status: int | None = None | ||
| charge_status: int | None = _requires_schema_code("charge_status", default=None) | ||
| unsave_map_reason: int | None = None | ||
| unsave_map_flag: int | None = None | ||
| wash_status: int | None = None | ||
| distance_off: int | None = None | ||
| in_warmup: int | None = None | ||
| dry_status: int | None = None | ||
| dry_status: int | None = _requires_schema_code("drying_status", default=None) | ||
| rdt: int | None = None | ||
| clean_percent: int | None = None | ||
| rss: int | None = None | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # serializer version: 1 | ||
| # name: test_is_attribute_supported[home_data_device_s5e.json] | ||
| dict({ | ||
| 'battery': True, | ||
| 'charge_status': True, | ||
| 'dry_status': True, | ||
| 'fan_power': True, | ||
| 'state': True, | ||
| 'water_box_mode': True, | ||
| }) | ||
| # --- | ||
| # name: test_is_attribute_supported[home_data_device_s7_maxv.json] | ||
| dict({ | ||
| 'battery': True, | ||
| 'charge_status': True, | ||
| 'dry_status': True, | ||
| 'fan_power': True, | ||
| 'state': True, | ||
| 'water_box_mode': True, | ||
| }) | ||
| # --- | ||
| # name: test_is_attribute_supported[home_data_device_saros_10r.json] | ||
| dict({ | ||
| 'battery': True, | ||
| 'charge_status': True, | ||
| 'dry_status': True, | ||
| 'fan_power': True, | ||
| 'state': True, | ||
| 'water_box_mode': True, | ||
| }) | ||
| # --- |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,33 @@ | ||||||
| """Tests for the DeviceFeaturesTrait related functionality.""" | ||||||
| import pytest | ||||||
| from syrupy import SnapshotAssertion | ||||||
| from roborock.data import HomeDataDevice | ||||||
| from roborock.data.v1.v1_containers import StatusField | ||||||
| from roborock.devices.device import RoborockDevice | ||||||
| from roborock.devices.traits.v1.status import StatusTrait | ||||||
| from tests import mock_data | ||||||
| V1_DEVICES = { | ||||||
| k: HomeDataDevice.from_dict(device) for k, device in mock_data.DEVICES.items() if device.get("pv") == "1.0" | ||||||
| } | ||||||
| @pytest.mark.parametrize( | ||||||
| ("device_info"), | ||||||
CopilotAI | ||||||
| ("device_info"), | |
| "device_info", |
CopilotAIJan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docstring incorrectly refers to "roborock.devices.traits.v1.status.DeviceFeaturesTrait" when it should be "roborock.devices.traits.v1.device_features.DeviceFeaturesTrait". The DeviceFeaturesTrait class is located in the device_features module, not the status module.