Skip to content
Merged

2024.6.1 #119096

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
00dd86f
Update requests to 2.32.3 (#118868)
cdce8p Jun 6, 2024
0f9a91d
Prioritize literal text with name slots in sentence matching (#118900)
synesthesiam Jun 6, 2024
5a7332a
Check if imap message text has a value instead of checking if its not…
engrbm87 Jun 6, 2024
86b13e8
Fix flaky Google Assistant test (#118914)
jpbede Jun 5, 2024
394c13a
Revert "Bump orjson to 3.10.3 (#116945)" (#118920)
bdraco Jun 6, 2024
6e9a53d
Bump `imgw-pib` backend library to version `1.0.2` (#118953)
bieniu Jun 6, 2024
62f73cf
Fix Alarm control panel not require code in several integrations (#11…
gjohansson-ST Jun 6, 2024
d6e1d05
Bump python-holidays to 0.50 (#118965)
gjohansson-ST Jun 6, 2024
14da1e9
Bump pydrawise to 2024.6.3 (#118977)
dknowles2 Jun 6, 2024
52d1432
Bump `imgw-pib` library to version `1.0.4` (#118978)
bieniu Jun 6, 2024
1f6be7b
Fix unit of measurement for airgradient sensor (#118981)
joostlek Jun 7, 2024
56db7fc
Fix exposure checks on some intents (#118988)
synesthesiam Jun 7, 2024
cfa619b
Remove isal from after_dependencies in http (#119000)
bdraco Jun 7, 2024
5bb4e4f
Hold connection lock in Shelly RPC reconnect (#119009)
thecode Jun 7, 2024
581fb2f
Always have addon url in detached_addon_missing (#119011)
mdegat01 Jun 7, 2024
de3a084
Increase test coverage for KNX Climate (#117903)
farmio May 30, 2024
31b44b7
Fix KNX `climate.set_hvac_mode` not turning `on` (#119012)
farmio Jun 6, 2024
1cbd3ab
Fix refactoring error in snmp switch (#119028)
bdraco Jun 7, 2024
20b77aa
Fix remember_the_milk calling configurator async api from the wrong t…
bdraco Jun 7, 2024
b5693ca
Fix AirGradient name (#119046)
joostlek Jun 7, 2024
093f07c
Add type ignore comments (#119052)
cdce8p Jun 7, 2024
ed22e98
Fix Azure Data Explorer strings (#119067)
joostlek Jun 7, 2024
3f70e2b
Bump version to 2024.6.1
frenck Jun 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions homeassistant/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,15 @@


DEBUGGER_INTEGRATIONS = {"debugpy"}

# Core integrations are unconditionally loaded
CORE_INTEGRATIONS = {"homeassistant", "persistent_notification"}
LOGGING_INTEGRATIONS = {

# Integrations that are loaded right after the core is set up
LOGGING_AND_HTTP_DEPS_INTEGRATIONS = {
# isal is loaded right away before `http` to ensure if its
# enabled, that `isal` is up to date.
"isal",
# Set log levels
"logger",
# Error logging
Expand Down Expand Up @@ -214,8 +221,8 @@
}

SETUP_ORDER = (
# Load logging as soon as possible
("logging", LOGGING_INTEGRATIONS),
# Load logging and http deps as soon as possible
("logging, http deps", LOGGING_AND_HTTP_DEPS_INTEGRATIONS),
# Setup frontend and recorder
("frontend, recorder", {*FRONTEND_INTEGRATIONS, *RECORDER_INTEGRATIONS}),
# Start up debuggers. Start these first in case they want to wait.
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/agent_dvr/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class AgentBaseStation(AlarmControlPanelEntity):
| AlarmControlPanelEntityFeature.ARM_AWAY
| AlarmControlPanelEntityFeature.ARM_NIGHT
)
_attr_code_arm_required = False
_attr_has_entity_name = True
_attr_name = None

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/airgradient/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"domain": "airgradient",
"name": "Airgradient",
"name": "AirGradient",
"codeowners": ["@airgradienthq", "@joostlek"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/airgradient",
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/airgradient/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class AirGradientSensorEntityDescription(SensorEntityDescription):
AirGradientSensorEntityDescription(
key="pm003",
translation_key="pm003_count",
native_unit_of_measurement="particles/dL",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda status: status.pm003_count,
),
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/airgradient/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"name": "Nitrogen index"
},
"pm003_count": {
"name": "PM0.3 count"
"name": "PM0.3"
},
"raw_total_volatile_organic_component": {
"name": "Raw total VOC"
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/azure_data_explorer/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
"title": "Setup your Azure Data Explorer integration",
"description": "Enter connection details.",
"data": {
"clusteringesturi": "Cluster Ingest URI",
"cluster_ingest_uri": "Cluster ingest URI",
"database": "Database name",
"table": "Table name",
"client_id": "Client ID",
"client_secret": "Client secret",
"authority_id": "Authority ID"
"authority_id": "Authority ID",
"use_queued_ingestion": "Use queued ingestion"
}
}
},
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/blink/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class BlinkSyncModuleHA(
"""Representation of a Blink Alarm Control Panel."""

_attr_supported_features = AlarmControlPanelEntityFeature.ARM_AWAY
_attr_code_arm_required = False
_attr_has_entity_name = True
_attr_name = None

Expand Down
90 changes: 21 additions & 69 deletions homeassistant/components/climate/intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

import voluptuous as vol

from homeassistant.core import HomeAssistant, State
from homeassistant.core import HomeAssistant
from homeassistant.helpers import intent
from homeassistant.helpers.entity_component import EntityComponent

from . import DOMAIN, ClimateEntity
from . import DOMAIN

INTENT_GET_TEMPERATURE = "HassClimateGetTemperature"

Expand All @@ -23,82 +22,35 @@ class GetTemperatureIntent(intent.IntentHandler):

intent_type = INTENT_GET_TEMPERATURE
description = "Gets the current temperature of a climate device or entity"
slot_schema = {vol.Optional("area"): str, vol.Optional("name"): str}
slot_schema = {
vol.Optional("area"): intent.non_empty_string,
vol.Optional("name"): intent.non_empty_string,
}
platforms = {DOMAIN}

async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
"""Handle the intent."""
hass = intent_obj.hass
slots = self.async_validate_slots(intent_obj.slots)

component: EntityComponent[ClimateEntity] = hass.data[DOMAIN]
entities: list[ClimateEntity] = list(component.entities)
climate_entity: ClimateEntity | None = None
climate_state: State | None = None
name: str | None = None
if "name" in slots:
name = slots["name"]["value"]

if not entities:
raise intent.IntentHandleError("No climate entities")
area: str | None = None
if "area" in slots:
area = slots["area"]["value"]

name_slot = slots.get("name", {})
entity_name: str | None = name_slot.get("value")
entity_text: str | None = name_slot.get("text")

area_slot = slots.get("area", {})
area_id = area_slot.get("value")

if area_id:
# Filter by area and optionally name
area_name = area_slot.get("text")

for maybe_climate in intent.async_match_states(
hass, name=entity_name, area_name=area_id, domains=[DOMAIN]
):
climate_state = maybe_climate
break

if climate_state is None:
raise intent.NoStatesMatchedError(
reason=intent.MatchFailedReason.AREA,
name=entity_text or entity_name,
area=area_name or area_id,
floor=None,
domains={DOMAIN},
device_classes=None,
)

climate_entity = component.get_entity(climate_state.entity_id)
elif entity_name:
# Filter by name
for maybe_climate in intent.async_match_states(
hass, name=entity_name, domains=[DOMAIN]
):
climate_state = maybe_climate
break

if climate_state is None:
raise intent.NoStatesMatchedError(
reason=intent.MatchFailedReason.NAME,
name=entity_name,
area=None,
floor=None,
domains={DOMAIN},
device_classes=None,
)

climate_entity = component.get_entity(climate_state.entity_id)
else:
# First entity
climate_entity = entities[0]
climate_state = hass.states.get(climate_entity.entity_id)

assert climate_entity is not None

if climate_state is None:
raise intent.IntentHandleError(f"No state for {climate_entity.name}")

assert climate_state is not None
match_constraints = intent.MatchTargetsConstraints(
name=name, area_name=area, domains=[DOMAIN], assistant=intent_obj.assistant
)
match_result = intent.async_match_targets(hass, match_constraints)
if not match_result.is_match:
raise intent.MatchFailedError(
result=match_result, constraints=match_constraints
)

response = intent_obj.create_response()
response.response_type = intent.IntentResponseType.QUERY_ANSWER
response.async_set_states(matched_states=[climate_state])
response.async_set_states(matched_states=match_result.states)
return response
11 changes: 9 additions & 2 deletions homeassistant/components/conversation/default_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,15 @@ def _recognize(
intent_context=intent_context,
language=language,
):
if ("name" in result.entities) and (
not result.entities["name"].is_wildcard
# Prioritize results with a "name" slot, but still prefer ones with
# more literal text matched.
if (
("name" in result.entities)
and (not result.entities["name"].is_wildcard)
and (
(name_result is None)
or (result.text_chunks_matched > name_result.text_chunks_matched)
)
):
name_result = result

Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/egardia/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class EgardiaAlarm(AlarmControlPanelEntity):
"""Representation of a Egardia alarm."""

_attr_state: str | None
_attr_code_arm_required = False
_attr_supported_features = (
AlarmControlPanelEntityFeature.ARM_HOME
| AlarmControlPanelEntityFeature.ARM_AWAY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ async def async_process(
await session.async_ensure_token_valid()
self.assistant = None
if not self.assistant or user_input.language != self.language:
credentials = Credentials(session.token[CONF_ACCESS_TOKEN])
credentials = Credentials(session.token[CONF_ACCESS_TOKEN]) # type: ignore[no-untyped-call]
self.language = user_input.language
self.assistant = TextAssistant(credentials, self.language)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/google_assistant_sdk/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ async def async_send_text_commands(
entry.async_start_reauth(hass)
raise

credentials = Credentials(session.token[CONF_ACCESS_TOKEN])
credentials = Credentials(session.token[CONF_ACCESS_TOKEN]) # type: ignore[no-untyped-call]
language_code = entry.options.get(CONF_LANGUAGE_CODE, default_language_code(hass))
with TextAssistant(
credentials, language_code, audio_out=bool(media_players)
Expand Down
4 changes: 3 additions & 1 deletion homeassistant/components/google_sheets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ async def async_setup_service(hass: HomeAssistant) -> None:

def _append_to_sheet(call: ServiceCall, entry: ConfigEntry) -> None:
"""Run append in the executor."""
service = Client(Credentials(entry.data[CONF_TOKEN][CONF_ACCESS_TOKEN]))
service = Client(
Credentials(entry.data[CONF_TOKEN][CONF_ACCESS_TOKEN]) # type: ignore[no-untyped-call]
)
try:
sheet = service.open_by_key(entry.unique_id)
except RefreshError:
Expand Down
4 changes: 3 additions & 1 deletion homeassistant/components/google_sheets/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ async def async_step_reauth_confirm(

async def async_oauth_create_entry(self, data: dict[str, Any]) -> ConfigFlowResult:
"""Create an entry for the flow, or update existing entry."""
service = Client(Credentials(data[CONF_TOKEN][CONF_ACCESS_TOKEN]))
service = Client(
Credentials(data[CONF_TOKEN][CONF_ACCESS_TOKEN]) # type: ignore[no-untyped-call]
)

if self.reauth_entry:
_LOGGER.debug("service.open_by_key")
Expand Down
7 changes: 3 additions & 4 deletions homeassistant/components/hassio/issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,14 @@ def add_issue(self, issue: Issue) -> None:
placeholders = {PLACEHOLDER_KEY_REFERENCE: issue.reference}

if issue.key == ISSUE_KEY_ADDON_DETACHED_ADDON_MISSING:
placeholders[PLACEHOLDER_KEY_ADDON_URL] = (
f"/hassio/addon/{issue.reference}"
)
addons = get_addons_info(self._hass)
if addons and issue.reference in addons:
placeholders[PLACEHOLDER_KEY_ADDON] = addons[issue.reference][
"name"
]
if "url" in addons[issue.reference]:
placeholders[PLACEHOLDER_KEY_ADDON_URL] = addons[
issue.reference
]["url"]
else:
placeholders[PLACEHOLDER_KEY_ADDON] = issue.reference

Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/hive/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class HiveAlarmControlPanelEntity(HiveEntity, AlarmControlPanelEntity):
| AlarmControlPanelEntityFeature.ARM_AWAY
| AlarmControlPanelEntityFeature.TRIGGER
)
_attr_code_arm_required = False

async def async_alarm_disarm(self, code: str | None = None) -> None:
"""Send disarm command."""
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/holiday/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/holiday",
"iot_class": "local_polling",
"requirements": ["holidays==0.49", "babel==2.13.1"]
"requirements": ["holidays==0.50", "babel==2.13.1"]
}
1 change: 0 additions & 1 deletion homeassistant/components/http/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"domain": "http",
"name": "HTTP",
"after_dependencies": ["isal"],
"codeowners": ["@home-assistant/core"],
"documentation": "https://www.home-assistant.io/integrations/http",
"integration_type": "system",
Expand Down
45 changes: 23 additions & 22 deletions homeassistant/components/humidifier/intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class HumidityHandler(intent.IntentHandler):
intent_type = INTENT_HUMIDITY
description = "Set desired humidity level"
slot_schema = {
vol.Required("name"): cv.string,
vol.Required("name"): intent.non_empty_string,
vol.Required("humidity"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
}
platforms = {DOMAIN}
Expand All @@ -44,18 +44,19 @@ async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse
"""Handle the hass intent."""
hass = intent_obj.hass
slots = self.async_validate_slots(intent_obj.slots)
states = list(
intent.async_match_states(
hass,
name=slots["name"]["value"],
states=hass.states.async_all(DOMAIN),
)
)

if not states:
raise intent.IntentHandleError("No entities matched")
match_constraints = intent.MatchTargetsConstraints(
name=slots["name"]["value"],
domains=[DOMAIN],
assistant=intent_obj.assistant,
)
match_result = intent.async_match_targets(hass, match_constraints)
if not match_result.is_match:
raise intent.MatchFailedError(
result=match_result, constraints=match_constraints
)

state = states[0]
state = match_result.states[0]
service_data = {ATTR_ENTITY_ID: state.entity_id}

humidity = slots["humidity"]["value"]
Expand Down Expand Up @@ -89,7 +90,7 @@ class SetModeHandler(intent.IntentHandler):
intent_type = INTENT_MODE
description = "Set humidifier mode"
slot_schema = {
vol.Required("name"): cv.string,
vol.Required("name"): intent.non_empty_string,
vol.Required("mode"): cv.string,
}
platforms = {DOMAIN}
Expand All @@ -98,18 +99,18 @@ async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse
"""Handle the hass intent."""
hass = intent_obj.hass
slots = self.async_validate_slots(intent_obj.slots)
states = list(
intent.async_match_states(
hass,
name=slots["name"]["value"],
states=hass.states.async_all(DOMAIN),
)
match_constraints = intent.MatchTargetsConstraints(
name=slots["name"]["value"],
domains=[DOMAIN],
assistant=intent_obj.assistant,
)
match_result = intent.async_match_targets(hass, match_constraints)
if not match_result.is_match:
raise intent.MatchFailedError(
result=match_result, constraints=match_constraints
)

if not states:
raise intent.IntentHandleError("No entities matched")

state = states[0]
state = match_result.states[0]
service_data = {ATTR_ENTITY_ID: state.entity_id}

intent.async_test_feature(state, HumidifierEntityFeature.MODES, "modes")
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/hydrawise/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/hydrawise",
"iot_class": "cloud_polling",
"loggers": ["pydrawise"],
"requirements": ["pydrawise==2024.6.2"]
"requirements": ["pydrawise==2024.6.3"]
}
Loading