mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Fix doorbird models are missing the schedule API (#123033)
* Fix doorbird models are missing the schedule API fixes #122997 * cover
This commit is contained in:
parent
fef9c92eb7
commit
a3b5dcc21b
@ -5,9 +5,11 @@ from __future__ import annotations
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from aiohttp import ClientResponseError
|
||||||
from doorbirdpy import (
|
from doorbirdpy import (
|
||||||
DoorBird,
|
DoorBird,
|
||||||
DoorBirdScheduleEntry,
|
DoorBirdScheduleEntry,
|
||||||
@ -170,15 +172,21 @@ class ConfiguredDoorBird:
|
|||||||
) -> DoorbirdEventConfig:
|
) -> DoorbirdEventConfig:
|
||||||
"""Get events and unconfigured favorites from http favorites."""
|
"""Get events and unconfigured favorites from http favorites."""
|
||||||
device = self.device
|
device = self.device
|
||||||
|
events: list[DoorbirdEvent] = []
|
||||||
|
unconfigured_favorites: defaultdict[str, list[str]] = defaultdict(list)
|
||||||
|
try:
|
||||||
schedule = await device.schedule()
|
schedule = await device.schedule()
|
||||||
|
except ClientResponseError as ex:
|
||||||
|
if ex.status == HTTPStatus.NOT_FOUND:
|
||||||
|
# D301 models do not support schedules
|
||||||
|
return DoorbirdEventConfig(events, [], unconfigured_favorites)
|
||||||
|
raise
|
||||||
favorite_input_type = {
|
favorite_input_type = {
|
||||||
output.param: entry.input
|
output.param: entry.input
|
||||||
for entry in schedule
|
for entry in schedule
|
||||||
for output in entry.output
|
for output in entry.output
|
||||||
if output.event == HTTP_EVENT_TYPE
|
if output.event == HTTP_EVENT_TYPE
|
||||||
}
|
}
|
||||||
events: list[DoorbirdEvent] = []
|
|
||||||
unconfigured_favorites: defaultdict[str, list[str]] = defaultdict(list)
|
|
||||||
default_event_types = {
|
default_event_types = {
|
||||||
self._get_event_name(event): event_type
|
self._get_event_name(event): event_type
|
||||||
for event, event_type in DEFAULT_EVENT_TYPES
|
for event, event_type in DEFAULT_EVENT_TYPES
|
||||||
|
@ -47,31 +47,30 @@ def get_mock_doorbird_api(
|
|||||||
info: dict[str, Any] | None = None,
|
info: dict[str, Any] | None = None,
|
||||||
info_side_effect: Exception | None = None,
|
info_side_effect: Exception | None = None,
|
||||||
schedule: list[DoorBirdScheduleEntry] | None = None,
|
schedule: list[DoorBirdScheduleEntry] | None = None,
|
||||||
|
schedule_side_effect: Exception | None = None,
|
||||||
favorites: dict[str, dict[str, Any]] | None = None,
|
favorites: dict[str, dict[str, Any]] | None = None,
|
||||||
favorites_side_effect: Exception | None = None,
|
favorites_side_effect: Exception | None = None,
|
||||||
change_schedule: tuple[bool, int] | None = None,
|
change_schedule: tuple[bool, int] | None = None,
|
||||||
) -> DoorBird:
|
) -> DoorBird:
|
||||||
"""Return a mock DoorBirdAPI object with return values."""
|
"""Return a mock DoorBirdAPI object with return values."""
|
||||||
doorbirdapi_mock = MagicMock(spec_set=DoorBird)
|
doorbirdapi_mock = MagicMock(spec_set=DoorBird)
|
||||||
type(doorbirdapi_mock).info = AsyncMock(
|
api_mock_type = type(doorbirdapi_mock)
|
||||||
side_effect=info_side_effect, return_value=info
|
api_mock_type.info = AsyncMock(side_effect=info_side_effect, return_value=info)
|
||||||
|
api_mock_type.favorites = AsyncMock(
|
||||||
|
side_effect=favorites_side_effect, return_value=favorites
|
||||||
)
|
)
|
||||||
type(doorbirdapi_mock).favorites = AsyncMock(
|
api_mock_type.change_favorite = AsyncMock(return_value=True)
|
||||||
side_effect=favorites_side_effect,
|
api_mock_type.change_schedule = AsyncMock(
|
||||||
return_value=favorites,
|
|
||||||
)
|
|
||||||
type(doorbirdapi_mock).change_favorite = AsyncMock(return_value=True)
|
|
||||||
type(doorbirdapi_mock).change_schedule = AsyncMock(
|
|
||||||
return_value=change_schedule or (True, 200)
|
return_value=change_schedule or (True, 200)
|
||||||
)
|
)
|
||||||
type(doorbirdapi_mock).schedule = AsyncMock(return_value=schedule)
|
api_mock_type.schedule = AsyncMock(
|
||||||
type(doorbirdapi_mock).energize_relay = AsyncMock(return_value=True)
|
return_value=schedule, side_effect=schedule_side_effect
|
||||||
type(doorbirdapi_mock).turn_light_on = AsyncMock(return_value=True)
|
|
||||||
type(doorbirdapi_mock).delete_favorite = AsyncMock(return_value=True)
|
|
||||||
type(doorbirdapi_mock).get_image = AsyncMock(return_value=b"image")
|
|
||||||
type(doorbirdapi_mock).doorbell_state = AsyncMock(
|
|
||||||
side_effect=mock_unauthorized_exception()
|
|
||||||
)
|
)
|
||||||
|
api_mock_type.energize_relay = AsyncMock(return_value=True)
|
||||||
|
api_mock_type.turn_light_on = AsyncMock(return_value=True)
|
||||||
|
api_mock_type.delete_favorite = AsyncMock(return_value=True)
|
||||||
|
api_mock_type.get_image = AsyncMock(return_value=b"image")
|
||||||
|
api_mock_type.doorbell_state = AsyncMock(side_effect=mock_unauthorized_exception())
|
||||||
return doorbirdapi_mock
|
return doorbirdapi_mock
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,6 +102,7 @@ async def doorbird_mocker(
|
|||||||
info: dict[str, Any] | None = None,
|
info: dict[str, Any] | None = None,
|
||||||
info_side_effect: Exception | None = None,
|
info_side_effect: Exception | None = None,
|
||||||
schedule: list[DoorBirdScheduleEntry] | None = None,
|
schedule: list[DoorBirdScheduleEntry] | None = None,
|
||||||
|
schedule_side_effect: Exception | None = None,
|
||||||
favorites: dict[str, dict[str, Any]] | None = None,
|
favorites: dict[str, dict[str, Any]] | None = None,
|
||||||
favorites_side_effect: Exception | None = None,
|
favorites_side_effect: Exception | None = None,
|
||||||
options: dict[str, Any] | None = None,
|
options: dict[str, Any] | None = None,
|
||||||
@ -118,6 +119,7 @@ async def doorbird_mocker(
|
|||||||
info=info or doorbird_info,
|
info=info or doorbird_info,
|
||||||
info_side_effect=info_side_effect,
|
info_side_effect=info_side_effect,
|
||||||
schedule=schedule or doorbird_schedule,
|
schedule=schedule or doorbird_schedule,
|
||||||
|
schedule_side_effect=schedule_side_effect,
|
||||||
favorites=favorites or doorbird_favorites,
|
favorites=favorites or doorbird_favorites,
|
||||||
favorites_side_effect=favorites_side_effect,
|
favorites_side_effect=favorites_side_effect,
|
||||||
change_schedule=change_schedule,
|
change_schedule=change_schedule,
|
||||||
|
@ -56,6 +56,16 @@ async def test_http_favorites_request_fails(
|
|||||||
assert doorbird_entry.entry.state is ConfigEntryState.SETUP_RETRY
|
assert doorbird_entry.entry.state is ConfigEntryState.SETUP_RETRY
|
||||||
|
|
||||||
|
|
||||||
|
async def test_http_schedule_api_missing(
|
||||||
|
doorbird_mocker: DoorbirdMockerType,
|
||||||
|
) -> None:
|
||||||
|
"""Test missing the schedule API is non-fatal as not all models support it."""
|
||||||
|
doorbird_entry = await doorbird_mocker(
|
||||||
|
schedule_side_effect=mock_not_found_exception()
|
||||||
|
)
|
||||||
|
assert doorbird_entry.entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
|
||||||
async def test_events_changed(
|
async def test_events_changed(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
doorbird_mocker: DoorbirdMockerType,
|
doorbird_mocker: DoorbirdMockerType,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user