Improve Tuya data validation#157968
Conversation
|
Hey there @tuya, @zlinoliver, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
There was a problem hiding this comment.
Pull request overview
This PR refactors the Tuya integration's data validation by moving validation logic from wrapper classes into type information classes, improving code organization and type safety. The changes make TypeInformation classes generic with a typed process_raw_value() method, add validation for boolean and integer values, and centralize the duplicate warning suppression logic.
Key changes:
- Added
BooleanTypeInformationclass with validation that rejects non-boolean values - Enhanced
IntegerTypeInformation.process_raw_value()to validate values are within min/max range - Enhanced
EnumTypeInformation.process_raw_value()to validate values are in the allowed range - Moved
DEVICE_WARNINGSdictionary and_should_log_warning()frommodels.pytotype_information.py - Removed redundant
read_device_status()methods from wrapper classes, now using base implementation
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/tuya/type_information.py |
Adds validation logic to type information classes, makes classes generic, and includes warning deduplication |
homeassistant/components/tuya/models.py |
Removes validation logic from wrapper classes and moves DEVICE_WARNINGS to type_information.py |
homeassistant/components/tuya/fan.py |
Removes unnecessary # type: ignore[override] comment now that return type matches base class |
homeassistant/components/tuya/diagnostics.py |
Updates import to reference moved DEVICE_WARNINGS location |
tests/components/tuya/snapshots/test_climate.ambr |
Updates test snapshots where invalid out-of-range temperature values now correctly return None instead of invalid scaled values |
| if not isinstance(raw_value, int) or not (self.min <= raw_value <= self.max): | ||
| if _should_log_warning( | ||
| device.id, f"integer_out_range|{self.dpcode}|{raw_value}" | ||
| ): | ||
| LOGGER.warning( | ||
| "Found invalid integer value `%s` for datapoint `%s` in product " | ||
| "id `%s`, expected value between %s and %s; please report this " | ||
| "defect to Tuya support", | ||
| raw_value, | ||
| self.dpcode, | ||
| device.product_id, | ||
| self.min, | ||
| self.max, | ||
| ) |
There was a problem hiding this comment.
The validation logic combines type checking and range checking in a single condition. If raw_value is not an integer (e.g., a float or string), the warning message will incorrectly suggest the issue is with the range rather than the type. Consider separating these checks:
if not isinstance(raw_value, int):
if _should_log_warning(...):
LOGGER.warning("Found invalid type `%s` for integer datapoint `%s`...", type(raw_value).__name__, ...)
return None
if not (self.min <= raw_value <= self.max):
if _should_log_warning(...):
LOGGER.warning("Found integer value `%s` out of range for datapoint `%s`...", raw_value, ...)
return None| 'supported_features': <ClimateEntityFeature: 401>, | ||
| 'target_temp_step': 1.0, | ||
| 'temperature': 2.3, | ||
| 'temperature': None, |
There was a problem hiding this comment.
This device reports temp_set with status 23, but min 50 / max 350
| 'min_temp': 12, | ||
| 'target_temp_step': 1.0, | ||
| 'temperature': 4, | ||
| 'temperature': None, |
There was a problem hiding this comment.
This (same) device reports temp_set_f with status 41, but min 122 / max 662
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Proposed change
process_raw_valueis now typed)Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: