Skip to content

Commit 818b7bb

Browse files
authored
Prevent overriding default values when restoring descriptions in passive bluetooth update processor (home-assistant#156044)
1 parent a265ecf commit 818b7bb

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

homeassistant/components/bluetooth/passive_update_processor.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ def deserialize_entity_description(
9999
descriptions_class = descriptions_class._dataclass # noqa: SLF001
100100
for field in cached_fields(descriptions_class):
101101
field_name = field.name
102+
# Only set fields that are in the data
103+
# otherwise we would override default values with None
104+
# causing side effects
105+
if field_name not in data:
106+
continue
107+
102108
# It would be nice if field.type returned the actual
103109
# type instead of a str so we could avoid writing this
104110
# out, but it doesn't. If we end up using this in more

tests/components/bluetooth/test_passive_update_processor.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,19 @@
3131
PassiveBluetoothEntityKey,
3232
PassiveBluetoothProcessorCoordinator,
3333
PassiveBluetoothProcessorEntity,
34+
deserialize_entity_description,
3435
)
3536
from homeassistant.components.sensor import (
3637
DOMAIN as SENSOR_DOMAIN,
3738
SensorDeviceClass,
3839
SensorEntityDescription,
40+
SensorStateClass,
3941
)
4042
from homeassistant.config_entries import current_entry
4143
from homeassistant.const import UnitOfTemperature
4244
from homeassistant.core import CoreState, HomeAssistant, callback
4345
from homeassistant.helpers.device_registry import DeviceInfo
46+
from homeassistant.helpers.entity import EntityDescription
4447
from homeassistant.helpers.typing import UNDEFINED
4548
from homeassistant.setup import async_setup_component
4649
from homeassistant.util import dt as dt_util
@@ -1920,3 +1923,55 @@ def _mock_update_method(
19201923
assert sensor_entity.translation_key is None
19211924

19221925
cancel_coordinator()
1926+
1927+
1928+
@pytest.mark.parametrize(
1929+
("description_type", "description_dict", "expected_description"),
1930+
[
1931+
(
1932+
SensorEntityDescription,
1933+
{
1934+
"key": "humidity",
1935+
"native_unit_of_measurement": "%",
1936+
"device_class": "humidity",
1937+
"state_class": "measurement",
1938+
},
1939+
SensorEntityDescription(
1940+
key="humidity",
1941+
native_unit_of_measurement="%",
1942+
device_class=SensorDeviceClass.HUMIDITY,
1943+
state_class=SensorStateClass.MEASUREMENT,
1944+
),
1945+
),
1946+
(
1947+
BinarySensorEntityDescription,
1948+
{
1949+
"key": "motion",
1950+
"device_class": "motion",
1951+
},
1952+
BinarySensorEntityDescription(
1953+
key="motion",
1954+
device_class=BinarySensorDeviceClass.MOTION,
1955+
),
1956+
),
1957+
(
1958+
SensorEntityDescription,
1959+
{
1960+
"key": "temperature",
1961+
"name": None,
1962+
},
1963+
SensorEntityDescription(
1964+
key="temperature",
1965+
name=None,
1966+
),
1967+
),
1968+
],
1969+
)
1970+
def test_deserialize_entity_description(
1971+
description_type: type[EntityDescription],
1972+
description_dict: dict[str, Any],
1973+
expected_description: EntityDescription,
1974+
) -> None:
1975+
"""Test deserializing an entity description."""
1976+
description = deserialize_entity_description(description_type, description_dict)
1977+
assert description == expected_description

0 commit comments

Comments
 (0)