mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
2024.10.1 (#127566)
This commit is contained in:
commit
2182bc3af2
@ -14,6 +14,6 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/cast",
|
"documentation": "https://www.home-assistant.io/integrations/cast",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["casttube", "pychromecast"],
|
"loggers": ["casttube", "pychromecast"],
|
||||||
"requirements": ["PyChromecast==14.0.2"],
|
"requirements": ["PyChromecast==14.0.1"],
|
||||||
"zeroconf": ["_googlecast._tcp.local."]
|
"zeroconf": ["_googlecast._tcp.local."]
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/matrix",
|
"documentation": "https://www.home-assistant.io/integrations/matrix",
|
||||||
"iot_class": "cloud_push",
|
"iot_class": "cloud_push",
|
||||||
"loggers": ["matrix_client"],
|
"loggers": ["matrix_client"],
|
||||||
"requirements": ["matrix-nio==0.25.1", "Pillow==10.4.0"]
|
"requirements": ["matrix-nio==0.25.2", "Pillow==10.4.0"]
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/mealie",
|
"documentation": "https://www.home-assistant.io/integrations/mealie",
|
||||||
"integration_type": "service",
|
"integration_type": "service",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"requirements": ["aiomealie==0.9.2"]
|
"requirements": ["aiomealie==0.9.3"]
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ from nyt_games import NYTGamesClient
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_TOKEN, Platform
|
from homeassistant.const import CONF_TOKEN, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_create_clientsession
|
||||||
|
|
||||||
from .coordinator import NYTGamesCoordinator
|
from .coordinator import NYTGamesCoordinator
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: NYTGamesConfigEntry) ->
|
|||||||
"""Set up NYTGames from a config entry."""
|
"""Set up NYTGames from a config entry."""
|
||||||
|
|
||||||
client = NYTGamesClient(
|
client = NYTGamesClient(
|
||||||
entry.data[CONF_TOKEN], session=async_get_clientsession(hass)
|
entry.data[CONF_TOKEN], session=async_create_clientsession(hass)
|
||||||
)
|
)
|
||||||
|
|
||||||
coordinator = NYTGamesCoordinator(hass, client)
|
coordinator = NYTGamesCoordinator(hass, client)
|
||||||
|
@ -7,7 +7,7 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||||
from homeassistant.const import CONF_TOKEN
|
from homeassistant.const import CONF_TOKEN
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_create_clientsession
|
||||||
|
|
||||||
from .const import DOMAIN, LOGGER
|
from .const import DOMAIN, LOGGER
|
||||||
|
|
||||||
@ -21,8 +21,9 @@ class NYTGamesConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
"""Handle a flow initialized by the user."""
|
"""Handle a flow initialized by the user."""
|
||||||
errors: dict[str, str] = {}
|
errors: dict[str, str] = {}
|
||||||
if user_input:
|
if user_input:
|
||||||
session = async_get_clientsession(self.hass)
|
session = async_create_clientsession(self.hass)
|
||||||
client = NYTGamesClient(user_input[CONF_TOKEN], session=session)
|
token = user_input[CONF_TOKEN].strip()
|
||||||
|
client = NYTGamesClient(token, session=session)
|
||||||
try:
|
try:
|
||||||
user_id = await client.get_user_id()
|
user_id = await client.get_user_id()
|
||||||
except NYTGamesAuthenticationError:
|
except NYTGamesAuthenticationError:
|
||||||
@ -35,7 +36,9 @@ class NYTGamesConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
else:
|
else:
|
||||||
await self.async_set_unique_id(str(user_id))
|
await self.async_set_unique_id(str(user_id))
|
||||||
self._abort_if_unique_id_configured()
|
self._abort_if_unique_id_configured()
|
||||||
return self.async_create_entry(title="NYT Games", data=user_input)
|
return self.async_create_entry(
|
||||||
|
title="NYT Games", data={CONF_TOKEN: token}
|
||||||
|
)
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="user",
|
step_id="user",
|
||||||
data_schema=vol.Schema({vol.Required(CONF_TOKEN): str}),
|
data_schema=vol.Schema({vol.Required(CONF_TOKEN): str}),
|
||||||
|
@ -12,7 +12,7 @@ from homeassistant.exceptions import ConfigEntryNotReady
|
|||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
|
||||||
from .const import ACCOUNT_HASH, DOMAIN
|
from .const import ACCOUNT_HASH, DOMAIN, UPDATE_INTERVAL
|
||||||
from .coordinator import RitualsDataUpdateCoordinator
|
from .coordinator import RitualsDataUpdateCoordinator
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
@ -37,9 +37,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
# Migrate old unique_ids to the new format
|
# Migrate old unique_ids to the new format
|
||||||
async_migrate_entities_unique_ids(hass, entry, account_devices)
|
async_migrate_entities_unique_ids(hass, entry, account_devices)
|
||||||
|
|
||||||
|
# The API provided by Rituals is currently rate limited to 30 requests
|
||||||
|
# per hour per IP address. To avoid hitting this limit, we will adjust
|
||||||
|
# the polling interval based on the number of diffusers one has.
|
||||||
|
update_interval = UPDATE_INTERVAL * len(account_devices)
|
||||||
|
|
||||||
# Create a coordinator for each diffuser
|
# Create a coordinator for each diffuser
|
||||||
coordinators = {
|
coordinators = {
|
||||||
diffuser.hublot: RitualsDataUpdateCoordinator(hass, diffuser)
|
diffuser.hublot: RitualsDataUpdateCoordinator(hass, diffuser, update_interval)
|
||||||
for diffuser in account_devices
|
for diffuser in account_devices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ class RitualsPerfumeGenieConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
try:
|
try:
|
||||||
await account.authenticate()
|
await account.authenticate()
|
||||||
except ClientResponseError:
|
except ClientResponseError:
|
||||||
|
_LOGGER.exception("Unexpected response")
|
||||||
errors["base"] = "cannot_connect"
|
errors["base"] = "cannot_connect"
|
||||||
except AuthenticationException:
|
except AuthenticationException:
|
||||||
errors["base"] = "invalid_auth"
|
errors["base"] = "invalid_auth"
|
||||||
|
@ -6,4 +6,8 @@ DOMAIN = "rituals_perfume_genie"
|
|||||||
|
|
||||||
ACCOUNT_HASH = "account_hash"
|
ACCOUNT_HASH = "account_hash"
|
||||||
|
|
||||||
UPDATE_INTERVAL = timedelta(minutes=2)
|
# The API provided by Rituals is currently rate limited to 30 requests
|
||||||
|
# per hour per IP address. To avoid hitting this limit, the polling
|
||||||
|
# interval is set to 3 minutes. This also gives a little room for
|
||||||
|
# Home Assistant restarts.
|
||||||
|
UPDATE_INTERVAL = timedelta(minutes=3)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""The Rituals Perfume Genie data update coordinator."""
|
"""The Rituals Perfume Genie data update coordinator."""
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from pyrituals import Diffuser
|
from pyrituals import Diffuser
|
||||||
@ -7,7 +8,7 @@ from pyrituals import Diffuser
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
from .const import DOMAIN, UPDATE_INTERVAL
|
from .const import DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -15,14 +16,19 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
class RitualsDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
class RitualsDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
||||||
"""Class to manage fetching Rituals Perfume Genie device data from single endpoint."""
|
"""Class to manage fetching Rituals Perfume Genie device data from single endpoint."""
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, diffuser: Diffuser) -> None:
|
def __init__(
|
||||||
|
self,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
diffuser: Diffuser,
|
||||||
|
update_interval: timedelta,
|
||||||
|
) -> None:
|
||||||
"""Initialize global Rituals Perfume Genie data updater."""
|
"""Initialize global Rituals Perfume Genie data updater."""
|
||||||
self.diffuser = diffuser
|
self.diffuser = diffuser
|
||||||
super().__init__(
|
super().__init__(
|
||||||
hass,
|
hass,
|
||||||
_LOGGER,
|
_LOGGER,
|
||||||
name=f"{DOMAIN}-{diffuser.hublot}",
|
name=f"{DOMAIN}-{diffuser.hublot}",
|
||||||
update_interval=UPDATE_INTERVAL,
|
update_interval=update_interval,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _async_update_data(self) -> None:
|
async def _async_update_data(self) -> None:
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/smlight",
|
"documentation": "https://www.home-assistant.io/integrations/smlight",
|
||||||
"integration_type": "device",
|
"integration_type": "device",
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"requirements": ["pysmlight==0.1.1"],
|
"requirements": ["pysmlight==0.1.2"],
|
||||||
"zeroconf": [
|
"zeroconf": [
|
||||||
{
|
{
|
||||||
"type": "_slzb-06._tcp.local."
|
"type": "_slzb-06._tcp.local."
|
||||||
|
@ -194,4 +194,4 @@ class TelldusLiveSensor(TelldusLiveEntity, SensorEntity):
|
|||||||
@property
|
@property
|
||||||
def unique_id(self) -> str:
|
def unique_id(self) -> str:
|
||||||
"""Return a unique ID."""
|
"""Return a unique ID."""
|
||||||
return "-".join(self._id)
|
return "-".join(map(str, self._id))
|
||||||
|
@ -38,6 +38,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.exceptions import TemplateError
|
from homeassistant.exceptions import TemplateError
|
||||||
from homeassistant.helpers import selector
|
from homeassistant.helpers import selector
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||||
from homeassistant.helpers.entity import async_generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
@ -233,7 +234,10 @@ class AlarmControlPanelTemplate(TemplateEntity, AlarmControlPanelEntity, Restore
|
|||||||
self._trigger_script = Script(hass, trigger_action, name, DOMAIN)
|
self._trigger_script = Script(hass, trigger_action, name, DOMAIN)
|
||||||
|
|
||||||
self._state: str | None = None
|
self._state: str | None = None
|
||||||
|
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||||
|
hass,
|
||||||
|
config.get(CONF_DEVICE_ID),
|
||||||
|
)
|
||||||
supported_features = AlarmControlPanelEntityFeature(0)
|
supported_features = AlarmControlPanelEntityFeature(0)
|
||||||
if self._arm_night_script is not None:
|
if self._arm_night_script is not None:
|
||||||
supported_features = (
|
supported_features = (
|
||||||
|
@ -47,6 +47,7 @@ PLATFORMS: Final = [
|
|||||||
Platform.DEVICE_TRACKER,
|
Platform.DEVICE_TRACKER,
|
||||||
Platform.LOCK,
|
Platform.LOCK,
|
||||||
Platform.MEDIA_PLAYER,
|
Platform.MEDIA_PLAYER,
|
||||||
|
Platform.NUMBER,
|
||||||
Platform.SELECT,
|
Platform.SELECT,
|
||||||
Platform.SENSOR,
|
Platform.SENSOR,
|
||||||
Platform.SWITCH,
|
Platform.SWITCH,
|
||||||
|
@ -1558,7 +1558,7 @@ class ConfigEntryItems(UserDict[str, ConfigEntry]):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._domain_index: dict[str, list[ConfigEntry]] = {}
|
self._domain_index: dict[str, list[ConfigEntry]] = {}
|
||||||
self._domain_unique_id_index: dict[str, dict[str, ConfigEntry]] = {}
|
self._domain_unique_id_index: dict[str, dict[str, list[ConfigEntry]]] = {}
|
||||||
|
|
||||||
def values(self) -> ValuesView[ConfigEntry]:
|
def values(self) -> ValuesView[ConfigEntry]:
|
||||||
"""Return the underlying values to avoid __iter__ overhead."""
|
"""Return the underlying values to avoid __iter__ overhead."""
|
||||||
@ -1601,9 +1601,9 @@ class ConfigEntryItems(UserDict[str, ConfigEntry]):
|
|||||||
report_issue,
|
report_issue,
|
||||||
)
|
)
|
||||||
|
|
||||||
self._domain_unique_id_index.setdefault(entry.domain, {})[
|
self._domain_unique_id_index.setdefault(entry.domain, {}).setdefault(
|
||||||
unique_id_hash
|
unique_id_hash, []
|
||||||
] = entry
|
).append(entry)
|
||||||
|
|
||||||
def _unindex_entry(self, entry_id: str) -> None:
|
def _unindex_entry(self, entry_id: str) -> None:
|
||||||
"""Unindex an entry."""
|
"""Unindex an entry."""
|
||||||
@ -1616,7 +1616,9 @@ class ConfigEntryItems(UserDict[str, ConfigEntry]):
|
|||||||
# Check type first to avoid expensive isinstance call
|
# Check type first to avoid expensive isinstance call
|
||||||
if type(unique_id) is not str and not isinstance(unique_id, Hashable): # noqa: E721
|
if type(unique_id) is not str and not isinstance(unique_id, Hashable): # noqa: E721
|
||||||
unique_id = str(entry.unique_id) # type: ignore[unreachable]
|
unique_id = str(entry.unique_id) # type: ignore[unreachable]
|
||||||
del self._domain_unique_id_index[domain][unique_id]
|
self._domain_unique_id_index[domain][unique_id].remove(entry)
|
||||||
|
if not self._domain_unique_id_index[domain][unique_id]:
|
||||||
|
del self._domain_unique_id_index[domain][unique_id]
|
||||||
if not self._domain_unique_id_index[domain]:
|
if not self._domain_unique_id_index[domain]:
|
||||||
del self._domain_unique_id_index[domain]
|
del self._domain_unique_id_index[domain]
|
||||||
|
|
||||||
@ -1647,7 +1649,10 @@ class ConfigEntryItems(UserDict[str, ConfigEntry]):
|
|||||||
# Check type first to avoid expensive isinstance call
|
# Check type first to avoid expensive isinstance call
|
||||||
if type(unique_id) is not str and not isinstance(unique_id, Hashable): # noqa: E721
|
if type(unique_id) is not str and not isinstance(unique_id, Hashable): # noqa: E721
|
||||||
unique_id = str(unique_id) # type: ignore[unreachable]
|
unique_id = str(unique_id) # type: ignore[unreachable]
|
||||||
return self._domain_unique_id_index.get(domain, {}).get(unique_id)
|
entries = self._domain_unique_id_index.get(domain, {}).get(unique_id)
|
||||||
|
if not entries:
|
||||||
|
return None
|
||||||
|
return entries[0]
|
||||||
|
|
||||||
|
|
||||||
class ConfigEntryStore(storage.Store[dict[str, list[dict[str, Any]]]]):
|
class ConfigEntryStore(storage.Store[dict[str, list[dict[str, Any]]]]):
|
||||||
|
@ -24,7 +24,7 @@ if TYPE_CHECKING:
|
|||||||
APPLICATION_NAME: Final = "HomeAssistant"
|
APPLICATION_NAME: Final = "HomeAssistant"
|
||||||
MAJOR_VERSION: Final = 2024
|
MAJOR_VERSION: Final = 2024
|
||||||
MINOR_VERSION: Final = 10
|
MINOR_VERSION: Final = 10
|
||||||
PATCH_VERSION: Final = "0"
|
PATCH_VERSION: Final = "1"
|
||||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 12, 0)
|
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 12, 0)
|
||||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "homeassistant"
|
name = "homeassistant"
|
||||||
version = "2024.10.0"
|
version = "2024.10.1"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
description = "Open-source home automation platform running on Python 3."
|
description = "Open-source home automation platform running on Python 3."
|
||||||
readme = "README.rst"
|
readme = "README.rst"
|
||||||
|
@ -45,7 +45,7 @@ ProgettiHWSW==0.1.3
|
|||||||
# PyBluez==0.22
|
# PyBluez==0.22
|
||||||
|
|
||||||
# homeassistant.components.cast
|
# homeassistant.components.cast
|
||||||
PyChromecast==14.0.2
|
PyChromecast==14.0.1
|
||||||
|
|
||||||
# homeassistant.components.flick_electric
|
# homeassistant.components.flick_electric
|
||||||
PyFlick==0.0.2
|
PyFlick==0.0.2
|
||||||
@ -294,7 +294,7 @@ aiolookin==1.0.0
|
|||||||
aiolyric==2.0.1
|
aiolyric==2.0.1
|
||||||
|
|
||||||
# homeassistant.components.mealie
|
# homeassistant.components.mealie
|
||||||
aiomealie==0.9.2
|
aiomealie==0.9.3
|
||||||
|
|
||||||
# homeassistant.components.modern_forms
|
# homeassistant.components.modern_forms
|
||||||
aiomodernforms==0.1.8
|
aiomodernforms==0.1.8
|
||||||
@ -1324,7 +1324,7 @@ lw12==0.9.2
|
|||||||
lxml==5.3.0
|
lxml==5.3.0
|
||||||
|
|
||||||
# homeassistant.components.matrix
|
# homeassistant.components.matrix
|
||||||
matrix-nio==0.25.1
|
matrix-nio==0.25.2
|
||||||
|
|
||||||
# homeassistant.components.maxcube
|
# homeassistant.components.maxcube
|
||||||
maxcube-api==0.4.3
|
maxcube-api==0.4.3
|
||||||
@ -2244,7 +2244,7 @@ pysmarty2==0.10.1
|
|||||||
pysml==0.0.12
|
pysml==0.0.12
|
||||||
|
|
||||||
# homeassistant.components.smlight
|
# homeassistant.components.smlight
|
||||||
pysmlight==0.1.1
|
pysmlight==0.1.2
|
||||||
|
|
||||||
# homeassistant.components.snmp
|
# homeassistant.components.snmp
|
||||||
pysnmp==6.2.6
|
pysnmp==6.2.6
|
||||||
|
@ -42,7 +42,7 @@ PlexAPI==4.15.16
|
|||||||
ProgettiHWSW==0.1.3
|
ProgettiHWSW==0.1.3
|
||||||
|
|
||||||
# homeassistant.components.cast
|
# homeassistant.components.cast
|
||||||
PyChromecast==14.0.2
|
PyChromecast==14.0.1
|
||||||
|
|
||||||
# homeassistant.components.flick_electric
|
# homeassistant.components.flick_electric
|
||||||
PyFlick==0.0.2
|
PyFlick==0.0.2
|
||||||
@ -276,7 +276,7 @@ aiolookin==1.0.0
|
|||||||
aiolyric==2.0.1
|
aiolyric==2.0.1
|
||||||
|
|
||||||
# homeassistant.components.mealie
|
# homeassistant.components.mealie
|
||||||
aiomealie==0.9.2
|
aiomealie==0.9.3
|
||||||
|
|
||||||
# homeassistant.components.modern_forms
|
# homeassistant.components.modern_forms
|
||||||
aiomodernforms==0.1.8
|
aiomodernforms==0.1.8
|
||||||
@ -1099,7 +1099,7 @@ lupupy==0.3.2
|
|||||||
lxml==5.3.0
|
lxml==5.3.0
|
||||||
|
|
||||||
# homeassistant.components.matrix
|
# homeassistant.components.matrix
|
||||||
matrix-nio==0.25.1
|
matrix-nio==0.25.2
|
||||||
|
|
||||||
# homeassistant.components.maxcube
|
# homeassistant.components.maxcube
|
||||||
maxcube-api==0.4.3
|
maxcube-api==0.4.3
|
||||||
@ -1798,7 +1798,7 @@ pysmartthings==0.7.8
|
|||||||
pysml==0.0.12
|
pysml==0.0.12
|
||||||
|
|
||||||
# homeassistant.components.smlight
|
# homeassistant.components.smlight
|
||||||
pysmlight==0.1.1
|
pysmlight==0.1.2
|
||||||
|
|
||||||
# homeassistant.components.snmp
|
# homeassistant.components.snmp
|
||||||
pysnmp==6.2.6
|
pysnmp==6.2.6
|
||||||
|
@ -37,6 +37,27 @@ async def test_full_flow(
|
|||||||
assert result["result"].unique_id == "218886794"
|
assert result["result"].unique_id == "218886794"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_stripping_token(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_nyt_games_client: AsyncMock,
|
||||||
|
mock_setup_entry: AsyncMock,
|
||||||
|
) -> None:
|
||||||
|
"""Test stripping token."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_USER},
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "user"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_TOKEN: " token "},
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
assert result["data"] == {CONF_TOKEN: "token"}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("exception", "error"),
|
("exception", "error"),
|
||||||
[
|
[
|
||||||
|
@ -23,6 +23,7 @@ from homeassistant.const import (
|
|||||||
STATE_UNKNOWN,
|
STATE_UNKNOWN,
|
||||||
)
|
)
|
||||||
from homeassistant.core import Event, HomeAssistant, State, callback
|
from homeassistant.core import Event, HomeAssistant, State, callback
|
||||||
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, assert_setup_component, mock_restore_cache
|
from tests.common import MockConfigEntry, assert_setup_component, mock_restore_cache
|
||||||
@ -503,3 +504,45 @@ async def test_restore_state(
|
|||||||
|
|
||||||
state = hass.states.get("alarm_control_panel.test_template_panel")
|
state = hass.states.get("alarm_control_panel.test_template_panel")
|
||||||
assert state.state == initial_state
|
assert state.state == initial_state
|
||||||
|
|
||||||
|
|
||||||
|
async def test_device_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test for device for button template."""
|
||||||
|
|
||||||
|
device_config_entry = MockConfigEntry()
|
||||||
|
device_config_entry.add_to_hass(hass)
|
||||||
|
device_entry = device_registry.async_get_or_create(
|
||||||
|
config_entry_id=device_config_entry.entry_id,
|
||||||
|
identifiers={("test", "identifier_test")},
|
||||||
|
connections={("mac", "30:31:32:33:34:35")},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert device_entry is not None
|
||||||
|
assert device_entry.id is not None
|
||||||
|
|
||||||
|
template_config_entry = MockConfigEntry(
|
||||||
|
data={},
|
||||||
|
domain=template.DOMAIN,
|
||||||
|
options={
|
||||||
|
"name": "My template",
|
||||||
|
"value_template": "disarmed",
|
||||||
|
"template_type": "alarm_control_panel",
|
||||||
|
"code_arm_required": True,
|
||||||
|
"code_format": "number",
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
},
|
||||||
|
title="My template",
|
||||||
|
)
|
||||||
|
|
||||||
|
template_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
template_entity = entity_registry.async_get("alarm_control_panel.my_template")
|
||||||
|
assert template_entity is not None
|
||||||
|
assert template_entity.device_id == device_entry.id
|
||||||
|
@ -512,6 +512,41 @@ async def test_remove_entry(
|
|||||||
assert not entity_entry_list
|
assert not entity_entry_list
|
||||||
|
|
||||||
|
|
||||||
|
async def test_remove_entry_non_unique_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
manager: config_entries.ConfigEntries,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test that we can remove entry with colliding unique_id."""
|
||||||
|
entry_1 = MockConfigEntry(
|
||||||
|
domain="test_other", entry_id="test1", unique_id="not_unique"
|
||||||
|
)
|
||||||
|
entry_1.add_to_manager(manager)
|
||||||
|
entry_2 = MockConfigEntry(
|
||||||
|
domain="test_other", entry_id="test2", unique_id="not_unique"
|
||||||
|
)
|
||||||
|
entry_2.add_to_manager(manager)
|
||||||
|
entry_3 = MockConfigEntry(
|
||||||
|
domain="test_other", entry_id="test3", unique_id="not_unique"
|
||||||
|
)
|
||||||
|
entry_3.add_to_manager(manager)
|
||||||
|
|
||||||
|
# Check all config entries exist
|
||||||
|
assert manager.async_entry_ids() == [
|
||||||
|
"test1",
|
||||||
|
"test2",
|
||||||
|
"test3",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Remove entries
|
||||||
|
assert await manager.async_remove("test1") == {"require_restart": False}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert await manager.async_remove("test2") == {"require_restart": False}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert await manager.async_remove("test3") == {"require_restart": False}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
async def test_remove_entry_cancels_reauth(
|
async def test_remove_entry_cancels_reauth(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
manager: config_entries.ConfigEntries,
|
manager: config_entries.ConfigEntries,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user