From e43f4412fa196bbb9e65ac1db4aa12339ca8c840 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 23 Dec 2023 13:20:24 -1000 Subject: [PATCH] Fix native_step in number not looking at _attr_native_step (#106327) --- homeassistant/components/number/__init__.py | 4 +-- tests/components/number/test_init.py | 40 +++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/number/__init__.py b/homeassistant/components/number/__init__.py index c1da287879f..55b281e02e1 100644 --- a/homeassistant/components/number/__init__.py +++ b/homeassistant/components/number/__init__.py @@ -306,6 +306,8 @@ class NumberEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_): @cached_property def native_step(self) -> float | None: """Return the increment/decrement step.""" + if hasattr(self, "_attr_native_step"): + return self._attr_native_step if ( hasattr(self, "entity_description") and self.entity_description.native_step is not None @@ -321,8 +323,6 @@ class NumberEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_): def _calculate_step(self, min_value: float, max_value: float) -> float: """Return the increment/decrement step.""" - if hasattr(self, "_attr_native_step"): - return self._attr_native_step if (native_step := self.native_step) is not None: return native_step step = DEFAULT_STEP diff --git a/tests/components/number/test_init.py b/tests/components/number/test_init.py index 601a34d4271..4de47b9b844 100644 --- a/tests/components/number/test_init.py +++ b/tests/components/number/test_init.py @@ -131,6 +131,31 @@ class MockNumberEntityDescr(NumberEntity): return None +class MockNumberEntityAttrWithDescription(NumberEntity): + """Mock NumberEntity device to use in tests. + + This class sets an entity description and overrides + all the values with _attr members to ensure the _attr + members take precedence over the entity description. + """ + + def __init__(self): + """Initialize the clas instance.""" + self.entity_description = NumberEntityDescription( + "test", + native_max_value=10.0, + native_min_value=-10.0, + native_step=2.0, + native_unit_of_measurement="native_rabbits", + ) + + _attr_native_max_value = 1000.0 + _attr_native_min_value = -1000.0 + _attr_native_step = 100.0 + _attr_native_unit_of_measurement = "native_dogs" + _attr_native_value = 500.0 + + class MockDefaultNumberEntityDeprecated(NumberEntity): """Mock NumberEntity device to use in tests. @@ -277,6 +302,21 @@ async def test_attributes(hass: HomeAssistant) -> None: ATTR_STEP: 2.0, } + number_5 = MockNumberEntityAttrWithDescription() + number_5.hass = hass + assert number_5.max_value == 1000.0 + assert number_5.min_value == -1000.0 + assert number_5.step == 100.0 + assert number_5.native_step == 100.0 + assert number_5.unit_of_measurement == "native_dogs" + assert number_5.value == 500.0 + assert number_5.capability_attributes == { + ATTR_MAX: 1000.0, + ATTR_MIN: -1000.0, + ATTR_MODE: NumberMode.AUTO, + ATTR_STEP: 100.0, + } + async def test_sync_set_value(hass: HomeAssistant) -> None: """Test if async set_value calls sync set_value."""