Skip to content

Commit

Permalink
2024.4.3 (#115463)
Browse files Browse the repository at this point in the history
  • Loading branch information
frenck committed Apr 12, 2024
2 parents 04072cb + 62eee52 commit efe9181
Show file tree
Hide file tree
Showing 44 changed files with 486 additions and 102 deletions.
20 changes: 9 additions & 11 deletions homeassistant/components/aranet/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

from __future__ import annotations

import logging
from typing import Any

from aranet4.client import Aranet4Advertisement, Version as AranetVersion
from bluetooth_data_tools import human_readable_name
import voluptuous as vol

from homeassistant.components.bluetooth import (
Expand All @@ -18,11 +18,15 @@

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)

MIN_VERSION = AranetVersion(1, 2, 0)


def _title(discovery_info: BluetoothServiceInfoBleak) -> str:
return discovery_info.device.name or human_readable_name(
None, "Aranet", discovery_info.address
)


class AranetConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Aranet."""

Expand Down Expand Up @@ -61,11 +65,8 @@ async def async_step_bluetooth_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Confirm discovery."""
assert self._discovered_device is not None
adv = self._discovered_device
assert self._discovery_info is not None
discovery_info = self._discovery_info
title = adv.readings.name if adv.readings else discovery_info.name
title = _title(self._discovery_info)
if user_input is not None:
return self.async_create_entry(title=title, data={})

Expand Down Expand Up @@ -101,10 +102,7 @@ async def async_step_user(
discovery_info.device, discovery_info.advertisement
)
if adv.manufacturer_data:
self._discovered_devices[address] = (
adv.readings.name if adv.readings else discovery_info.name,
adv,
)
self._discovered_devices[address] = (_title(discovery_info), adv)

if not self._discovered_devices:
return self.async_abort(reason="no_devices_found")
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/aranet/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
"documentation": "https://www.home-assistant.io/integrations/aranet",
"integration_type": "device",
"iot_class": "local_push",
"requirements": ["aranet4==2.2.2"]
"requirements": ["aranet4==2.3.3"]
}
18 changes: 17 additions & 1 deletion homeassistant/components/automation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,22 @@ def _log_callback(self, level: int, msg: str, **kwargs: Any) -> None:
"""Log helper callback."""
self._logger.log(level, "%s %s", msg, self.name, **kwargs)

async def _async_trigger_if_enabled(
self,
run_variables: dict[str, Any],
context: Context | None = None,
skip_condition: bool = False,
) -> ScriptRunResult | None:
"""Trigger automation if enabled.
If the trigger starts but has a delay, the automation will be triggered
when the delay has passed so we need to make sure its still enabled before
executing the action.
"""
if not self._is_enabled:
return None
return await self.async_trigger(run_variables, context, skip_condition)

async def _async_attach_triggers(
self, home_assistant_start: bool
) -> Callable[[], None] | None:
Expand All @@ -835,7 +851,7 @@ async def _async_attach_triggers(
return await async_initialize_triggers(
self.hass,
self._trigger_config,
self.async_trigger,
self._async_trigger_if_enabled,
DOMAIN,
str(self.name),
self._log_callback,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/bluetooth/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"quality_scale": "internal",
"requirements": [
"bleak==0.21.1",
"bleak-retry-connector==3.4.0",
"bleak-retry-connector==3.5.0",
"bluetooth-adapters==0.18.0",
"bluetooth-auto-recovery==1.4.0",
"bluetooth-data-tools==1.19.0",
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/caldav/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
username=entry.data[CONF_USERNAME],
password=entry.data[CONF_PASSWORD],
ssl_verify_cert=entry.data[CONF_VERIFY_SSL],
timeout=10,
)
try:
await hass.async_add_executor_job(client.principal)
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/forecast_solar/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"quality_scale": "platinum",
"requirements": ["forecast-solar==3.0.0"]
"requirements": ["forecast-solar==3.1.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20240404.1"]
"requirements": ["home-assistant-frontend==20240404.2"]
}
5 changes: 3 additions & 2 deletions homeassistant/components/google_tasks/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ def response_handler(_, response, exception: HttpError) -> None:
raise GoogleTasksApiError(
f"Google Tasks API responded with error ({exception.status_code})"
) from exception
data = json.loads(response)
_raise_if_error(data)
if response:
data = json.loads(response)
_raise_if_error(data)

for task_id in task_ids:
batch.add(
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/hassio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def valid_addon(value: Any) -> str:
{
vol.Optional(ATTR_HOMEASSISTANT): cv.boolean,
vol.Optional(ATTR_FOLDERS): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(ATTR_ADDONS): vol.All(cv.ensure_list, [cv.slug]),
vol.Optional(ATTR_ADDONS): vol.All(cv.ensure_list, [VALID_ADDON_SLUG]),
}
)

Expand All @@ -211,7 +211,7 @@ def valid_addon(value: Any) -> str:
{
vol.Optional(ATTR_HOMEASSISTANT): cv.boolean,
vol.Optional(ATTR_FOLDERS): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(ATTR_ADDONS): vol.All(cv.ensure_list, [cv.slug]),
vol.Optional(ATTR_ADDONS): vol.All(cv.ensure_list, [VALID_ADDON_SLUG]),
}
)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/hassio/repairs.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from .handler import async_apply_suggestion
from .issues import Issue, Suggestion

SUGGESTION_CONFIRMATION_REQUIRED = {"system_execute_reboot"}
SUGGESTION_CONFIRMATION_REQUIRED = {"system_adopt_data_disk", "system_execute_reboot"}

EXTRA_PLACEHOLDERS = {
"issue_mount_mount_failed": {
Expand Down
11 changes: 9 additions & 2 deletions homeassistant/components/hassio/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,15 @@
"title": "Multiple data disks detected",
"fix_flow": {
"step": {
"system_rename_data_disk": {
"description": "`{reference}` is a filesystem with the name hassos-data and is not the active data disk. This can cause Home Assistant to choose the wrong data disk at system reboot.\n\nUse the fix option to rename the filesystem to prevent this. Alternatively you can move the data disk to the drive (overwriting its contents) or remove the drive from the system."
"fix_menu": {
"description": "`{reference}` is a filesystem with the name hassos-data and is not the active data disk. This can cause Home Assistant to choose the wrong data disk at system reboot.\n\nUse the 'Rename' option to rename the filesystem to prevent this. Use the 'Adopt' option to make that your data disk and rename the existing one. Alternatively you can move the data disk to the drive (overwriting its contents) or remove the drive from the system.",
"menu_options": {
"system_rename_data_disk": "Rename",
"system_adopt_data_disk": "Adopt"
}
},
"system_adopt_data_disk": {
"description": "This fix will initiate a system reboot which will make Home Assistant and all the Add-ons inaccessible for a brief period. After the reboot `{reference}` will be the data disk of Home Assistant and your existing data disk will be renamed and ignored."
}
},
"abort": {
Expand Down
23 changes: 22 additions & 1 deletion homeassistant/components/holiday/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,36 @@

from __future__ import annotations

from functools import partial

from holidays import country_holidays

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.const import CONF_COUNTRY, Platform
from homeassistant.core import HomeAssistant
from homeassistant.setup import SetupPhases, async_pause_setup

from .const import CONF_PROVINCE

PLATFORMS: list[Platform] = [Platform.CALENDAR]


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Holiday from a config entry."""
country: str = entry.data[CONF_COUNTRY]
province: str | None = entry.data.get(CONF_PROVINCE)

# We only import here to ensure that that its not imported later
# in the event loop since the platforms will call country_holidays
# which loads python code from disk.
with async_pause_setup(hass, SetupPhases.WAIT_IMPORT_PACKAGES):
# import executor job is used here because multiple integrations use
# the holidays library and it is not thread safe to import it in parallel
# https://github.com/python/cpython/issues/83065
await hass.async_add_import_executor_job(
partial(country_holidays, country, subdiv=province)
)

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

return True
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/media_extractor/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"iot_class": "calculated",
"loggers": ["yt_dlp"],
"quality_scale": "internal",
"requirements": ["yt-dlp==2024.03.10"]
"requirements": ["yt-dlp==2024.04.09"]
}
3 changes: 3 additions & 0 deletions homeassistant/components/modbus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:

async def async_reset_platform(hass: HomeAssistant, integration_name: str) -> None:
"""Release modbus resources."""
if DOMAIN not in hass.data:
_LOGGER.error("Modbus cannot reload, because it was never loaded")
return
_LOGGER.info("Modbus reloading")
hubs = hass.data[DOMAIN]
for name in hubs:
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/modbus/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"iot_class": "local_polling",
"loggers": ["pymodbus"],
"quality_scale": "platinum",
"requirements": ["pymodbus==3.6.6"]
"requirements": ["pymodbus==3.6.7"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/neato/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"documentation": "https://www.home-assistant.io/integrations/neato",
"iot_class": "cloud_polling",
"loggers": ["pybotvac"],
"requirements": ["pybotvac==0.0.24"]
"requirements": ["pybotvac==0.0.25"]
}
3 changes: 2 additions & 1 deletion homeassistant/components/rainbird/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ async def async_turn_off(self, **kwargs):

# The device reflects the old state for a few moments. Update the
# state manually and trigger a refresh after a short debounced delay.
self.coordinator.data.active_zones.remove(self._zone)
if self.is_on:
self.coordinator.data.active_zones.remove(self._zone)
self.async_write_ha_state()
await self.coordinator.async_request_refresh()

Expand Down
9 changes: 7 additions & 2 deletions homeassistant/components/risco/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import (
CONF_CONCURRENCY,
DATA_COORDINATOR,
DEFAULT_CONCURRENCY,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
EVENTS_COORDINATOR,
Expand Down Expand Up @@ -85,7 +87,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

async def _async_setup_local_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
data = entry.data
risco = RiscoLocal(data[CONF_HOST], data[CONF_PORT], data[CONF_PIN])
concurrency = entry.options.get(CONF_CONCURRENCY, DEFAULT_CONCURRENCY)
risco = RiscoLocal(
data[CONF_HOST], data[CONF_PORT], data[CONF_PIN], concurrency=concurrency
)

try:
await risco.connect()
Expand All @@ -96,7 +101,7 @@ async def _async_setup_local_entry(hass: HomeAssistant, entry: ConfigEntry) -> b
return False

async def _error(error: Exception) -> None:
_LOGGER.error("Error in Risco library: %s", error)
_LOGGER.error("Error in Risco library", exc_info=error)

entry.async_on_unload(risco.add_error_handler(_error))

Expand Down
20 changes: 16 additions & 4 deletions homeassistant/components/risco/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@
CONF_CODE_ARM_REQUIRED,
CONF_CODE_DISARM_REQUIRED,
CONF_COMMUNICATION_DELAY,
CONF_CONCURRENCY,
CONF_HA_STATES_TO_RISCO,
CONF_RISCO_STATES_TO_HA,
DEFAULT_ADVANCED_OPTIONS,
DEFAULT_OPTIONS,
DOMAIN,
MAX_COMMUNICATION_DELAY,
Expand Down Expand Up @@ -225,11 +227,8 @@ def __init__(self, config_entry: ConfigEntry) -> None:
self._data = {**DEFAULT_OPTIONS, **config_entry.options}

def _options_schema(self) -> vol.Schema:
return vol.Schema(
schema = vol.Schema(
{
vol.Required(
CONF_SCAN_INTERVAL, default=self._data[CONF_SCAN_INTERVAL]
): int,
vol.Required(
CONF_CODE_ARM_REQUIRED, default=self._data[CONF_CODE_ARM_REQUIRED]
): bool,
Expand All @@ -239,6 +238,19 @@ def _options_schema(self) -> vol.Schema:
): bool,
}
)
if self.show_advanced_options:
self._data = {**DEFAULT_ADVANCED_OPTIONS, **self._data}
schema = schema.extend(
{
vol.Required(
CONF_SCAN_INTERVAL, default=self._data[CONF_SCAN_INTERVAL]
): int,
vol.Required(
CONF_CONCURRENCY, default=self._data[CONF_CONCURRENCY]
): int,
}
)
return schema

async def async_step_init(
self, user_input: dict[str, Any] | None = None
Expand Down
8 changes: 7 additions & 1 deletion homeassistant/components/risco/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
EVENTS_COORDINATOR = "risco_events"

DEFAULT_SCAN_INTERVAL = 30
DEFAULT_CONCURRENCY = 4

TYPE_LOCAL = "local"

Expand All @@ -25,6 +26,7 @@
CONF_RISCO_STATES_TO_HA = "risco_states_to_ha"
CONF_HA_STATES_TO_RISCO = "ha_states_to_risco"
CONF_COMMUNICATION_DELAY = "communication_delay"
CONF_CONCURRENCY = "concurrency"

RISCO_GROUPS = ["A", "B", "C", "D"]
RISCO_ARM = "arm"
Expand All @@ -44,9 +46,13 @@
}

DEFAULT_OPTIONS = {
CONF_SCAN_INTERVAL: DEFAULT_SCAN_INTERVAL,
CONF_CODE_ARM_REQUIRED: False,
CONF_CODE_DISARM_REQUIRED: False,
CONF_RISCO_STATES_TO_HA: DEFAULT_RISCO_STATES_TO_HA,
CONF_HA_STATES_TO_RISCO: DEFAULT_HA_STATES_TO_RISCO,
}

DEFAULT_ADVANCED_OPTIONS = {
CONF_SCAN_INTERVAL: DEFAULT_SCAN_INTERVAL,
CONF_CONCURRENCY: DEFAULT_CONCURRENCY,
}
3 changes: 2 additions & 1 deletion homeassistant/components/risco/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"init": {
"title": "Configure options",
"data": {
"scan_interval": "How often to poll Risco (in seconds)",
"scan_interval": "How often to poll Risco Cloud (in seconds)",
"concurrency": "Maximum concurrent requests in Risco local",
"code_arm_required": "Require PIN to arm",
"code_disarm_required": "Require PIN to disarm"
}
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/whirlpool/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "hub",
"iot_class": "cloud_push",
"loggers": ["whirlpool"],
"requirements": ["whirlpool-sixth-sense==0.18.7"]
"requirements": ["whirlpool-sixth-sense==0.18.8"]
}

0 comments on commit efe9181

Please sign in to comment.