mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 20:27:08 +00:00
Deprecate sensors in Habitica integration (#134036)
* Deprecate sensors * move to setup, remove disabled * changes * add breaking version to string * fixes * fix entity id in tests
This commit is contained in:
parent
8d38279993
commit
cdcc7dbbe8
@ -17,16 +17,26 @@ from habiticalib import (
|
||||
deserialize_task,
|
||||
)
|
||||
|
||||
from homeassistant.components.automation import automations_with_entity
|
||||
from homeassistant.components.script import scripts_with_entity
|
||||
from homeassistant.components.sensor import (
|
||||
DOMAIN as SENSOR_DOMAIN,
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorEntityDescription,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.issue_registry import (
|
||||
IssueSeverity,
|
||||
async_create_issue,
|
||||
async_delete_issue,
|
||||
)
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from .const import ASSETS_URL
|
||||
from .const import ASSETS_URL, DOMAIN
|
||||
from .coordinator import HabiticaDataUpdateCoordinator
|
||||
from .entity import HabiticaBase
|
||||
from .types import HabiticaConfigEntry
|
||||
from .util import get_attribute_points, get_attributes_total, inventory_list
|
||||
@ -269,6 +279,13 @@ TASK_SENSOR_DESCRIPTION: tuple[HabiticaTaskSensorEntityDescription, ...] = (
|
||||
)
|
||||
|
||||
|
||||
def entity_used_in(hass: HomeAssistant, entity_id: str) -> list[str]:
|
||||
"""Get list of related automations and scripts."""
|
||||
used_in = automations_with_entity(hass, entity_id)
|
||||
used_in += scripts_with_entity(hass, entity_id)
|
||||
return used_in
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: HabiticaConfigEntry,
|
||||
@ -277,14 +294,58 @@ async def async_setup_entry(
|
||||
"""Set up the habitica sensors."""
|
||||
|
||||
coordinator = config_entry.runtime_data
|
||||
ent_reg = er.async_get(hass)
|
||||
entities: list[SensorEntity] = []
|
||||
description: SensorEntityDescription
|
||||
|
||||
def add_deprecated_entity(
|
||||
description: SensorEntityDescription,
|
||||
entity_cls: Callable[
|
||||
[HabiticaDataUpdateCoordinator, SensorEntityDescription], SensorEntity
|
||||
],
|
||||
) -> None:
|
||||
"""Add deprecated entities."""
|
||||
if entity_id := ent_reg.async_get_entity_id(
|
||||
SENSOR_DOMAIN,
|
||||
DOMAIN,
|
||||
f"{config_entry.unique_id}_{description.key}",
|
||||
):
|
||||
entity_entry = ent_reg.async_get(entity_id)
|
||||
if entity_entry and entity_entry.disabled:
|
||||
ent_reg.async_remove(entity_id)
|
||||
async_delete_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
f"deprecated_entity_{description.key}",
|
||||
)
|
||||
elif entity_entry:
|
||||
entities.append(entity_cls(coordinator, description))
|
||||
if entity_used_in(hass, entity_id):
|
||||
async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
f"deprecated_entity_{description.key}",
|
||||
breaks_in_ha_version="2025.8.0",
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_entity",
|
||||
translation_placeholders={
|
||||
"name": str(
|
||||
entity_entry.name or entity_entry.original_name
|
||||
),
|
||||
"entity": entity_id,
|
||||
},
|
||||
)
|
||||
|
||||
for description in SENSOR_DESCRIPTIONS:
|
||||
if description.key is HabiticaSensorEntity.HEALTH_MAX:
|
||||
add_deprecated_entity(description, HabiticaSensor)
|
||||
else:
|
||||
entities.append(HabiticaSensor(coordinator, description))
|
||||
|
||||
for description in TASK_SENSOR_DESCRIPTION:
|
||||
add_deprecated_entity(description, HabiticaTaskSensor)
|
||||
|
||||
entities: list[SensorEntity] = [
|
||||
HabiticaSensor(coordinator, description) for description in SENSOR_DESCRIPTIONS
|
||||
]
|
||||
entities.extend(
|
||||
HabiticaTaskSensor(coordinator, description)
|
||||
for description in TASK_SENSOR_DESCRIPTION
|
||||
)
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
|
@ -421,6 +421,10 @@
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_entity": {
|
||||
"title": "The Habitica {name} entity is deprecated",
|
||||
"description": "The Habitica entity `{entity}` is deprecated and will be removed in a future release.\nPlease update your automations and scripts, disable `{entity}` and reload the integration/restart Home Assistant to fix this issue."
|
||||
},
|
||||
"deprecated_api_call": {
|
||||
"title": "The Habitica action habitica.api_call is deprecated",
|
||||
"description": "The Habitica action `habitica.api_call` is deprecated and will be removed in Home Assistant 2025.5.0.\n\nPlease update your automations and scripts to use other Habitica actions and entities."
|
||||
|
@ -23,9 +23,6 @@ from dateutil.rrule import (
|
||||
)
|
||||
from habiticalib import ContentData, Frequency, TaskData, UserData
|
||||
|
||||
from homeassistant.components.automation import automations_with_entity
|
||||
from homeassistant.components.script import scripts_with_entity
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
|
||||
@ -59,13 +56,6 @@ def next_due_date(task: TaskData, today: datetime.datetime) -> datetime.date | N
|
||||
return dt_util.as_local(task.nextDue[0]).date()
|
||||
|
||||
|
||||
def entity_used_in(hass: HomeAssistant, entity_id: str) -> list[str]:
|
||||
"""Get list of related automations and scripts."""
|
||||
used_in = automations_with_entity(hass, entity_id)
|
||||
used_in += scripts_with_entity(hass, entity_id)
|
||||
return used_in
|
||||
|
||||
|
||||
FREQUENCY_MAP = {"daily": DAILY, "weekly": WEEKLY, "monthly": MONTHLY, "yearly": YEARLY}
|
||||
WEEKDAY_MAP = {"m": MO, "t": TU, "w": WE, "th": TH, "f": FR, "s": SA, "su": SU}
|
||||
|
||||
|
@ -6,10 +6,13 @@ from unittest.mock import patch
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.habitica.const import DOMAIN
|
||||
from homeassistant.components.habitica.sensor import HabiticaSensorEntity
|
||||
from homeassistant.components.sensor.const import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
@ -33,6 +36,19 @@ async def test_sensors(
|
||||
) -> None:
|
||||
"""Test setup of the Habitica sensor platform."""
|
||||
|
||||
for entity in (
|
||||
("test_user_habits", "habits"),
|
||||
("test_user_rewards", "rewards"),
|
||||
("test_user_max_health", "health_max"),
|
||||
):
|
||||
entity_registry.async_get_or_create(
|
||||
SENSOR_DOMAIN,
|
||||
DOMAIN,
|
||||
f"a380546a-94be-4b8e-8a0b-23e0d5c03303_{entity[1]}",
|
||||
suggested_object_id=entity[0],
|
||||
disabled_by=None,
|
||||
)
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -40,3 +56,96 @@ async def test_sensors(
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("entity_id", "key"),
|
||||
[
|
||||
("test_user_habits", HabiticaSensorEntity.HABITS),
|
||||
("test_user_rewards", HabiticaSensorEntity.REWARDS),
|
||||
("test_user_max_health", HabiticaSensorEntity.HEALTH_MAX),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("habitica", "entity_registry_enabled_by_default")
|
||||
async def test_sensor_deprecation_issue(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
entity_id: str,
|
||||
key: HabiticaSensorEntity,
|
||||
) -> None:
|
||||
"""Test sensor deprecation issue."""
|
||||
entity_registry.async_get_or_create(
|
||||
SENSOR_DOMAIN,
|
||||
DOMAIN,
|
||||
f"a380546a-94be-4b8e-8a0b-23e0d5c03303_{key}",
|
||||
suggested_object_id=entity_id,
|
||||
disabled_by=None,
|
||||
)
|
||||
|
||||
assert entity_registry is not None
|
||||
with patch(
|
||||
"homeassistant.components.habitica.sensor.entity_used_in", return_value=True
|
||||
):
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
assert entity_registry.async_get(f"sensor.{entity_id}") is not None
|
||||
assert issue_registry.async_get_issue(
|
||||
domain=DOMAIN,
|
||||
issue_id=f"deprecated_entity_{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("entity_id", "key"),
|
||||
[
|
||||
("test_user_habits", HabiticaSensorEntity.HABITS),
|
||||
("test_user_rewards", HabiticaSensorEntity.REWARDS),
|
||||
("test_user_max_health", HabiticaSensorEntity.HEALTH_MAX),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("habitica", "entity_registry_enabled_by_default")
|
||||
async def test_sensor_deprecation_delete_disabled(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
entity_id: str,
|
||||
key: HabiticaSensorEntity,
|
||||
) -> None:
|
||||
"""Test sensor deletion ."""
|
||||
|
||||
entity_registry.async_get_or_create(
|
||||
SENSOR_DOMAIN,
|
||||
DOMAIN,
|
||||
f"a380546a-94be-4b8e-8a0b-23e0d5c03303_{key}",
|
||||
suggested_object_id=entity_id,
|
||||
disabled_by=er.RegistryEntryDisabler.USER,
|
||||
)
|
||||
|
||||
assert entity_registry is not None
|
||||
with patch(
|
||||
"homeassistant.components.habitica.sensor.entity_used_in", return_value=True
|
||||
):
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
assert (
|
||||
issue_registry.async_get_issue(
|
||||
domain=DOMAIN,
|
||||
issue_id=f"deprecated_entity_{key}",
|
||||
)
|
||||
is None
|
||||
)
|
||||
|
||||
assert entity_registry.async_get(f"sensor.{entity_id}") is None
|
||||
|
Loading…
x
Reference in New Issue
Block a user