From 51b2d0b4f8e16b5892c1ca9d8e408270863335c8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 20 Feb 2020 08:30:24 -0800 Subject: [PATCH] Add entity ID to input_number warning (#32012) * Add entity ID to warning * Input Number flexibility --- .../components/input_number/__init__.py | 34 +++--------- .../input_number/reproduce_state.py | 12 +++-- tests/components/input_number/test_init.py | 52 +++++++++---------- 3 files changed, 41 insertions(+), 57 deletions(-) diff --git a/homeassistant/components/input_number/__init__.py b/homeassistant/components/input_number/__init__.py index f78fc485e40..eb781baf2ca 100644 --- a/homeassistant/components/input_number/__init__.py +++ b/homeassistant/components/input_number/__init__.py @@ -288,44 +288,22 @@ class InputNumber(RestoreEntity): async def async_set_value(self, value): """Set new value.""" num_value = float(value) + if num_value < self._minimum or num_value > self._maximum: - _LOGGER.warning( - "Invalid value: %s (range %s - %s)", - num_value, - self._minimum, - self._maximum, + raise vol.Invalid( + f"Invalid value for {self.entity_id}: {value} (range {self._minimum} - {self._maximum})" ) - return + self._current_value = num_value self.async_write_ha_state() async def async_increment(self): """Increment value.""" - new_value = self._current_value + self._step - if new_value > self._maximum: - _LOGGER.warning( - "Invalid value: %s (range %s - %s)", - new_value, - self._minimum, - self._maximum, - ) - return - self._current_value = new_value - self.async_write_ha_state() + await self.async_set_value(min(self._current_value + self._step, self._maximum)) async def async_decrement(self): """Decrement value.""" - new_value = self._current_value - self._step - if new_value < self._minimum: - _LOGGER.warning( - "Invalid value: %s (range %s - %s)", - new_value, - self._minimum, - self._maximum, - ) - return - self._current_value = new_value - self.async_write_ha_state() + await self.async_set_value(max(self._current_value - self._step, self._minimum)) async def async_update_config(self, config: typing.Dict) -> None: """Handle when the config is updated.""" diff --git a/homeassistant/components/input_number/reproduce_state.py b/homeassistant/components/input_number/reproduce_state.py index 22a91f74000..a81c7041607 100644 --- a/homeassistant/components/input_number/reproduce_state.py +++ b/homeassistant/components/input_number/reproduce_state.py @@ -3,6 +3,8 @@ import asyncio import logging from typing import Iterable, Optional +import voluptuous as vol + from homeassistant.const import ATTR_ENTITY_ID from homeassistant.core import Context, State from homeassistant.helpers.typing import HomeAssistantType @@ -37,9 +39,13 @@ async def _async_reproduce_state( service = SERVICE_SET_VALUE service_data = {ATTR_ENTITY_ID: state.entity_id, ATTR_VALUE: state.state} - await hass.services.async_call( - DOMAIN, service, service_data, context=context, blocking=True - ) + try: + await hass.services.async_call( + DOMAIN, service, service_data, context=context, blocking=True + ) + except vol.Invalid as err: + # If value out of range. + _LOGGER.warning("Unable to reproduce state for %s: %s", state.entity_id, err) async def async_reproduce_states( diff --git a/tests/components/input_number/test_init.py b/tests/components/input_number/test_init.py index 8331e1374c8..28b9d27d23f 100644 --- a/tests/components/input_number/test_init.py +++ b/tests/components/input_number/test_init.py @@ -3,6 +3,7 @@ from unittest.mock import patch import pytest +import voluptuous as vol from homeassistant.components.input_number import ( ATTR_VALUE, @@ -21,7 +22,6 @@ from homeassistant.const import ( from homeassistant.core import Context, CoreState, State from homeassistant.exceptions import Unauthorized from homeassistant.helpers import entity_registry -from homeassistant.loader import bind_hass from homeassistant.setup import async_setup_component from tests.common import mock_restore_cache @@ -63,38 +63,36 @@ def storage_setup(hass, hass_storage): return _storage -@bind_hass -def set_value(hass, entity_id, value): +async def set_value(hass, entity_id, value): """Set input_number to value. This is a legacy helper method. Do not use it for new tests. """ - hass.async_create_task( - hass.services.async_call( - DOMAIN, SERVICE_SET_VALUE, {ATTR_ENTITY_ID: entity_id, ATTR_VALUE: value} - ) + await hass.services.async_call( + DOMAIN, + SERVICE_SET_VALUE, + {ATTR_ENTITY_ID: entity_id, ATTR_VALUE: value}, + blocking=True, ) -@bind_hass -def increment(hass, entity_id): +async def increment(hass, entity_id): """Increment value of entity. This is a legacy helper method. Do not use it for new tests. """ - hass.async_create_task( - hass.services.async_call(DOMAIN, SERVICE_INCREMENT, {ATTR_ENTITY_ID: entity_id}) + await hass.services.async_call( + DOMAIN, SERVICE_INCREMENT, {ATTR_ENTITY_ID: entity_id}, blocking=True ) -@bind_hass -def decrement(hass, entity_id): +async def decrement(hass, entity_id): """Decrement value of entity. This is a legacy helper method. Do not use it for new tests. """ - hass.async_create_task( - hass.services.async_call(DOMAIN, SERVICE_DECREMENT, {ATTR_ENTITY_ID: entity_id}) + await hass.services.async_call( + DOMAIN, SERVICE_DECREMENT, {ATTR_ENTITY_ID: entity_id}, blocking=True ) @@ -110,7 +108,7 @@ async def test_config(hass): assert not await async_setup_component(hass, DOMAIN, {DOMAIN: cfg}) -async def test_set_value(hass): +async def test_set_value(hass, caplog): """Test set_value method.""" assert await async_setup_component( hass, DOMAIN, {DOMAIN: {"test_1": {"initial": 50, "min": 0, "max": 100}}} @@ -120,20 +118,22 @@ async def test_set_value(hass): state = hass.states.get(entity_id) assert 50 == float(state.state) - set_value(hass, entity_id, "30.4") - await hass.async_block_till_done() + await set_value(hass, entity_id, "30.4") state = hass.states.get(entity_id) assert 30.4 == float(state.state) - set_value(hass, entity_id, "70") - await hass.async_block_till_done() + await set_value(hass, entity_id, "70") state = hass.states.get(entity_id) assert 70 == float(state.state) - set_value(hass, entity_id, "110") - await hass.async_block_till_done() + with pytest.raises(vol.Invalid) as excinfo: + await set_value(hass, entity_id, "110") + + assert "Invalid value for input_number.test_1: 110.0 (range 0.0 - 100.0)" in str( + excinfo.value + ) state = hass.states.get(entity_id) assert 70 == float(state.state) @@ -149,13 +149,13 @@ async def test_increment(hass): state = hass.states.get(entity_id) assert 50 == float(state.state) - increment(hass, entity_id) + await increment(hass, entity_id) await hass.async_block_till_done() state = hass.states.get(entity_id) assert 51 == float(state.state) - increment(hass, entity_id) + await increment(hass, entity_id) await hass.async_block_till_done() state = hass.states.get(entity_id) @@ -172,13 +172,13 @@ async def test_decrement(hass): state = hass.states.get(entity_id) assert 50 == float(state.state) - decrement(hass, entity_id) + await decrement(hass, entity_id) await hass.async_block_till_done() state = hass.states.get(entity_id) assert 49 == float(state.state) - decrement(hass, entity_id) + await decrement(hass, entity_id) await hass.async_block_till_done() state = hass.states.get(entity_id)