From e26a2596afd848a8ebc72efcbbf5fa1583282998 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Thu, 19 Oct 2023 21:14:45 +0200 Subject: [PATCH] Do not fail MQTT setup if climate's configured via yaml can't be validated (#102303) Add climate --- homeassistant/components/mqtt/climate.py | 29 +++++++--------- .../components/mqtt/config_integration.py | 6 +--- tests/components/mqtt/test_climate.py | 33 +++++++++---------- 3 files changed, 27 insertions(+), 41 deletions(-) diff --git a/homeassistant/components/mqtt/climate.py b/homeassistant/components/mqtt/climate.py index 77f28e1b5ca..4437f2a6270 100644 --- a/homeassistant/components/mqtt/climate.py +++ b/homeassistant/components/mqtt/climate.py @@ -3,7 +3,6 @@ from __future__ import annotations from abc import ABC, abstractmethod from collections.abc import Callable -import functools import logging from typing import Any @@ -47,7 +46,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.template import Template -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType +from homeassistant.helpers.typing import ConfigType from homeassistant.util.unit_conversion import TemperatureConverter from . import subscription @@ -85,7 +84,7 @@ from .debug_info import log_messages from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_setup_entry_helper, + async_mqtt_entry_helper, write_state_on_attr_change, ) from .models import ( @@ -399,22 +398,16 @@ async def async_setup_entry( config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: - """Set up MQTT climate device through YAML and through MQTT discovery.""" - setup = functools.partial( - _async_setup_entity, hass, async_add_entities, config_entry=config_entry + """Set up MQTT climate through YAML and through MQTT discovery.""" + await async_mqtt_entry_helper( + hass, + config_entry, + MqttClimate, + climate.DOMAIN, + async_add_entities, + DISCOVERY_SCHEMA, + PLATFORM_SCHEMA_MODERN, ) - await async_setup_entry_helper(hass, climate.DOMAIN, setup, DISCOVERY_SCHEMA) - - -async def _async_setup_entity( - hass: HomeAssistant, - async_add_entities: AddEntitiesCallback, - config: ConfigType, - config_entry: ConfigEntry, - discovery_data: DiscoveryInfoType | None = None, -) -> None: - """Set up the MQTT climate devices.""" - async_add_entities([MqttClimate(hass, config, config_entry, discovery_data)]) class MqttTemperatureControlEntity(MqttEntity, ABC): diff --git a/homeassistant/components/mqtt/config_integration.py b/homeassistant/components/mqtt/config_integration.py index a97a577c0dc..e05056fdb57 100644 --- a/homeassistant/components/mqtt/config_integration.py +++ b/homeassistant/components/mqtt/config_integration.py @@ -16,7 +16,6 @@ from homeassistant.helpers import config_validation as cv from . import ( button as button_platform, - climate as climate_platform, cover as cover_platform, event as event_platform, humidifier as humidifier_platform, @@ -52,10 +51,7 @@ CONFIG_SCHEMA_BASE = vol.Schema( [button_platform.PLATFORM_SCHEMA_MODERN], # type: ignore[has-type] ), Platform.CAMERA.value: vol.All(cv.ensure_list, [dict]), - Platform.CLIMATE.value: vol.All( - cv.ensure_list, - [climate_platform.PLATFORM_SCHEMA_MODERN], # type: ignore[has-type] - ), + Platform.CLIMATE.value: vol.All(cv.ensure_list, [dict]), Platform.COVER.value: vol.All( cv.ensure_list, [cover_platform.PLATFORM_SCHEMA_MODERN], # type: ignore[has-type] diff --git a/tests/components/mqtt/test_climate.py b/tests/components/mqtt/test_climate.py index 9c0adbe2adf..89eaf87fb3a 100644 --- a/tests/components/mqtt/test_climate.py +++ b/tests/components/mqtt/test_climate.py @@ -138,9 +138,8 @@ async def test_preset_none_in_preset_modes( mqtt_mock_entry: MqttMockHAClientGenerator, ) -> None: """Test the preset mode payload reset configuration.""" - with pytest.raises(AssertionError): - await mqtt_mock_entry() - assert "Invalid config for [mqtt]: not a valid value" in caplog.text + assert await mqtt_mock_entry() + assert "not a valid value" in caplog.text @pytest.mark.parametrize( @@ -2448,11 +2447,11 @@ async def test_publishing_with_custom_encoding( @pytest.mark.parametrize( ("hass_config", "valid"), [ - ( + ( # test_valid_humidity_min_max { mqtt.DOMAIN: { climate.DOMAIN: { - "name": "test_valid_humidity_min_max", + "name": "test", "min_humidity": 20, "max_humidity": 80, }, @@ -2460,11 +2459,11 @@ async def test_publishing_with_custom_encoding( }, True, ), - ( + ( # test_invalid_humidity_min_max_1 { mqtt.DOMAIN: { climate.DOMAIN: { - "name": "test_invalid_humidity_min_max_1", + "name": "test", "min_humidity": 0, "max_humidity": 101, }, @@ -2472,11 +2471,11 @@ async def test_publishing_with_custom_encoding( }, False, ), - ( + ( # test_invalid_humidity_min_max_2 { mqtt.DOMAIN: { climate.DOMAIN: { - "name": "test_invalid_humidity_min_max_2", + "name": "test", "max_humidity": 20, "min_humidity": 40, }, @@ -2484,11 +2483,11 @@ async def test_publishing_with_custom_encoding( }, False, ), - ( + ( # test_valid_humidity_state { mqtt.DOMAIN: { climate.DOMAIN: { - "name": "test_valid_humidity_state", + "name": "test", "target_humidity_state_topic": "humidity-state", "target_humidity_command_topic": "humidity-command", }, @@ -2496,11 +2495,11 @@ async def test_publishing_with_custom_encoding( }, True, ), - ( + ( # test_invalid_humidity_state { mqtt.DOMAIN: { climate.DOMAIN: { - "name": "test_invalid_humidity_state", + "name": "test", "target_humidity_state_topic": "humidity-state", }, } @@ -2515,11 +2514,9 @@ async def test_humidity_configuration_validity( valid: bool, ) -> None: """Test the validity of humidity configurations.""" - if valid: - await mqtt_mock_entry() - return - with pytest.raises(AssertionError): - await mqtt_mock_entry() + assert await mqtt_mock_entry() + state = hass.states.get("climate.test") + assert (state is not None) == valid async def test_reloadable(