Avoid duplicate property calls when writing sensor state (#101853)

* Avoid duplicate attribute lookups when writing sensor state

_numeric_state_expected would call self.device_class,
self.state_class, self.native_unit_of_measurement,
and self.suggested_display_precision a second time
when the `state` path already had these values.

* one more

* avoid another
This commit is contained in:
J. Nick Koston 2023-10-11 20:45:20 -10:00 committed by GitHub
parent f0317f0d59
commit 6ce5f190c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -150,6 +150,28 @@ class SensorEntityDescription(EntityDescription):
unit_of_measurement: None = None # Type override, use native_unit_of_measurement
def _numeric_state_expected(
device_class: SensorDeviceClass | None,
state_class: SensorStateClass | str | None,
native_unit_of_measurement: str | None,
suggested_display_precision: int | None,
) -> bool:
"""Return true if the sensor must be numeric."""
# Note: the order of the checks needs to be kept aligned
# with the checks in `state` property.
if device_class in NON_NUMERIC_DEVICE_CLASSES:
return False
if (
state_class is not None
or native_unit_of_measurement is not None
or suggested_display_precision is not None
):
return True
# Sensors with custom device classes will have the device class
# converted to None and are not considered numeric
return device_class is not None
class SensorEntity(Entity):
"""Base class for sensor entities."""
@ -284,20 +306,12 @@ class SensorEntity(Entity):
@property
def _numeric_state_expected(self) -> bool:
"""Return true if the sensor must be numeric."""
# Note: the order of the checks needs to be kept aligned
# with the checks in `state` property.
device_class = try_parse_enum(SensorDeviceClass, self.device_class)
if device_class in NON_NUMERIC_DEVICE_CLASSES:
return False
if (
self.state_class is not None
or self.native_unit_of_measurement is not None
or self.suggested_display_precision is not None
):
return True
# Sensors with custom device classes will have the device class
# converted to None and are not considered numeric
return device_class is not None
return _numeric_state_expected(
try_parse_enum(SensorDeviceClass, self.device_class),
self.state_class,
self.native_unit_of_measurement,
self.suggested_display_precision,
)
@property
def options(self) -> list[str] | None:
@ -377,10 +391,8 @@ class SensorEntity(Entity):
def state_attributes(self) -> dict[str, Any] | None:
"""Return state attributes."""
if last_reset := self.last_reset:
if (
self.state_class != SensorStateClass.TOTAL
and not self._last_reset_reported
):
state_class = self.state_class
if state_class != SensorStateClass.TOTAL and not self._last_reset_reported:
self._last_reset_reported = True
report_issue = self._suggest_report_issue()
# This should raise in Home Assistant Core 2022.5
@ -393,11 +405,11 @@ class SensorEntity(Entity):
),
self.entity_id,
type(self),
self.state_class,
state_class,
report_issue,
)
if self.state_class == SensorStateClass.TOTAL:
if state_class == SensorStateClass.TOTAL:
return {ATTR_LAST_RESET: last_reset.isoformat()}
return None
@ -470,9 +482,9 @@ class SensorEntity(Entity):
native_unit_of_measurement = self.native_unit_of_measurement
if (
self.device_class == SensorDeviceClass.TEMPERATURE
and native_unit_of_measurement
native_unit_of_measurement
in {UnitOfTemperature.CELSIUS, UnitOfTemperature.FAHRENHEIT}
and self.device_class == SensorDeviceClass.TEMPERATURE
):
return self.hass.config.units.temperature_unit
@ -590,7 +602,9 @@ class SensorEntity(Entity):
# If the sensor has neither a device class, a state class, a unit of measurement
# nor a precision then there are no further checks or conversions
if not self._numeric_state_expected:
if not _numeric_state_expected(
device_class, state_class, native_unit_of_measurement, suggested_precision
):
return value
# From here on a numerical value is expected