mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
2025.7.1 (#148171)
This commit is contained in:
commit
5d6b02f470
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@ -37,7 +37,7 @@ on:
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
CACHE_VERSION: 3
|
||||
CACHE_VERSION: 4
|
||||
UV_CACHE_VERSION: 1
|
||||
MYPY_CACHE_VERSION: 1
|
||||
HA_SHORT_VERSION: "2025.7"
|
||||
|
@ -8,5 +8,5 @@
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["aioamazondevices"],
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["aioamazondevices==3.2.2"]
|
||||
"requirements": ["aioamazondevices==3.2.3"]
|
||||
}
|
||||
|
@ -13,6 +13,6 @@
|
||||
"integration_type": "system",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["acme", "hass_nabucasa", "snitun"],
|
||||
"requirements": ["hass-nabucasa==0.104.0"],
|
||||
"requirements": ["hass-nabucasa==0.105.0"],
|
||||
"single_config_entry": true
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: EnphaseConfigEntry) ->
|
||||
coordinator = entry.runtime_data
|
||||
coordinator.async_cancel_token_refresh()
|
||||
coordinator.async_cancel_firmware_refresh()
|
||||
coordinator.async_cancel_mac_verification()
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["pyenphase"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["pyenphase==2.1.0"],
|
||||
"requirements": ["pyenphase==2.2.0"],
|
||||
"zeroconf": [
|
||||
{
|
||||
"type": "_enphase-envoy._tcp.local."
|
||||
|
@ -20,5 +20,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||
"integration_type": "system",
|
||||
"quality_scale": "internal",
|
||||
"requirements": ["home-assistant-frontend==20250702.0"]
|
||||
"requirements": ["home-assistant-frontend==20250702.1"]
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ def setup_bans(hass: HomeAssistant, app: Application, login_threshold: int) -> N
|
||||
"""Initialize bans when app starts up."""
|
||||
await app[KEY_BAN_MANAGER].async_load()
|
||||
|
||||
app.on_startup.append(ban_startup)
|
||||
app.on_startup.append(ban_startup) # type: ignore[arg-type]
|
||||
|
||||
|
||||
@middleware
|
||||
|
@ -7,6 +7,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/music_assistant",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["music_assistant"],
|
||||
"requirements": ["music-assistant-client==1.2.3"],
|
||||
"requirements": ["music-assistant-client==1.2.4"],
|
||||
"zeroconf": ["_mass._tcp.local."]
|
||||
}
|
||||
|
@ -248,8 +248,6 @@ class MusicAssistantPlayer(MusicAssistantEntity, MediaPlayerEntity):
|
||||
player = self.player
|
||||
active_queue = self.active_queue
|
||||
# update generic attributes
|
||||
if player.powered and active_queue is not None:
|
||||
self._attr_state = MediaPlayerState(active_queue.state.value)
|
||||
if player.powered and player.playback_state is not None:
|
||||
self._attr_state = MediaPlayerState(player.playback_state.value)
|
||||
else:
|
||||
|
12
homeassistant/components/remote_calendar/client.py
Normal file
12
homeassistant/components/remote_calendar/client.py
Normal file
@ -0,0 +1,12 @@
|
||||
"""Specifies the parameter for the httpx download."""
|
||||
|
||||
from httpx import AsyncClient, Response, Timeout
|
||||
|
||||
|
||||
async def get_calendar(client: AsyncClient, url: str) -> Response:
|
||||
"""Make an HTTP GET request using Home Assistant's async HTTPX client with timeout."""
|
||||
return await client.get(
|
||||
url,
|
||||
follow_redirects=True,
|
||||
timeout=Timeout(5, read=30, write=5, pool=5),
|
||||
)
|
@ -4,13 +4,14 @@ from http import HTTPStatus
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from httpx import HTTPError, InvalidURL
|
||||
from httpx import HTTPError, InvalidURL, TimeoutException
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.const import CONF_URL
|
||||
from homeassistant.helpers.httpx_client import get_async_client
|
||||
|
||||
from .client import get_calendar
|
||||
from .const import CONF_CALENDAR_NAME, DOMAIN
|
||||
from .ics import InvalidIcsException, parse_calendar
|
||||
|
||||
@ -49,7 +50,7 @@ class RemoteCalendarConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
self._async_abort_entries_match({CONF_URL: user_input[CONF_URL]})
|
||||
client = get_async_client(self.hass)
|
||||
try:
|
||||
res = await client.get(user_input[CONF_URL], follow_redirects=True)
|
||||
res = await get_calendar(client, user_input[CONF_URL])
|
||||
if res.status_code == HTTPStatus.FORBIDDEN:
|
||||
errors["base"] = "forbidden"
|
||||
return self.async_show_form(
|
||||
@ -58,9 +59,14 @@ class RemoteCalendarConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
errors=errors,
|
||||
)
|
||||
res.raise_for_status()
|
||||
except TimeoutException as err:
|
||||
errors["base"] = "timeout_connect"
|
||||
_LOGGER.debug(
|
||||
"A timeout error occurred: %s", str(err) or type(err).__name__
|
||||
)
|
||||
except (HTTPError, InvalidURL) as err:
|
||||
errors["base"] = "cannot_connect"
|
||||
_LOGGER.debug("An error occurred: %s", err)
|
||||
_LOGGER.debug("An error occurred: %s", str(err) or type(err).__name__)
|
||||
else:
|
||||
try:
|
||||
await parse_calendar(self.hass, res.text)
|
||||
|
@ -3,7 +3,7 @@
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from httpx import HTTPError, InvalidURL
|
||||
from httpx import HTTPError, InvalidURL, TimeoutException
|
||||
from ical.calendar import Calendar
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -12,6 +12,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.httpx_client import get_async_client
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .client import get_calendar
|
||||
from .const import DOMAIN
|
||||
from .ics import InvalidIcsException, parse_calendar
|
||||
|
||||
@ -36,7 +37,7 @@ class RemoteCalendarDataUpdateCoordinator(DataUpdateCoordinator[Calendar]):
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
name=DOMAIN,
|
||||
name=f"{DOMAIN}_{config_entry.title}",
|
||||
update_interval=SCAN_INTERVAL,
|
||||
always_update=True,
|
||||
)
|
||||
@ -46,13 +47,19 @@ class RemoteCalendarDataUpdateCoordinator(DataUpdateCoordinator[Calendar]):
|
||||
async def _async_update_data(self) -> Calendar:
|
||||
"""Update data from the url."""
|
||||
try:
|
||||
res = await self._client.get(self._url, follow_redirects=True)
|
||||
res = await get_calendar(self._client, self._url)
|
||||
res.raise_for_status()
|
||||
except TimeoutException as err:
|
||||
_LOGGER.debug("%s: %s", self._url, str(err) or type(err).__name__)
|
||||
raise UpdateFailed(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="timeout",
|
||||
) from err
|
||||
except (HTTPError, InvalidURL) as err:
|
||||
_LOGGER.debug("%s: %s", self._url, str(err) or type(err).__name__)
|
||||
raise UpdateFailed(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="unable_to_fetch",
|
||||
translation_placeholders={"err": str(err)},
|
||||
) from err
|
||||
try:
|
||||
self.ics = res.text
|
||||
|
@ -18,14 +18,18 @@
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]"
|
||||
},
|
||||
"error": {
|
||||
"timeout_connect": "[%key:common::config_flow::error::timeout_connect%]",
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"forbidden": "The server understood the request but refuses to authorize it.",
|
||||
"invalid_ics_file": "There was a problem reading the calendar information. See the error log for additional details."
|
||||
}
|
||||
},
|
||||
"exceptions": {
|
||||
"timeout": {
|
||||
"message": "The connection timed out. See the debug log for additional details."
|
||||
},
|
||||
"unable_to_fetch": {
|
||||
"message": "Unable to fetch calendar data: {err}"
|
||||
"message": "Unable to fetch calendar data. See the debug log for additional details."
|
||||
},
|
||||
"unable_to_parse": {
|
||||
"message": "Unable to parse calendar data: {err}"
|
||||
|
@ -124,6 +124,7 @@ class SamsungTVConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
self._model: str | None = None
|
||||
self._connect_result: str | None = None
|
||||
self._method: str | None = None
|
||||
self._port: int | None = None
|
||||
self._name: str | None = None
|
||||
self._title: str = ""
|
||||
self._id: int | None = None
|
||||
@ -199,33 +200,37 @@ class SamsungTVConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
async def _async_create_bridge(self) -> None:
|
||||
"""Create the bridge."""
|
||||
result, method, _info = await self._async_get_device_info_and_method()
|
||||
result = await self._async_load_device_info()
|
||||
if result not in SUCCESSFUL_RESULTS:
|
||||
LOGGER.debug("No working config found for %s", self._host)
|
||||
raise AbortFlow(result)
|
||||
assert method is not None
|
||||
self._bridge = SamsungTVBridge.get_bridge(self.hass, method, self._host)
|
||||
assert self._method is not None
|
||||
self._bridge = SamsungTVBridge.get_bridge(
|
||||
self.hass, self._method, self._host, self._port
|
||||
)
|
||||
|
||||
async def _async_get_device_info_and_method(
|
||||
async def _async_load_device_info(
|
||||
self,
|
||||
) -> tuple[str, str | None, dict[str, Any] | None]:
|
||||
) -> str:
|
||||
"""Get device info and method only once."""
|
||||
if self._connect_result is None:
|
||||
result, _, method, info = await async_get_device_info(self.hass, self._host)
|
||||
result, port, method, info = await async_get_device_info(
|
||||
self.hass, self._host
|
||||
)
|
||||
self._connect_result = result
|
||||
self._method = method
|
||||
self._port = port
|
||||
self._device_info = info
|
||||
if not method:
|
||||
LOGGER.debug("Host:%s did not return device info", self._host)
|
||||
return result, None, None
|
||||
return self._connect_result, self._method, self._device_info
|
||||
return self._connect_result
|
||||
|
||||
async def _async_get_and_check_device_info(self) -> bool:
|
||||
"""Try to get the device info."""
|
||||
result, _method, info = await self._async_get_device_info_and_method()
|
||||
result = await self._async_load_device_info()
|
||||
if result not in SUCCESSFUL_RESULTS:
|
||||
raise AbortFlow(result)
|
||||
if not info:
|
||||
if not (info := self._device_info):
|
||||
return False
|
||||
dev_info = info.get("device", {})
|
||||
assert dev_info is not None
|
||||
|
@ -374,9 +374,7 @@ class TelegramNotificationService:
|
||||
}
|
||||
if data is not None:
|
||||
if ATTR_PARSER in data:
|
||||
params[ATTR_PARSER] = self._parsers.get(
|
||||
data[ATTR_PARSER], self.parse_mode
|
||||
)
|
||||
params[ATTR_PARSER] = data[ATTR_PARSER]
|
||||
if ATTR_TIMEOUT in data:
|
||||
params[ATTR_TIMEOUT] = data[ATTR_TIMEOUT]
|
||||
if ATTR_DISABLE_NOTIF in data:
|
||||
@ -408,6 +406,8 @@ class TelegramNotificationService:
|
||||
params[ATTR_REPLYMARKUP] = InlineKeyboardMarkup(
|
||||
[_make_row_inline_keyboard(row) for row in keys]
|
||||
)
|
||||
if params[ATTR_PARSER] == PARSER_PLAIN_TEXT:
|
||||
params[ATTR_PARSER] = None
|
||||
return params
|
||||
|
||||
async def _send_msg(
|
||||
|
@ -159,8 +159,6 @@ class OptionsFlowHandler(OptionsFlow):
|
||||
"""Manage the options."""
|
||||
|
||||
if user_input is not None:
|
||||
if user_input[ATTR_PARSER] == PARSER_PLAIN_TEXT:
|
||||
user_input[ATTR_PARSER] = None
|
||||
return self.async_create_entry(data=user_input)
|
||||
|
||||
return self.async_show_form(
|
||||
|
@ -109,6 +109,7 @@ send_photo:
|
||||
- "markdown"
|
||||
- "markdownv2"
|
||||
- "plain_text"
|
||||
translation_key: "parse_mode"
|
||||
disable_notification:
|
||||
selector:
|
||||
boolean:
|
||||
@ -261,6 +262,7 @@ send_animation:
|
||||
- "markdown"
|
||||
- "markdownv2"
|
||||
- "plain_text"
|
||||
translation_key: "parse_mode"
|
||||
disable_notification:
|
||||
selector:
|
||||
boolean:
|
||||
@ -341,6 +343,7 @@ send_video:
|
||||
- "markdown"
|
||||
- "markdownv2"
|
||||
- "plain_text"
|
||||
translation_key: "parse_mode"
|
||||
disable_notification:
|
||||
selector:
|
||||
boolean:
|
||||
@ -493,6 +496,7 @@ send_document:
|
||||
- "markdown"
|
||||
- "markdownv2"
|
||||
- "plain_text"
|
||||
translation_key: "parse_mode"
|
||||
disable_notification:
|
||||
selector:
|
||||
boolean:
|
||||
@ -670,6 +674,7 @@ edit_message:
|
||||
- "markdown"
|
||||
- "markdownv2"
|
||||
- "plain_text"
|
||||
translation_key: "parse_mode"
|
||||
disable_web_page_preview:
|
||||
selector:
|
||||
boolean:
|
||||
|
@ -7,7 +7,7 @@
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aiounifi"],
|
||||
"requirements": ["aiounifi==83"],
|
||||
"requirements": ["aiounifi==84"],
|
||||
"ssdp": [
|
||||
{
|
||||
"manufacturer": "Ubiquiti Networks",
|
||||
|
@ -6,5 +6,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/venstar",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["venstarcolortouch"],
|
||||
"requirements": ["venstarcolortouch==0.19"]
|
||||
"requirements": ["venstarcolortouch==0.21"]
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
"zha",
|
||||
"universal_silabs_flasher"
|
||||
],
|
||||
"requirements": ["zha==0.0.61"],
|
||||
"requirements": ["zha==0.0.62"],
|
||||
"usb": [
|
||||
{
|
||||
"vid": "10C4",
|
||||
|
@ -25,7 +25,7 @@ if TYPE_CHECKING:
|
||||
APPLICATION_NAME: Final = "HomeAssistant"
|
||||
MAJOR_VERSION: Final = 2025
|
||||
MINOR_VERSION: Final = 7
|
||||
PATCH_VERSION: Final = "0"
|
||||
PATCH_VERSION: Final = "1"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 13, 2)
|
||||
|
@ -35,10 +35,10 @@ fnv-hash-fast==1.5.0
|
||||
go2rtc-client==0.2.1
|
||||
ha-ffmpeg==3.2.2
|
||||
habluetooth==3.49.0
|
||||
hass-nabucasa==0.104.0
|
||||
hass-nabucasa==0.105.0
|
||||
hassil==2.2.3
|
||||
home-assistant-bluetooth==1.13.1
|
||||
home-assistant-frontend==20250702.0
|
||||
home-assistant-frontend==20250702.1
|
||||
home-assistant-intents==2025.6.23
|
||||
httpx==0.28.1
|
||||
ifaddr==0.2.0
|
||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "homeassistant"
|
||||
version = "2025.7.0"
|
||||
version = "2025.7.1"
|
||||
license = "Apache-2.0"
|
||||
license-files = ["LICENSE*", "homeassistant/backports/LICENSE*"]
|
||||
description = "Open-source home automation platform running on Python 3."
|
||||
@ -47,7 +47,7 @@ dependencies = [
|
||||
"fnv-hash-fast==1.5.0",
|
||||
# hass-nabucasa is imported by helpers which don't depend on the cloud
|
||||
# integration
|
||||
"hass-nabucasa==0.104.0",
|
||||
"hass-nabucasa==0.105.0",
|
||||
# When bumping httpx, please check the version pins of
|
||||
# httpcore, anyio, and h11 in gen_requirements_all
|
||||
"httpx==0.28.1",
|
||||
|
2
requirements.txt
generated
2
requirements.txt
generated
@ -22,7 +22,7 @@ certifi>=2021.5.30
|
||||
ciso8601==2.3.2
|
||||
cronsim==2.6
|
||||
fnv-hash-fast==1.5.0
|
||||
hass-nabucasa==0.104.0
|
||||
hass-nabucasa==0.105.0
|
||||
httpx==0.28.1
|
||||
home-assistant-bluetooth==1.13.1
|
||||
ifaddr==0.2.0
|
||||
|
16
requirements_all.txt
generated
16
requirements_all.txt
generated
@ -185,7 +185,7 @@ aioairzone-cloud==0.6.12
|
||||
aioairzone==1.0.0
|
||||
|
||||
# homeassistant.components.alexa_devices
|
||||
aioamazondevices==3.2.2
|
||||
aioamazondevices==3.2.3
|
||||
|
||||
# homeassistant.components.ambient_network
|
||||
# homeassistant.components.ambient_station
|
||||
@ -414,7 +414,7 @@ aiotedee==0.2.25
|
||||
aiotractive==0.6.0
|
||||
|
||||
# homeassistant.components.unifi
|
||||
aiounifi==83
|
||||
aiounifi==84
|
||||
|
||||
# homeassistant.components.usb
|
||||
aiousbwatcher==1.1.1
|
||||
@ -1127,7 +1127,7 @@ habiticalib==0.4.0
|
||||
habluetooth==3.49.0
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.104.0
|
||||
hass-nabucasa==0.105.0
|
||||
|
||||
# homeassistant.components.splunk
|
||||
hass-splunk==0.1.1
|
||||
@ -1168,7 +1168,7 @@ hole==0.8.0
|
||||
holidays==0.75
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20250702.0
|
||||
home-assistant-frontend==20250702.1
|
||||
|
||||
# homeassistant.components.conversation
|
||||
home-assistant-intents==2025.6.23
|
||||
@ -1467,7 +1467,7 @@ mozart-api==4.1.1.116.4
|
||||
mullvad-api==1.0.0
|
||||
|
||||
# homeassistant.components.music_assistant
|
||||
music-assistant-client==1.2.3
|
||||
music-assistant-client==1.2.4
|
||||
|
||||
# homeassistant.components.tts
|
||||
mutagen==1.47.0
|
||||
@ -1962,7 +1962,7 @@ pyeiscp==0.0.7
|
||||
pyemoncms==0.1.1
|
||||
|
||||
# homeassistant.components.enphase_envoy
|
||||
pyenphase==2.1.0
|
||||
pyenphase==2.2.0
|
||||
|
||||
# homeassistant.components.envisalink
|
||||
pyenvisalink==4.7
|
||||
@ -3041,7 +3041,7 @@ vehicle==2.2.2
|
||||
velbus-aio==2025.5.0
|
||||
|
||||
# homeassistant.components.venstar
|
||||
venstarcolortouch==0.19
|
||||
venstarcolortouch==0.21
|
||||
|
||||
# homeassistant.components.vilfo
|
||||
vilfo-api-client==0.5.0
|
||||
@ -3190,7 +3190,7 @@ zeroconf==0.147.0
|
||||
zeversolar==0.3.2
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha==0.0.61
|
||||
zha==0.0.62
|
||||
|
||||
# homeassistant.components.zhong_hong
|
||||
zhong-hong-hvac==1.0.13
|
||||
|
16
requirements_test_all.txt
generated
16
requirements_test_all.txt
generated
@ -173,7 +173,7 @@ aioairzone-cloud==0.6.12
|
||||
aioairzone==1.0.0
|
||||
|
||||
# homeassistant.components.alexa_devices
|
||||
aioamazondevices==3.2.2
|
||||
aioamazondevices==3.2.3
|
||||
|
||||
# homeassistant.components.ambient_network
|
||||
# homeassistant.components.ambient_station
|
||||
@ -396,7 +396,7 @@ aiotedee==0.2.25
|
||||
aiotractive==0.6.0
|
||||
|
||||
# homeassistant.components.unifi
|
||||
aiounifi==83
|
||||
aiounifi==84
|
||||
|
||||
# homeassistant.components.usb
|
||||
aiousbwatcher==1.1.1
|
||||
@ -988,7 +988,7 @@ habiticalib==0.4.0
|
||||
habluetooth==3.49.0
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.104.0
|
||||
hass-nabucasa==0.105.0
|
||||
|
||||
# homeassistant.components.assist_satellite
|
||||
# homeassistant.components.conversation
|
||||
@ -1017,7 +1017,7 @@ hole==0.8.0
|
||||
holidays==0.75
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20250702.0
|
||||
home-assistant-frontend==20250702.1
|
||||
|
||||
# homeassistant.components.conversation
|
||||
home-assistant-intents==2025.6.23
|
||||
@ -1259,7 +1259,7 @@ mozart-api==4.1.1.116.4
|
||||
mullvad-api==1.0.0
|
||||
|
||||
# homeassistant.components.music_assistant
|
||||
music-assistant-client==1.2.3
|
||||
music-assistant-client==1.2.4
|
||||
|
||||
# homeassistant.components.tts
|
||||
mutagen==1.47.0
|
||||
@ -1637,7 +1637,7 @@ pyeiscp==0.0.7
|
||||
pyemoncms==0.1.1
|
||||
|
||||
# homeassistant.components.enphase_envoy
|
||||
pyenphase==2.1.0
|
||||
pyenphase==2.2.0
|
||||
|
||||
# homeassistant.components.everlights
|
||||
pyeverlights==0.1.0
|
||||
@ -2509,7 +2509,7 @@ vehicle==2.2.2
|
||||
velbus-aio==2025.5.0
|
||||
|
||||
# homeassistant.components.venstar
|
||||
venstarcolortouch==0.19
|
||||
venstarcolortouch==0.21
|
||||
|
||||
# homeassistant.components.vilfo
|
||||
vilfo-api-client==0.5.0
|
||||
@ -2634,7 +2634,7 @@ zeroconf==0.147.0
|
||||
zeversolar==0.3.2
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha==0.0.61
|
||||
zha==0.0.62
|
||||
|
||||
# homeassistant.components.zwave_js
|
||||
zwave-js-server-python==0.65.0
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Test the Remote Calendar config flow."""
|
||||
|
||||
from httpx import ConnectError, Response, UnsupportedProtocol
|
||||
from httpx import HTTPError, InvalidURL, Response, TimeoutException
|
||||
import pytest
|
||||
import respx
|
||||
|
||||
@ -75,10 +75,11 @@ async def test_form_import_webcal(hass: HomeAssistant, ics_content: str) -> None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("side_effect"),
|
||||
("side_effect", "base_error"),
|
||||
[
|
||||
ConnectError("Connection failed"),
|
||||
UnsupportedProtocol("Unsupported protocol"),
|
||||
(TimeoutException("Connection timed out"), "timeout_connect"),
|
||||
(HTTPError("Connection failed"), "cannot_connect"),
|
||||
(InvalidURL("Unsupported protocol"), "cannot_connect"),
|
||||
],
|
||||
)
|
||||
@respx.mock
|
||||
@ -86,6 +87,7 @@ async def test_form_inavild_url(
|
||||
hass: HomeAssistant,
|
||||
side_effect: Exception,
|
||||
ics_content: str,
|
||||
base_error: str,
|
||||
) -> None:
|
||||
"""Test we get the import form."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -102,7 +104,7 @@ async def test_form_inavild_url(
|
||||
},
|
||||
)
|
||||
assert result2["type"] is FlowResultType.FORM
|
||||
assert result2["errors"] == {"base": "cannot_connect"}
|
||||
assert result2["errors"] == {"base": base_error}
|
||||
respx.get(CALENDER_URL).mock(
|
||||
return_value=Response(
|
||||
status_code=200,
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Tests for init platform of Remote Calendar."""
|
||||
|
||||
from httpx import ConnectError, Response, UnsupportedProtocol
|
||||
from httpx import HTTPError, InvalidURL, Response, TimeoutException
|
||||
import pytest
|
||||
import respx
|
||||
|
||||
@ -56,8 +56,9 @@ async def test_raise_for_status(
|
||||
@pytest.mark.parametrize(
|
||||
"side_effect",
|
||||
[
|
||||
ConnectError("Connection failed"),
|
||||
UnsupportedProtocol("Unsupported protocol"),
|
||||
TimeoutException("Connection timed out"),
|
||||
HTTPError("Connection failed"),
|
||||
InvalidURL("Unsupported protocol"),
|
||||
ValueError("Invalid response"),
|
||||
],
|
||||
)
|
||||
|
@ -161,6 +161,7 @@ async def test_user_legacy(hass: HomeAssistant) -> None:
|
||||
assert result["data"][CONF_METHOD] == METHOD_LEGACY
|
||||
assert result["data"][CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
||||
assert result["data"][CONF_MODEL] is None
|
||||
assert result["data"][CONF_PORT] == 55000
|
||||
assert result["result"].unique_id is None
|
||||
|
||||
|
||||
@ -195,6 +196,7 @@ async def test_user_legacy_does_not_ok_first_time(hass: HomeAssistant) -> None:
|
||||
assert result3["data"][CONF_METHOD] == METHOD_LEGACY
|
||||
assert result3["data"][CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
||||
assert result3["data"][CONF_MODEL] is None
|
||||
assert result3["data"][CONF_PORT] == 55000
|
||||
assert result3["result"].unique_id is None
|
||||
|
||||
|
||||
@ -224,6 +226,7 @@ async def test_user_websocket(hass: HomeAssistant) -> None:
|
||||
assert result["data"][CONF_METHOD] == "websocket"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
||||
|
||||
|
||||
@ -272,6 +275,7 @@ async def test_user_encrypted_websocket(
|
||||
assert result4["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||
assert result4["data"][CONF_MANUFACTURER] == "Samsung"
|
||||
assert result4["data"][CONF_MODEL] == "UE48JU6400"
|
||||
assert result4["data"][CONF_PORT] == 8000
|
||||
assert result4["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION] is None
|
||||
assert result4["data"][CONF_TOKEN] == "037739871315caef138547b03e348b72"
|
||||
assert result4["data"][CONF_SESSION_ID] == "1"
|
||||
@ -402,6 +406,7 @@ async def test_user_websocket_auth_retry(hass: HomeAssistant) -> None:
|
||||
assert result["data"][CONF_HOST] == "10.20.43.21"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
||||
|
||||
|
||||
@ -464,6 +469,7 @@ async def test_ssdp(hass: HomeAssistant) -> None:
|
||||
assert result["data"][CONF_HOST] == "10.10.12.34"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||
assert result["data"][CONF_MODEL] == "UE55H6400"
|
||||
assert result["data"][CONF_PORT] == 55000
|
||||
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
||||
|
||||
|
||||
@ -522,6 +528,7 @@ async def test_ssdp_noprefix(hass: HomeAssistant) -> None:
|
||||
assert result["data"][CONF_HOST] == "10.10.12.34"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||
assert result["data"][CONF_MODEL] == "UE55H6400"
|
||||
assert result["data"][CONF_PORT] == 55000
|
||||
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
||||
|
||||
|
||||
@ -557,6 +564,7 @@ async def test_ssdp_legacy_missing_auth(hass: HomeAssistant) -> None:
|
||||
assert result["data"][CONF_HOST] == "10.10.12.34"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||
assert result["data"][CONF_MODEL] == "UE55H6400"
|
||||
assert result["data"][CONF_PORT] == 55000
|
||||
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
||||
|
||||
|
||||
@ -599,6 +607,7 @@ async def test_ssdp_websocket_success_populates_mac_address_and_ssdp_location(
|
||||
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
assert (
|
||||
result["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION]
|
||||
== "http://10.10.12.34:7676/smp_15_"
|
||||
@ -630,6 +639,7 @@ async def test_ssdp_websocket_success_populates_mac_address_and_main_tv_ssdp_loc
|
||||
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
assert (
|
||||
result["data"][CONF_SSDP_MAIN_TV_AGENT_LOCATION]
|
||||
== "http://10.10.12.34:7676/smp_2_"
|
||||
@ -681,6 +691,7 @@ async def test_ssdp_encrypted_websocket_success_populates_mac_address_and_ssdp_l
|
||||
assert result4["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||
assert result4["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||
assert result4["data"][CONF_MODEL] == "UE48JU6400"
|
||||
assert result4["data"][CONF_PORT] == 8000
|
||||
assert (
|
||||
result4["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION]
|
||||
== "http://10.10.12.34:7676/smp_15_"
|
||||
@ -887,6 +898,7 @@ async def test_dhcp_wireless(hass: HomeAssistant) -> None:
|
||||
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||
assert result["data"][CONF_MODEL] == "UE48JU6400"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
assert result["result"].unique_id == "223da676-497a-4e06-9507-5e27ec4f0fb3"
|
||||
|
||||
|
||||
@ -919,6 +931,7 @@ async def test_dhcp_wired(hass: HomeAssistant, rest_api: Mock) -> None:
|
||||
assert result["data"][CONF_MAC] == "aa:ee:tt:hh:ee:rr"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||
assert result["data"][CONF_MODEL] == "UE43LS003"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
||||
|
||||
|
||||
@ -1020,6 +1033,7 @@ async def test_zeroconf(hass: HomeAssistant) -> None:
|
||||
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
||||
|
||||
|
||||
@ -1129,6 +1143,7 @@ async def test_autodetect_websocket(hass: HomeAssistant) -> None:
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["data"][CONF_METHOD] == "websocket"
|
||||
assert result["data"][CONF_TOKEN] == "123456789"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
remote_websocket.assert_called_once_with(**AUTODETECT_WEBSOCKET_SSL)
|
||||
rest_api_class.assert_called_once_with(**DEVICEINFO_WEBSOCKET_SSL)
|
||||
await hass.async_block_till_done()
|
||||
@ -1180,6 +1195,7 @@ async def test_websocket_no_mac(hass: HomeAssistant, mac_address: Mock) -> None:
|
||||
assert result["data"][CONF_METHOD] == "websocket"
|
||||
assert result["data"][CONF_TOKEN] == "123456789"
|
||||
assert result["data"][CONF_MAC] == "gg:ee:tt:mm:aa:cc"
|
||||
assert result["data"][CONF_PORT] == 8002
|
||||
remote_websocket.assert_called_once_with(**AUTODETECT_WEBSOCKET_SSL)
|
||||
rest_api_class.assert_called_once_with(**DEVICEINFO_WEBSOCKET_SSL)
|
||||
await hass.async_block_till_done()
|
||||
@ -2091,6 +2107,7 @@ async def test_ssdp_update_mac(hass: HomeAssistant) -> None:
|
||||
assert entry.data[CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
||||
assert entry.data[CONF_MODEL] == "fake_model"
|
||||
assert entry.data[CONF_MAC] is None
|
||||
assert entry.data[CONF_PORT] == 8002
|
||||
assert entry.unique_id == "123"
|
||||
|
||||
device_info = deepcopy(MOCK_DEVICE_INFO)
|
||||
|
@ -63,7 +63,7 @@ async def test_options_flow(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result["data"][ATTR_PARSER] is None
|
||||
assert result["data"][ATTR_PARSER] == PARSER_PLAIN_TEXT
|
||||
|
||||
|
||||
async def test_reconfigure_flow_broadcast(
|
||||
|
@ -50,6 +50,7 @@ from homeassistant.components.telegram_bot.const import (
|
||||
ATTR_VERIFY_SSL,
|
||||
CONF_CONFIG_ENTRY_ID,
|
||||
DOMAIN,
|
||||
PARSER_PLAIN_TEXT,
|
||||
PLATFORM_BROADCAST,
|
||||
SECTION_ADVANCED_SETTINGS,
|
||||
SERVICE_ANSWER_CALLBACK_QUERY,
|
||||
@ -183,6 +184,7 @@ async def test_send_message(
|
||||
(
|
||||
{
|
||||
ATTR_MESSAGE: "test_message",
|
||||
ATTR_PARSER: PARSER_PLAIN_TEXT,
|
||||
ATTR_KEYBOARD_INLINE: "command1:/cmd1,/cmd2,mock_link:https://mock_link",
|
||||
},
|
||||
InlineKeyboardMarkup(
|
||||
@ -199,6 +201,7 @@ async def test_send_message(
|
||||
(
|
||||
{
|
||||
ATTR_MESSAGE: "test_message",
|
||||
ATTR_PARSER: PARSER_PLAIN_TEXT,
|
||||
ATTR_KEYBOARD_INLINE: [
|
||||
[["command1", "/cmd1"]],
|
||||
[["mock_link", "https://mock_link"]],
|
||||
@ -250,7 +253,7 @@ async def test_send_message_with_inline_keyboard(
|
||||
mock_send_message.assert_called_once_with(
|
||||
12345678,
|
||||
"test_message",
|
||||
parse_mode=ParseMode.MARKDOWN,
|
||||
parse_mode=None,
|
||||
disable_web_page_preview=None,
|
||||
disable_notification=False,
|
||||
reply_to_message_id=None,
|
||||
|
@ -168,7 +168,6 @@
|
||||
dict({
|
||||
'id': '0x0010',
|
||||
'name': 'cie_addr',
|
||||
'unsupported': False,
|
||||
'value': list([
|
||||
50,
|
||||
79,
|
||||
@ -181,68 +180,18 @@
|
||||
]),
|
||||
'zcl_type': 'EUI64',
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0013',
|
||||
'name': 'current_zone_sensitivity_level',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'uint8',
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0012',
|
||||
'name': 'num_zone_sensitivity_levels_supported',
|
||||
'unsupported': True,
|
||||
'value': None,
|
||||
'zcl_type': 'uint8',
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0011',
|
||||
'name': 'zone_id',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'uint8',
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0000',
|
||||
'name': 'zone_state',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'enum8',
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0002',
|
||||
'name': 'zone_status',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'map16',
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0001',
|
||||
'name': 'zone_type',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'uint16',
|
||||
}),
|
||||
]),
|
||||
'cluster_id': '0x0500',
|
||||
'endpoint_attribute': 'ias_zone',
|
||||
}),
|
||||
dict({
|
||||
'attributes': list([
|
||||
dict({
|
||||
'id': '0xfffd',
|
||||
'name': 'cluster_revision',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'uint16',
|
||||
}),
|
||||
dict({
|
||||
'id': '0xfffe',
|
||||
'name': 'reporting_status',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'enum8',
|
||||
}),
|
||||
]),
|
||||
'cluster_id': '0x0501',
|
||||
'endpoint_attribute': 'ias_ace',
|
||||
|
Loading…
x
Reference in New Issue
Block a user