Update rokuecp to 0.13.1 (#65814)
parent
2da4d280b2
commit
15e5f516d2
|
@ -152,6 +152,7 @@ homeassistant.components.remote.*
|
|||
homeassistant.components.renault.*
|
||||
homeassistant.components.ridwell.*
|
||||
homeassistant.components.rituals_perfume_genie.*
|
||||
homeassistant.components.roku.*
|
||||
homeassistant.components.rpi_power.*
|
||||
homeassistant.components.rtsp_to_webrtc.*
|
||||
homeassistant.components.samsungtv.*
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Support for Roku."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
import logging
|
||||
|
||||
from rokuecp import RokuConnectionError, RokuError
|
||||
|
@ -46,10 +47,10 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return unload_ok
|
||||
|
||||
|
||||
def roku_exception_handler(func):
|
||||
def roku_exception_handler(func: Callable) -> Callable:
|
||||
"""Decorate Roku calls to handle Roku exceptions."""
|
||||
|
||||
async def handler(self, *args, **kwargs):
|
||||
async def handler(self, *args, **kwargs) -> None: # type: ignore
|
||||
try:
|
||||
await func(self, *args, **kwargs)
|
||||
except RokuConnectionError as error:
|
||||
|
|
|
@ -69,12 +69,12 @@ def get_thumbnail_url_full(
|
|||
|
||||
|
||||
async def async_browse_media(
|
||||
hass,
|
||||
hass: HomeAssistant,
|
||||
coordinator: RokuDataUpdateCoordinator,
|
||||
get_browse_image_url: GetBrowseImageUrlType,
|
||||
media_content_id: str | None,
|
||||
media_content_type: str | None,
|
||||
):
|
||||
) -> BrowseMedia:
|
||||
"""Browse media."""
|
||||
if media_content_id is None:
|
||||
return await root_payload(
|
||||
|
@ -113,7 +113,7 @@ async def root_payload(
|
|||
hass: HomeAssistant,
|
||||
coordinator: RokuDataUpdateCoordinator,
|
||||
get_browse_image_url: GetBrowseImageUrlType,
|
||||
):
|
||||
) -> BrowseMedia:
|
||||
"""Return root payload for Roku."""
|
||||
device = coordinator.data
|
||||
|
||||
|
@ -223,7 +223,7 @@ def item_payload(
|
|||
item: dict,
|
||||
coordinator: RokuDataUpdateCoordinator,
|
||||
get_browse_image_url: GetBrowseImageUrlType,
|
||||
):
|
||||
) -> BrowseMedia:
|
||||
"""
|
||||
Create response payload for a single media item.
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from rokuecp import Roku, RokuError
|
||||
|
@ -24,7 +25,7 @@ ERROR_UNKNOWN = "unknown"
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def validate_input(hass: HomeAssistant, data: dict) -> dict:
|
||||
async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Validate the user input allows us to connect.
|
||||
|
||||
Data has the keys from DATA_SCHEMA with values provided by the user.
|
||||
|
@ -44,12 +45,14 @@ class RokuConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||
|
||||
VERSION = 1
|
||||
|
||||
def __init__(self):
|
||||
discovery_info: dict[str, Any]
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Set up the instance."""
|
||||
self.discovery_info = {}
|
||||
|
||||
@callback
|
||||
def _show_form(self, errors: dict | None = None) -> FlowResult:
|
||||
def _show_form(self, errors: dict[str, Any] | None = None) -> FlowResult:
|
||||
"""Show the form to the user."""
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
|
@ -57,7 +60,9 @@ class RokuConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||
errors=errors or {},
|
||||
)
|
||||
|
||||
async def async_step_user(self, user_input: dict | None = None) -> FlowResult:
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Handle a flow initialized by the user."""
|
||||
if not user_input:
|
||||
return self._show_form()
|
||||
|
|
|
@ -17,7 +17,7 @@ class RokuEntity(CoordinatorEntity):
|
|||
def __init__(
|
||||
self,
|
||||
*,
|
||||
device_id: str,
|
||||
device_id: str | None,
|
||||
coordinator: RokuDataUpdateCoordinator,
|
||||
description: EntityDescription | None = None,
|
||||
) -> None:
|
||||
|
@ -28,10 +28,11 @@ class RokuEntity(CoordinatorEntity):
|
|||
if description is not None:
|
||||
self.entity_description = description
|
||||
self._attr_name = f"{coordinator.data.info.name} {description.name}"
|
||||
self._attr_unique_id = f"{device_id}_{description.key}"
|
||||
if device_id is not None:
|
||||
self._attr_unique_id = f"{device_id}_{description.key}"
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
def device_info(self) -> DeviceInfo | None:
|
||||
"""Return device information about this Roku device."""
|
||||
if self._device_id is None:
|
||||
return None
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"domain": "roku",
|
||||
"name": "Roku",
|
||||
"documentation": "https://www.home-assistant.io/integrations/roku",
|
||||
"requirements": ["rokuecp==0.12.0"],
|
||||
"requirements": ["rokuecp==0.13.1"],
|
||||
"homekit": {
|
||||
"models": ["3810X", "4660X", "7820X", "C105X", "C135X"]
|
||||
},
|
||||
|
|
|
@ -117,7 +117,9 @@ async def async_setup_entry(
|
|||
class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
||||
"""Representation of a Roku media player on the network."""
|
||||
|
||||
def __init__(self, unique_id: str, coordinator: RokuDataUpdateCoordinator) -> None:
|
||||
def __init__(
|
||||
self, unique_id: str | None, coordinator: RokuDataUpdateCoordinator
|
||||
) -> None:
|
||||
"""Initialize the Roku device."""
|
||||
super().__init__(
|
||||
coordinator=coordinator,
|
||||
|
@ -231,7 +233,7 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
|||
@property
|
||||
def media_duration(self) -> int | None:
|
||||
"""Duration of current playing media in seconds."""
|
||||
if self._media_playback_trackable():
|
||||
if self.coordinator.data.media is not None and self._media_playback_trackable():
|
||||
return self.coordinator.data.media.duration
|
||||
|
||||
return None
|
||||
|
@ -239,7 +241,7 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
|||
@property
|
||||
def media_position(self) -> int | None:
|
||||
"""Position of current playing media in seconds."""
|
||||
if self._media_playback_trackable():
|
||||
if self.coordinator.data.media is not None and self._media_playback_trackable():
|
||||
return self.coordinator.data.media.position
|
||||
|
||||
return None
|
||||
|
@ -247,7 +249,7 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
|||
@property
|
||||
def media_position_updated_at(self) -> dt.datetime | None:
|
||||
"""When was the position of the current playing media valid."""
|
||||
if self._media_playback_trackable():
|
||||
if self.coordinator.data.media is not None and self._media_playback_trackable():
|
||||
return self.coordinator.data.media.at
|
||||
|
||||
return None
|
||||
|
@ -263,10 +265,12 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
|||
@property
|
||||
def source_list(self) -> list:
|
||||
"""List of available input sources."""
|
||||
return ["Home"] + sorted(app.name for app in self.coordinator.data.apps)
|
||||
return ["Home"] + sorted(
|
||||
app.name for app in self.coordinator.data.apps if app.name is not None
|
||||
)
|
||||
|
||||
@roku_exception_handler
|
||||
async def search(self, keyword):
|
||||
async def search(self, keyword: str) -> None:
|
||||
"""Emulate opening the search screen and entering the search keyword."""
|
||||
await self.coordinator.roku.search(keyword)
|
||||
|
||||
|
@ -343,7 +347,7 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
|||
await self.coordinator.async_request_refresh()
|
||||
|
||||
@roku_exception_handler
|
||||
async def async_mute_volume(self, mute) -> None:
|
||||
async def async_mute_volume(self, mute: bool) -> None:
|
||||
"""Mute the volume."""
|
||||
await self.coordinator.roku.remote("volume_mute")
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
@ -359,7 +363,9 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
|||
await self.coordinator.roku.remote("volume_down")
|
||||
|
||||
@roku_exception_handler
|
||||
async def async_play_media(self, media_type: str, media_id: str, **kwargs) -> None:
|
||||
async def async_play_media(
|
||||
self, media_type: str, media_id: str, **kwargs: Any
|
||||
) -> None:
|
||||
"""Play media from a URL or file, launch an application, or tune to a channel."""
|
||||
extra: dict[str, Any] = kwargs.get(ATTR_MEDIA_EXTRA) or {}
|
||||
|
||||
|
@ -433,7 +439,6 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
|||
None,
|
||||
)
|
||||
|
||||
if appl is not None:
|
||||
if appl is not None and appl.app_id is not None:
|
||||
await self.coordinator.roku.launch(appl.app_id)
|
||||
|
||||
await self.coordinator.async_request_refresh()
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
"""Support for the Roku remote."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.remote import ATTR_NUM_REPEATS, RemoteEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -42,19 +44,19 @@ class RokuRemote(RokuEntity, RemoteEntity):
|
|||
return not self.coordinator.data.state.standby
|
||||
|
||||
@roku_exception_handler
|
||||
async def async_turn_on(self, **kwargs) -> None:
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the device on."""
|
||||
await self.coordinator.roku.remote("poweron")
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
@roku_exception_handler
|
||||
async def async_turn_off(self, **kwargs) -> None:
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the device off."""
|
||||
await self.coordinator.roku.remote("poweroff")
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
@roku_exception_handler
|
||||
async def async_send_command(self, command: list, **kwargs) -> None:
|
||||
async def async_send_command(self, command: list, **kwargs: Any) -> None:
|
||||
"""Send a command to one device."""
|
||||
num_repeats = kwargs[ATTR_NUM_REPEATS]
|
||||
|
||||
|
|
11
mypy.ini
11
mypy.ini
|
@ -1489,6 +1489,17 @@ no_implicit_optional = true
|
|||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
|
||||
[mypy-homeassistant.components.roku.*]
|
||||
check_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
disallow_subclassing_any = true
|
||||
disallow_untyped_calls = true
|
||||
disallow_untyped_decorators = true
|
||||
disallow_untyped_defs = true
|
||||
no_implicit_optional = true
|
||||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
|
||||
[mypy-homeassistant.components.rpi_power.*]
|
||||
check_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
|
|
|
@ -2111,7 +2111,7 @@ rjpl==0.3.6
|
|||
rocketchat-API==0.6.1
|
||||
|
||||
# homeassistant.components.roku
|
||||
rokuecp==0.12.0
|
||||
rokuecp==0.13.1
|
||||
|
||||
# homeassistant.components.roomba
|
||||
roombapy==1.6.5
|
||||
|
|
|
@ -1300,7 +1300,7 @@ rflink==0.0.62
|
|||
ring_doorbell==0.7.2
|
||||
|
||||
# homeassistant.components.roku
|
||||
rokuecp==0.12.0
|
||||
rokuecp==0.13.1
|
||||
|
||||
# homeassistant.components.roomba
|
||||
roombapy==1.6.5
|
||||
|
|
Loading…
Reference in New Issue