From f7292d5b00100d04f3a0f967595becb716b45b7c Mon Sep 17 00:00:00 2001 From: Robert Resch Date: Mon, 9 Oct 2023 13:37:52 +0200 Subject: [PATCH] Add check that sensors don't have EntityCategory.CONFIG set (#101471) --- homeassistant/components/nextcloud/sensor.py | 6 ++--- homeassistant/components/sensor/__init__.py | 7 ++++++ tests/components/esphome/test_sensor.py | 4 ++-- tests/components/mqtt/test_common.py | 7 +++--- tests/components/sensor/test_init.py | 23 ++++++++++++++++++++ 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/nextcloud/sensor.py b/homeassistant/components/nextcloud/sensor.py index 0133a9e7f76..16c8adb77ce 100644 --- a/homeassistant/components/nextcloud/sensor.py +++ b/homeassistant/components/nextcloud/sensor.py @@ -348,7 +348,7 @@ SENSORS: Final[list[NextcloudSensorEntityDescription]] = [ key="server_php_max_execution_time", translation_key="nextcloud_server_php_max_execution_time", device_class=SensorDeviceClass.DURATION, - entity_category=EntityCategory.CONFIG, + entity_category=EntityCategory.DIAGNOSTIC, icon="mdi:language-php", native_unit_of_measurement=UnitOfTime.SECONDS, ), @@ -356,7 +356,7 @@ SENSORS: Final[list[NextcloudSensorEntityDescription]] = [ key="server_php_memory_limit", translation_key="nextcloud_server_php_memory_limit", device_class=SensorDeviceClass.DATA_SIZE, - entity_category=EntityCategory.CONFIG, + entity_category=EntityCategory.DIAGNOSTIC, icon="mdi:language-php", native_unit_of_measurement=UnitOfInformation.BYTES, suggested_display_precision=1, @@ -366,7 +366,7 @@ SENSORS: Final[list[NextcloudSensorEntityDescription]] = [ key="server_php_upload_max_filesize", translation_key="nextcloud_server_php_upload_max_filesize", device_class=SensorDeviceClass.DATA_SIZE, - entity_category=EntityCategory.CONFIG, + entity_category=EntityCategory.DIAGNOSTIC, icon="mdi:language-php", native_unit_of_measurement=UnitOfInformation.BYTES, suggested_display_precision=1, diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index 55d2be6dfc6..10bf976f012 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -47,9 +47,11 @@ from homeassistant.const import ( # noqa: F401 DEVICE_CLASS_TIMESTAMP, DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, DEVICE_CLASS_VOLTAGE, + EntityCategory, UnitOfTemperature, ) from homeassistant.core import HomeAssistant, State, callback +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import entity_registry as er from homeassistant.helpers.config_validation import ( PLATFORM_SCHEMA, @@ -251,6 +253,11 @@ class SensorEntity(Entity): async def async_internal_added_to_hass(self) -> None: """Call when the sensor entity is added to hass.""" await super().async_internal_added_to_hass() + if self.entity_category == EntityCategory.CONFIG: + raise HomeAssistantError( + f"Entity {self.entity_id} cannot be added as the entity category is set to config" + ) + if not self.registry_entry: return self._async_read_entity_options() diff --git a/tests/components/esphome/test_sensor.py b/tests/components/esphome/test_sensor.py index e46906ffd33..cf7e2af02d7 100644 --- a/tests/components/esphome/test_sensor.py +++ b/tests/components/esphome/test_sensor.py @@ -97,7 +97,7 @@ async def test_generic_numeric_sensor_with_entity_category_and_icon( key=1, name="my sensor", unique_id="my_sensor", - entity_category=ESPHomeEntityCategory.CONFIG, + entity_category=ESPHomeEntityCategory.DIAGNOSTIC, icon="mdi:leaf", ) ] @@ -117,7 +117,7 @@ async def test_generic_numeric_sensor_with_entity_category_and_icon( entry = entity_reg.async_get("sensor.test_mysensor") assert entry is not None assert entry.unique_id == "my_sensor" - assert entry.entity_category is EntityCategory.CONFIG + assert entry.entity_category is EntityCategory.DIAGNOSTIC async def test_generic_numeric_sensor_state_class_measurement( diff --git a/tests/components/mqtt/test_common.py b/tests/components/mqtt/test_common.py index 64bece5369e..7af7aa34647 100644 --- a/tests/components/mqtt/test_common.py +++ b/tests/components/mqtt/test_common.py @@ -23,6 +23,7 @@ from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_RELOAD, STATE_UNAVAILABLE, + EntityCategory, ) from homeassistant.core import HomeAssistant from homeassistant.generated.mqtt import MQTT @@ -1635,9 +1636,9 @@ async def help_test_entity_category( entry = ent_registry.async_get(entity_id) assert entry is not None and entry.entity_category is None - # Discover an entity with entity category set to "config" + # Discover an entity with entity category set to "diagnostic" unique_id = "veryunique2" - config["entity_category"] = "config" + config["entity_category"] = EntityCategory.DIAGNOSTIC config["unique_id"] = unique_id data = json.dumps(config) async_fire_mqtt_message(hass, f"homeassistant/{domain}/{unique_id}/config", data) @@ -1645,7 +1646,7 @@ async def help_test_entity_category( entity_id = ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, unique_id) assert entity_id is not None and hass.states.get(entity_id) entry = ent_registry.async_get(entity_id) - assert entry is not None and entry.entity_category == "config" + assert entry is not None and entry.entity_category == EntityCategory.DIAGNOSTIC # Discover an entity with entity category set to "no_such_category" unique_id = "veryunique3" diff --git a/tests/components/sensor/test_init.py b/tests/components/sensor/test_init.py index 395f6d41a14..fc714a543bf 100644 --- a/tests/components/sensor/test_init.py +++ b/tests/components/sensor/test_init.py @@ -26,6 +26,7 @@ from homeassistant.const import ( ATTR_UNIT_OF_MEASUREMENT, PERCENTAGE, STATE_UNKNOWN, + EntityCategory, UnitOfEnergy, UnitOfLength, UnitOfMass, @@ -2496,3 +2497,25 @@ def test_device_class_units_state_classes(hass: HomeAssistant) -> None: ) - NON_NUMERIC_DEVICE_CLASSES - {SensorDeviceClass.MONETARY} # DEVICE_CLASS_STATE_CLASSES should include all device classes assert set(DEVICE_CLASS_STATE_CLASSES) == set(SensorDeviceClass) + + +async def test_entity_category_config_raises_error( + hass: HomeAssistant, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test error is raised when entity category is set to config.""" + platform = getattr(hass.components, "test.sensor") + platform.init(empty=True) + platform.ENTITIES["0"] = platform.MockSensor( + name="Test", entity_category=EntityCategory.CONFIG + ) + + assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + await hass.async_block_till_done() + + assert ( + "Entity sensor.test cannot be added as the entity category is set to config" + in caplog.text + ) + + assert not hass.states.get("sensor.test")