mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Make config entry disabled_by an enum (#60445)
* Make config entry disabled_by an enum * Update homeassistant/config_entries.py Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
aa83b0388a
commit
7db3246de4
@ -304,7 +304,8 @@ async def config_entry_update(hass, connection, msg):
|
|||||||
"type": "config_entries/disable",
|
"type": "config_entries/disable",
|
||||||
"entry_id": str,
|
"entry_id": str,
|
||||||
# We only allow setting disabled_by user via API.
|
# We only allow setting disabled_by user via API.
|
||||||
"disabled_by": vol.Any(config_entries.DISABLED_USER, None),
|
# No Enum support like this in voluptuous, use .value
|
||||||
|
"disabled_by": vol.Any(config_entries.ConfigEntryDisabler.USER.value, None),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
async def config_entry_disable(hass, connection, msg):
|
async def config_entry_disable(hass, connection, msg):
|
||||||
|
@ -13,6 +13,7 @@ from typing import TYPE_CHECKING, Any, Callable, Optional, cast
|
|||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
from homeassistant import data_entry_flow, loader
|
from homeassistant import data_entry_flow, loader
|
||||||
|
from homeassistant.backports.enum import StrEnum
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.core import CALLBACK_TYPE, CoreState, HomeAssistant, callback
|
from homeassistant.core import CALLBACK_TYPE, CoreState, HomeAssistant, callback
|
||||||
from homeassistant.exceptions import (
|
from homeassistant.exceptions import (
|
||||||
@ -22,6 +23,7 @@ from homeassistant.exceptions import (
|
|||||||
)
|
)
|
||||||
from homeassistant.helpers import device_registry, entity_registry
|
from homeassistant.helpers import device_registry, entity_registry
|
||||||
from homeassistant.helpers.event import Event
|
from homeassistant.helpers.event import Event
|
||||||
|
from homeassistant.helpers.frame import report
|
||||||
from homeassistant.helpers.typing import (
|
from homeassistant.helpers.typing import (
|
||||||
UNDEFINED,
|
UNDEFINED,
|
||||||
ConfigType,
|
ConfigType,
|
||||||
@ -128,7 +130,15 @@ RECONFIGURE_NOTIFICATION_ID = "config_entry_reconfigure"
|
|||||||
|
|
||||||
EVENT_FLOW_DISCOVERED = "config_entry_discovered"
|
EVENT_FLOW_DISCOVERED = "config_entry_discovered"
|
||||||
|
|
||||||
DISABLED_USER = "user"
|
|
||||||
|
class ConfigEntryDisabler(StrEnum):
|
||||||
|
"""What disabled a config entry."""
|
||||||
|
|
||||||
|
USER = "user"
|
||||||
|
|
||||||
|
|
||||||
|
# DISABLED_* is deprecated, to be removed in 2022.3
|
||||||
|
DISABLED_USER = ConfigEntryDisabler.USER.value
|
||||||
|
|
||||||
RELOAD_AFTER_UPDATE_DELAY = 30
|
RELOAD_AFTER_UPDATE_DELAY = 30
|
||||||
|
|
||||||
@ -195,7 +205,7 @@ class ConfigEntry:
|
|||||||
unique_id: str | None = None,
|
unique_id: str | None = None,
|
||||||
entry_id: str | None = None,
|
entry_id: str | None = None,
|
||||||
state: ConfigEntryState = ConfigEntryState.NOT_LOADED,
|
state: ConfigEntryState = ConfigEntryState.NOT_LOADED,
|
||||||
disabled_by: str | None = None,
|
disabled_by: ConfigEntryDisabler | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize a config entry."""
|
"""Initialize a config entry."""
|
||||||
# Unique id of the config entry
|
# Unique id of the config entry
|
||||||
@ -237,6 +247,16 @@ class ConfigEntry:
|
|||||||
self.unique_id = unique_id
|
self.unique_id = unique_id
|
||||||
|
|
||||||
# Config entry is disabled
|
# Config entry is disabled
|
||||||
|
if isinstance(disabled_by, str) and not isinstance(
|
||||||
|
disabled_by, ConfigEntryDisabler
|
||||||
|
):
|
||||||
|
report( # type: ignore[unreachable]
|
||||||
|
"uses str for config entry disabled_by. This is deprecated and will "
|
||||||
|
"stop working in Home Assistant 2022.3, it should be updated to use "
|
||||||
|
"ConfigEntryDisabler instead",
|
||||||
|
error_if_core=False,
|
||||||
|
)
|
||||||
|
disabled_by = ConfigEntryDisabler(disabled_by)
|
||||||
self.disabled_by = disabled_by
|
self.disabled_by = disabled_by
|
||||||
|
|
||||||
# Supports unload
|
# Supports unload
|
||||||
@ -924,7 +944,9 @@ class ConfigEntries:
|
|||||||
# New in 0.104
|
# New in 0.104
|
||||||
unique_id=entry.get("unique_id"),
|
unique_id=entry.get("unique_id"),
|
||||||
# New in 2021.3
|
# New in 2021.3
|
||||||
disabled_by=entry.get("disabled_by"),
|
disabled_by=ConfigEntryDisabler(entry["disabled_by"])
|
||||||
|
if entry.get("disabled_by")
|
||||||
|
else None,
|
||||||
# New in 2021.6
|
# New in 2021.6
|
||||||
pref_disable_new_entities=pref_disable_new_entities,
|
pref_disable_new_entities=pref_disable_new_entities,
|
||||||
pref_disable_polling=entry.get("pref_disable_polling"),
|
pref_disable_polling=entry.get("pref_disable_polling"),
|
||||||
@ -985,7 +1007,7 @@ class ConfigEntries:
|
|||||||
return await self.async_setup(entry_id)
|
return await self.async_setup(entry_id)
|
||||||
|
|
||||||
async def async_set_disabled_by(
|
async def async_set_disabled_by(
|
||||||
self, entry_id: str, disabled_by: str | None
|
self, entry_id: str, disabled_by: ConfigEntryDisabler | None
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Disable an entry.
|
"""Disable an entry.
|
||||||
|
|
||||||
@ -994,7 +1016,18 @@ class ConfigEntries:
|
|||||||
if (entry := self.async_get_entry(entry_id)) is None:
|
if (entry := self.async_get_entry(entry_id)) is None:
|
||||||
raise UnknownEntry
|
raise UnknownEntry
|
||||||
|
|
||||||
if entry.disabled_by == disabled_by:
|
if isinstance(disabled_by, str) and not isinstance(
|
||||||
|
disabled_by, ConfigEntryDisabler
|
||||||
|
):
|
||||||
|
report( # type: ignore[unreachable]
|
||||||
|
"uses str for config entry disabled_by. This is deprecated and will "
|
||||||
|
"stop working in Home Assistant 2022.3, it should be updated to use "
|
||||||
|
"ConfigEntryDisabler instead",
|
||||||
|
error_if_core=False,
|
||||||
|
)
|
||||||
|
disabled_by = ConfigEntryDisabler(disabled_by)
|
||||||
|
|
||||||
|
if entry.disabled_by is disabled_by:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
entry.disabled_by = disabled_by
|
entry.disabled_by = disabled_by
|
||||||
|
@ -79,7 +79,7 @@ async def test_get_entries(hass, client):
|
|||||||
domain="comp3",
|
domain="comp3",
|
||||||
title="Test 3",
|
title="Test 3",
|
||||||
source="bla3",
|
source="bla3",
|
||||||
disabled_by=core_ce.DISABLED_USER,
|
disabled_by=core_ce.ConfigEntryDisabler.USER,
|
||||||
).add_to_hass(hass)
|
).add_to_hass(hass)
|
||||||
|
|
||||||
resp = await client.get("/api/config/config_entries/entry")
|
resp = await client.get("/api/config/config_entries/entry")
|
||||||
@ -121,7 +121,7 @@ async def test_get_entries(hass, client):
|
|||||||
"supports_unload": False,
|
"supports_unload": False,
|
||||||
"pref_disable_new_entities": False,
|
"pref_disable_new_entities": False,
|
||||||
"pref_disable_polling": False,
|
"pref_disable_polling": False,
|
||||||
"disabled_by": core_ce.DISABLED_USER,
|
"disabled_by": core_ce.ConfigEntryDisabler.USER,
|
||||||
"reason": None,
|
"reason": None,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -877,14 +877,14 @@ async def test_disable_entry(hass, hass_ws_client):
|
|||||||
"id": 5,
|
"id": 5,
|
||||||
"type": "config_entries/disable",
|
"type": "config_entries/disable",
|
||||||
"entry_id": entry.entry_id,
|
"entry_id": entry.entry_id,
|
||||||
"disabled_by": core_ce.DISABLED_USER,
|
"disabled_by": core_ce.ConfigEntryDisabler.USER,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
response = await ws_client.receive_json()
|
response = await ws_client.receive_json()
|
||||||
|
|
||||||
assert response["success"]
|
assert response["success"]
|
||||||
assert response["result"] == {"require_restart": True}
|
assert response["result"] == {"require_restart": True}
|
||||||
assert entry.disabled_by == core_ce.DISABLED_USER
|
assert entry.disabled_by is core_ce.ConfigEntryDisabler.USER
|
||||||
assert entry.state is core_ce.ConfigEntryState.FAILED_UNLOAD
|
assert entry.state is core_ce.ConfigEntryState.FAILED_UNLOAD
|
||||||
|
|
||||||
# Enable
|
# Enable
|
||||||
@ -930,7 +930,7 @@ async def test_disable_entry_nonexisting(hass, hass_ws_client):
|
|||||||
"id": 5,
|
"id": 5,
|
||||||
"type": "config_entries/disable",
|
"type": "config_entries/disable",
|
||||||
"entry_id": "non_existing",
|
"entry_id": "non_existing",
|
||||||
"disabled_by": core_ce.DISABLED_USER,
|
"disabled_by": core_ce.ConfigEntryDisabler.USER,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
response = await ws_client.receive_json()
|
response = await ws_client.receive_json()
|
||||||
|
@ -10,7 +10,7 @@ from zwave_js_server.model.node import Node
|
|||||||
from homeassistant.components.hassio.handler import HassioAPIError
|
from homeassistant.components.hassio.handler import HassioAPIError
|
||||||
from homeassistant.components.zwave_js.const import DOMAIN
|
from homeassistant.components.zwave_js.const import DOMAIN
|
||||||
from homeassistant.components.zwave_js.helpers import get_device_id
|
from homeassistant.components.zwave_js.helpers import get_device_id
|
||||||
from homeassistant.config_entries import DISABLED_USER, ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryDisabler, ConfigEntryState
|
||||||
from homeassistant.const import STATE_UNAVAILABLE
|
from homeassistant.const import STATE_UNAVAILABLE
|
||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
|
|
||||||
@ -554,7 +554,9 @@ async def test_stop_addon(
|
|||||||
|
|
||||||
assert entry.state is ConfigEntryState.LOADED
|
assert entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
await hass.config_entries.async_set_disabled_by(entry.entry_id, DISABLED_USER)
|
await hass.config_entries.async_set_disabled_by(
|
||||||
|
entry.entry_id, ConfigEntryDisabler.USER
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert entry.state == entry_state
|
assert entry.state == entry_state
|
||||||
|
@ -1342,7 +1342,7 @@ async def test_disable_config_entry_disables_devices(hass, registry):
|
|||||||
assert entry2.disabled
|
assert entry2.disabled
|
||||||
|
|
||||||
await hass.config_entries.async_set_disabled_by(
|
await hass.config_entries.async_set_disabled_by(
|
||||||
config_entry.entry_id, config_entries.DISABLED_USER
|
config_entry.entry_id, config_entries.ConfigEntryDisabler.USER
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
@ -1382,7 +1382,7 @@ async def test_only_disable_device_if_all_config_entries_are_disabled(hass, regi
|
|||||||
assert not entry1.disabled
|
assert not entry1.disabled
|
||||||
|
|
||||||
await hass.config_entries.async_set_disabled_by(
|
await hass.config_entries.async_set_disabled_by(
|
||||||
config_entry1.entry_id, config_entries.DISABLED_USER
|
config_entry1.entry_id, config_entries.ConfigEntryDisabler.USER
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
@ -1390,7 +1390,7 @@ async def test_only_disable_device_if_all_config_entries_are_disabled(hass, regi
|
|||||||
assert not entry1.disabled
|
assert not entry1.disabled
|
||||||
|
|
||||||
await hass.config_entries.async_set_disabled_by(
|
await hass.config_entries.async_set_disabled_by(
|
||||||
config_entry2.entry_id, config_entries.DISABLED_USER
|
config_entry2.entry_id, config_entries.ConfigEntryDisabler.USER
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -919,7 +919,7 @@ async def test_disable_config_entry_disables_entities(hass, registry):
|
|||||||
assert entry3.disabled
|
assert entry3.disabled
|
||||||
|
|
||||||
await hass.config_entries.async_set_disabled_by(
|
await hass.config_entries.async_set_disabled_by(
|
||||||
config_entry.entry_id, config_entries.DISABLED_USER
|
config_entry.entry_id, config_entries.ConfigEntryDisabler.USER
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -529,7 +529,7 @@ async def test_domains_gets_domains_excludes_ignore_and_disabled(manager):
|
|||||||
).add_to_manager(manager)
|
).add_to_manager(manager)
|
||||||
MockConfigEntry(domain="test3").add_to_manager(manager)
|
MockConfigEntry(domain="test3").add_to_manager(manager)
|
||||||
MockConfigEntry(
|
MockConfigEntry(
|
||||||
domain="disabled", disabled_by=config_entries.DISABLED_USER
|
domain="disabled", disabled_by=config_entries.ConfigEntryDisabler.USER
|
||||||
).add_to_manager(manager)
|
).add_to_manager(manager)
|
||||||
assert manager.async_domains() == ["test", "test2", "test3"]
|
assert manager.async_domains() == ["test", "test2", "test3"]
|
||||||
assert manager.async_domains(include_ignore=False) == ["test", "test2", "test3"]
|
assert manager.async_domains(include_ignore=False) == ["test", "test2", "test3"]
|
||||||
@ -1323,7 +1323,7 @@ async def test_entry_disable_succeed(hass, manager):
|
|||||||
|
|
||||||
# Disable
|
# Disable
|
||||||
assert await manager.async_set_disabled_by(
|
assert await manager.async_set_disabled_by(
|
||||||
entry.entry_id, config_entries.DISABLED_USER
|
entry.entry_id, config_entries.ConfigEntryDisabler.USER
|
||||||
)
|
)
|
||||||
assert len(async_unload_entry.mock_calls) == 1
|
assert len(async_unload_entry.mock_calls) == 1
|
||||||
assert len(async_setup.mock_calls) == 0
|
assert len(async_setup.mock_calls) == 0
|
||||||
@ -1358,7 +1358,7 @@ async def test_entry_disable_without_reload_support(hass, manager):
|
|||||||
|
|
||||||
# Disable
|
# Disable
|
||||||
assert not await manager.async_set_disabled_by(
|
assert not await manager.async_set_disabled_by(
|
||||||
entry.entry_id, config_entries.DISABLED_USER
|
entry.entry_id, config_entries.ConfigEntryDisabler.USER
|
||||||
)
|
)
|
||||||
assert len(async_setup.mock_calls) == 0
|
assert len(async_setup.mock_calls) == 0
|
||||||
assert len(async_setup_entry.mock_calls) == 0
|
assert len(async_setup_entry.mock_calls) == 0
|
||||||
@ -1374,7 +1374,9 @@ async def test_entry_disable_without_reload_support(hass, manager):
|
|||||||
|
|
||||||
async def test_entry_enable_without_reload_support(hass, manager):
|
async def test_entry_enable_without_reload_support(hass, manager):
|
||||||
"""Test that we can disable an entry without reload support."""
|
"""Test that we can disable an entry without reload support."""
|
||||||
entry = MockConfigEntry(domain="comp", disabled_by=config_entries.DISABLED_USER)
|
entry = MockConfigEntry(
|
||||||
|
domain="comp", disabled_by=config_entries.ConfigEntryDisabler.USER
|
||||||
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
async_setup = AsyncMock(return_value=True)
|
async_setup = AsyncMock(return_value=True)
|
||||||
@ -1398,7 +1400,7 @@ async def test_entry_enable_without_reload_support(hass, manager):
|
|||||||
|
|
||||||
# Disable
|
# Disable
|
||||||
assert not await manager.async_set_disabled_by(
|
assert not await manager.async_set_disabled_by(
|
||||||
entry.entry_id, config_entries.DISABLED_USER
|
entry.entry_id, config_entries.ConfigEntryDisabler.USER
|
||||||
)
|
)
|
||||||
assert len(async_setup.mock_calls) == 1
|
assert len(async_setup.mock_calls) == 1
|
||||||
assert len(async_setup_entry.mock_calls) == 1
|
assert len(async_setup_entry.mock_calls) == 1
|
||||||
@ -2966,3 +2968,21 @@ async def test_loading_old_data(hass, hass_storage):
|
|||||||
assert entry.title == "Mock title"
|
assert entry.title == "Mock title"
|
||||||
assert entry.data == {"my": "data"}
|
assert entry.data == {"my": "data"}
|
||||||
assert entry.pref_disable_new_entities is True
|
assert entry.pref_disable_new_entities is True
|
||||||
|
|
||||||
|
|
||||||
|
async def test_deprecated_disabled_by_str_ctor(hass, caplog):
|
||||||
|
"""Test deprecated str disabled_by constructor enumizes and logs a warning."""
|
||||||
|
entry = MockConfigEntry(disabled_by=config_entries.ConfigEntryDisabler.USER.value)
|
||||||
|
assert entry.disabled_by is config_entries.ConfigEntryDisabler.USER
|
||||||
|
assert " str for config entry disabled_by. This is deprecated " in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_deprecated_disabled_by_str_set(hass, manager, caplog):
|
||||||
|
"""Test deprecated str set disabled_by enumizes and logs a warning."""
|
||||||
|
entry = MockConfigEntry()
|
||||||
|
entry.add_to_manager(manager)
|
||||||
|
assert await manager.async_set_disabled_by(
|
||||||
|
entry.entry_id, config_entries.ConfigEntryDisabler.USER.value
|
||||||
|
)
|
||||||
|
assert entry.disabled_by is config_entries.ConfigEntryDisabler.USER
|
||||||
|
assert " str for config entry disabled_by. This is deprecated " in caplog.text
|
||||||
|
Loading…
x
Reference in New Issue
Block a user