From 0cb61b628d1a82e5fd26790fcf625866727c59f3 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sat, 3 Jul 2021 15:37:54 +0200 Subject: [PATCH] Improve typing in Sony Bravia TV integration (#52438) * Strict typing * Variables typing * Suggested change * Fix pylint * Use suppress instead of try..except * Remove unused variables * Suggested change * Fix pylint * Fix typing for unique_id --- .strict-typing | 1 + homeassistant/components/braviatv/__init__.py | 100 ++++++++++-------- .../components/braviatv/config_flow.py | 67 +++++++----- homeassistant/components/braviatv/const.py | 24 +++-- .../components/braviatv/media_player.py | 69 +++++++----- homeassistant/components/braviatv/remote.py | 36 +++++-- mypy.ini | 11 ++ 7 files changed, 195 insertions(+), 113 deletions(-) diff --git a/.strict-typing b/.strict-typing index 7d2f83a0e8d..dbf25ac927e 100644 --- a/.strict-typing +++ b/.strict-typing @@ -18,6 +18,7 @@ homeassistant.components.automation.* homeassistant.components.binary_sensor.* homeassistant.components.bluetooth_tracker.* homeassistant.components.bond.* +homeassistant.components.braviatv.* homeassistant.components.brother.* homeassistant.components.calendar.* homeassistant.components.camera.* diff --git a/homeassistant/components/braviatv/__init__.py b/homeassistant/components/braviatv/__init__.py index eecf8533800..744c856a143 100644 --- a/homeassistant/components/braviatv/__init__.py +++ b/homeassistant/components/braviatv/__init__.py @@ -1,14 +1,20 @@ """The Bravia TV component.""" +from __future__ import annotations + import asyncio +from collections.abc import Iterable from datetime import timedelta import logging +from typing import Final from bravia_tv import BraviaRC from bravia_tv.braviarc import NoIPControl from homeassistant.components.media_player import DOMAIN as MEDIA_PLAYER_DOMAIN from homeassistant.components.remote import DOMAIN as REMOTE_DOMAIN +from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PIN +from homeassistant.core import HomeAssistant from homeassistant.helpers.debounce import Debouncer from homeassistant.helpers.update_coordinator import DataUpdateCoordinator @@ -16,11 +22,11 @@ from .const import CLIENTID_PREFIX, CONF_IGNORED_SOURCES, DOMAIN, NICKNAME _LOGGER = logging.getLogger(__name__) -PLATFORMS = [MEDIA_PLAYER_DOMAIN, REMOTE_DOMAIN] -SCAN_INTERVAL = timedelta(seconds=10) +PLATFORMS: Final[list[str]] = [MEDIA_PLAYER_DOMAIN, REMOTE_DOMAIN] +SCAN_INTERVAL: Final = timedelta(seconds=10) -async def async_setup_entry(hass, config_entry): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Set up a config entry.""" host = config_entry.data[CONF_HOST] mac = config_entry.data[CONF_MAC] @@ -40,7 +46,7 @@ async def async_setup_entry(hass, config_entry): return True -async def async_unload_entry(hass, config_entry): +async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Unload a config entry.""" unload_ok = await hass.config_entries.async_unload_platforms( config_entry, PLATFORMS @@ -52,7 +58,7 @@ async def async_unload_entry(hass, config_entry): return unload_ok -async def update_listener(hass, config_entry): +async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry) -> None: """Handle options update.""" await hass.config_entries.async_reload(config_entry.entry_id) @@ -64,28 +70,33 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): several platforms. """ - def __init__(self, hass, host, mac, pin, ignored_sources): + def __init__( + self, + hass: HomeAssistant, + host: str, + mac: str, + pin: str, + ignored_sources: list[str], + ) -> None: """Initialize Bravia TV Client.""" self.braviarc = BraviaRC(host, mac) self.pin = pin self.ignored_sources = ignored_sources - self.muted = False - self.channel_name = None - self.channel_number = None - self.media_title = None - self.source = None - self.source_list = [] - self.original_content_list = [] - self.content_mapping = {} - self.duration = None - self.content_uri = None - self.start_date_time = None - self.program_media_type = None - self.audio_output = None - self.min_volume = None - self.max_volume = None - self.volume_level = None + self.muted: bool = False + self.channel_name: str | None = None + self.media_title: str | None = None + self.source: str | None = None + self.source_list: list[str] = [] + self.original_content_list: list[str] = [] + self.content_mapping: dict[str, str] = {} + self.duration: int | None = None + self.content_uri: str | None = None + self.program_media_type: str | None = None + self.audio_output: str | None = None + self.min_volume: int | None = None + self.max_volume: int | None = None + self.volume_level: float | None = None self.is_on = False # Assume that the TV is in Play mode self.playing = True @@ -101,19 +112,20 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): ), ) - def _send_command(self, command, repeats=1): + def _send_command(self, command: str, repeats: int = 1) -> None: """Send a command to the TV.""" for _ in range(repeats): for cmd in command: self.braviarc.send_command(cmd) - def _get_source(self): + def _get_source(self) -> str | None: """Return the name of the source.""" for key, value in self.content_mapping.items(): if value == self.content_uri: return key + return None - def _refresh_volume(self): + def _refresh_volume(self) -> bool: """Refresh volume information.""" volume_info = self.braviarc.get_volume_info(self.audio_output) if volume_info is not None: @@ -122,11 +134,11 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): self.audio_output = volume_info.get("target") self.min_volume = volume_info.get("minVolume") self.max_volume = volume_info.get("maxVolume") - self.muted = volume_info.get("mute") + self.muted = volume_info.get("mute", False) return True return False - def _refresh_channels(self): + def _refresh_channels(self) -> bool: """Refresh source and channels list.""" if not self.source_list: self.content_mapping = self.braviarc.load_source_list() @@ -138,17 +150,15 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): self.source_list.append(key) return True - def _refresh_playing_info(self): + def _refresh_playing_info(self) -> None: """Refresh playing information.""" playing_info = self.braviarc.get_playing_info() program_name = playing_info.get("programTitle") self.channel_name = playing_info.get("title") self.program_media_type = playing_info.get("programMediaType") - self.channel_number = playing_info.get("dispNum") self.content_uri = playing_info.get("uri") self.source = self._get_source() self.duration = playing_info.get("durationSec") - self.start_date_time = playing_info.get("startDateTime") if not playing_info: self.channel_name = "App" if self.channel_name is not None: @@ -158,7 +168,7 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): else: self.media_title = None - def _update_tv_data(self): + def _update_tv_data(self) -> None: """Connect and update TV info.""" power_status = self.braviarc.get_power_status() @@ -182,26 +192,26 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): self.is_on = False - async def _async_update_data(self): + async def _async_update_data(self) -> None: """Fetch the latest data.""" if self.state_lock.locked(): return await self.hass.async_add_executor_job(self._update_tv_data) - async def async_turn_on(self): + async def async_turn_on(self) -> None: """Turn the device on.""" async with self.state_lock: await self.hass.async_add_executor_job(self.braviarc.turn_on) await self.async_request_refresh() - async def async_turn_off(self): + async def async_turn_off(self) -> None: """Turn off device.""" async with self.state_lock: await self.hass.async_add_executor_job(self.braviarc.turn_off) await self.async_request_refresh() - async def async_set_volume_level(self, volume): + async def async_set_volume_level(self, volume: float) -> None: """Set volume level, range 0..1.""" async with self.state_lock: await self.hass.async_add_executor_job( @@ -209,7 +219,7 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): ) await self.async_request_refresh() - async def async_volume_up(self): + async def async_volume_up(self) -> None: """Send volume up command to device.""" async with self.state_lock: await self.hass.async_add_executor_job( @@ -217,7 +227,7 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): ) await self.async_request_refresh() - async def async_volume_down(self): + async def async_volume_down(self) -> None: """Send volume down command to device.""" async with self.state_lock: await self.hass.async_add_executor_job( @@ -225,46 +235,46 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): ) await self.async_request_refresh() - async def async_volume_mute(self, mute): + async def async_volume_mute(self, mute: bool) -> None: """Send mute command to device.""" async with self.state_lock: await self.hass.async_add_executor_job(self.braviarc.mute_volume, mute) await self.async_request_refresh() - async def async_media_play(self): + async def async_media_play(self) -> None: """Send play command to device.""" async with self.state_lock: await self.hass.async_add_executor_job(self.braviarc.media_play) self.playing = True await self.async_request_refresh() - async def async_media_pause(self): + async def async_media_pause(self) -> None: """Send pause command to device.""" async with self.state_lock: await self.hass.async_add_executor_job(self.braviarc.media_pause) self.playing = False await self.async_request_refresh() - async def async_media_stop(self): + async def async_media_stop(self) -> None: """Send stop command to device.""" async with self.state_lock: await self.hass.async_add_executor_job(self.braviarc.media_stop) self.playing = False await self.async_request_refresh() - async def async_media_next_track(self): + async def async_media_next_track(self) -> None: """Send next track command.""" async with self.state_lock: await self.hass.async_add_executor_job(self.braviarc.media_next_track) await self.async_request_refresh() - async def async_media_previous_track(self): + async def async_media_previous_track(self) -> None: """Send previous track command.""" async with self.state_lock: await self.hass.async_add_executor_job(self.braviarc.media_previous_track) await self.async_request_refresh() - async def async_select_source(self, source): + async def async_select_source(self, source: str) -> None: """Set the input source.""" if source in self.content_mapping: uri = self.content_mapping[source] @@ -272,7 +282,7 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]): await self.hass.async_add_executor_job(self.braviarc.play_content, uri) await self.async_request_refresh() - async def async_send_command(self, command, repeats): + async def async_send_command(self, command: Iterable[str], repeats: int) -> None: """Send command to device.""" async with self.state_lock: await self.hass.async_add_executor_job(self._send_command, command, repeats) diff --git a/homeassistant/components/braviatv/config_flow.py b/homeassistant/components/braviatv/config_flow.py index 0813a3e52c5..159f3806d61 100644 --- a/homeassistant/components/braviatv/config_flow.py +++ b/homeassistant/components/braviatv/config_flow.py @@ -1,14 +1,20 @@ """Adds config flow for Bravia TV integration.""" +from __future__ import annotations + +from contextlib import suppress import ipaddress import re +from typing import Any from bravia_tv import BraviaRC from bravia_tv.braviarc import NoIPControl import voluptuous as vol from homeassistant import config_entries, exceptions +from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PIN from homeassistant.core import callback +from homeassistant.data_entry_flow import FlowResult import homeassistant.helpers.config_validation as cv from .const import ( @@ -22,14 +28,13 @@ from .const import ( ) -def host_valid(host): +def host_valid(host: str) -> bool: """Return True if hostname or IP address is valid.""" - try: + with suppress(ValueError): if ipaddress.ip_address(host).version in [4, 6]: return True - except ValueError: - disallowed = re.compile(r"[^a-zA-Z\d\-]") - return all(x and not disallowed.search(x) for x in host.split(".")) + disallowed = re.compile(r"[^a-zA-Z\d\-]") + return all(x and not disallowed.search(x) for x in host.split(".")) class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): @@ -37,15 +42,16 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 - def __init__(self): + def __init__(self) -> None: """Initialize.""" - self.braviarc = None - self.host = None - self.title = None - self.mac = None + self.braviarc: BraviaRC | None = None + self.host: str | None = None + self.title = "" + self.mac: str | None = None - async def init_device(self, pin): + async def init_device(self, pin: str) -> None: """Initialize Bravia TV device.""" + assert self.braviarc is not None await self.hass.async_add_executor_job( self.braviarc.connect, pin, CLIENTID_PREFIX, NICKNAME ) @@ -68,13 +74,15 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): @staticmethod @callback - def async_get_options_flow(config_entry): + def async_get_options_flow(config_entry: ConfigEntry) -> BraviaTVOptionsFlowHandler: """Bravia TV options callback.""" return BraviaTVOptionsFlowHandler(config_entry) - async def async_step_user(self, user_input=None): + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle the initial step.""" - errors = {} + errors: dict[str, str] = {} if user_input is not None: if host_valid(user_input[CONF_HOST]): @@ -91,9 +99,11 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): errors=errors, ) - async def async_step_authorize(self, user_input=None): + async def async_step_authorize( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Get PIN from the Bravia TV device.""" - errors = {} + errors: dict[str, str] = {} if user_input is not None: try: @@ -106,9 +116,9 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): user_input[CONF_HOST] = self.host user_input[CONF_MAC] = self.mac return self.async_create_entry(title=self.title, data=user_input) - # Connecting with th PIN "0000" to start the pairing process on the TV. try: + assert self.braviarc is not None await self.hass.async_add_executor_job( self.braviarc.connect, "0000", CLIENTID_PREFIX, NICKNAME ) @@ -125,31 +135,34 @@ class BraviaTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): class BraviaTVOptionsFlowHandler(config_entries.OptionsFlow): """Config flow options for Bravia TV.""" - def __init__(self, config_entry): + def __init__(self, config_entry: ConfigEntry) -> None: """Initialize Bravia TV options flow.""" - self.braviarc = None self.config_entry = config_entry self.pin = config_entry.data[CONF_PIN] self.ignored_sources = config_entry.options.get(CONF_IGNORED_SOURCES) - self.source_list = [] + self.source_list: dict[str, str] = {} - async def async_step_init(self, user_input=None): + async def async_step_init( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Manage the options.""" coordinator = self.hass.data[DOMAIN][self.config_entry.entry_id] - self.braviarc = coordinator.braviarc - connected = await self.hass.async_add_executor_job(self.braviarc.is_connected) + braviarc = coordinator.braviarc + connected = await self.hass.async_add_executor_job(braviarc.is_connected) if not connected: await self.hass.async_add_executor_job( - self.braviarc.connect, self.pin, CLIENTID_PREFIX, NICKNAME + braviarc.connect, self.pin, CLIENTID_PREFIX, NICKNAME ) content_mapping = await self.hass.async_add_executor_job( - self.braviarc.load_source_list + braviarc.load_source_list ) - self.source_list = [*content_mapping] + self.source_list = {item: item for item in [*content_mapping]} return await self.async_step_user() - async def async_step_user(self, user_input=None): + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle a flow initialized by the user.""" if user_input is not None: return self.async_create_entry(title="", data=user_input) diff --git a/homeassistant/components/braviatv/const.py b/homeassistant/components/braviatv/const.py index 1fa96e6a98d..01746cbe963 100644 --- a/homeassistant/components/braviatv/const.py +++ b/homeassistant/components/braviatv/const.py @@ -1,13 +1,17 @@ """Constants for Bravia TV integration.""" -ATTR_CID = "cid" -ATTR_MAC = "macAddr" -ATTR_MANUFACTURER = "Sony" -ATTR_MODEL = "model" +from __future__ import annotations -CONF_IGNORED_SOURCES = "ignored_sources" +from typing import Final -BRAVIA_CONFIG_FILE = "bravia.conf" -CLIENTID_PREFIX = "HomeAssistant" -DEFAULT_NAME = f"{ATTR_MANUFACTURER} Bravia TV" -DOMAIN = "braviatv" -NICKNAME = "Home Assistant" +ATTR_CID: Final = "cid" +ATTR_MAC: Final = "macAddr" +ATTR_MANUFACTURER: Final = "Sony" +ATTR_MODEL: Final = "model" + +CONF_IGNORED_SOURCES: Final = "ignored_sources" + +BRAVIA_CONFIG_FILE: Final = "bravia.conf" +CLIENTID_PREFIX: Final = "HomeAssistant" +DEFAULT_NAME: Final = f"{ATTR_MANUFACTURER} Bravia TV" +DOMAIN: Final = "braviatv" +NICKNAME: Final = "Home Assistant" diff --git a/homeassistant/components/braviatv/media_player.py b/homeassistant/components/braviatv/media_player.py index dda5b005497..8528e3649c1 100644 --- a/homeassistant/components/braviatv/media_player.py +++ b/homeassistant/components/braviatv/media_player.py @@ -1,4 +1,8 @@ """Support for interface with a Bravia TV.""" +from __future__ import annotations + +from typing import Final + from homeassistant.components.media_player import DEVICE_CLASS_TV, MediaPlayerEntity from homeassistant.components.media_player.const import ( SUPPORT_NEXT_TRACK, @@ -13,12 +17,17 @@ from homeassistant.components.media_player.const import ( SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP, ) +from homeassistant.config_entries import ConfigEntry from homeassistant.const import STATE_OFF, STATE_PAUSED, STATE_PLAYING +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity +from . import BraviaTVCoordinator from .const import ATTR_MANUFACTURER, DEFAULT_NAME, DOMAIN -SUPPORT_BRAVIA = ( +SUPPORT_BRAVIA: Final = ( SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | SUPPORT_VOLUME_MUTE @@ -33,12 +42,17 @@ SUPPORT_BRAVIA = ( ) -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: """Set up Bravia TV Media Player from a config_entry.""" coordinator = hass.data[DOMAIN][config_entry.entry_id] unique_id = config_entry.unique_id - device_info = { + assert unique_id is not None + device_info: DeviceInfo = { "identifiers": {(DOMAIN, unique_id)}, "name": DEFAULT_NAME, "manufacturer": ATTR_MANUFACTURER, @@ -53,10 +67,17 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class BraviaTVMediaPlayer(CoordinatorEntity, MediaPlayerEntity): """Representation of a Bravia TV Media Player.""" + coordinator: BraviaTVCoordinator _attr_device_class = DEVICE_CLASS_TV _attr_supported_features = SUPPORT_BRAVIA - def __init__(self, coordinator, name, unique_id, device_info): + def __init__( + self, + coordinator: BraviaTVCoordinator, + name: str, + unique_id: str, + device_info: DeviceInfo, + ) -> None: """Initialize the entity.""" self._attr_device_info = device_info @@ -66,91 +87,91 @@ class BraviaTVMediaPlayer(CoordinatorEntity, MediaPlayerEntity): super().__init__(coordinator) @property - def state(self): + def state(self) -> str | None: """Return the state of the device.""" if self.coordinator.is_on: return STATE_PLAYING if self.coordinator.playing else STATE_PAUSED return STATE_OFF @property - def source(self): + def source(self) -> str | None: """Return the current input source.""" return self.coordinator.source @property - def source_list(self): + def source_list(self) -> list[str]: """List of available input sources.""" return self.coordinator.source_list @property - def volume_level(self): + def volume_level(self) -> float | None: """Volume level of the media player (0..1).""" return self.coordinator.volume_level @property - def is_volume_muted(self): + def is_volume_muted(self) -> bool: """Boolean if volume is currently muted.""" return self.coordinator.muted @property - def media_title(self): + def media_title(self) -> str | None: """Title of current playing media.""" return self.coordinator.media_title @property - def media_content_id(self): + def media_content_id(self) -> str | None: """Content ID of current playing media.""" return self.coordinator.channel_name @property - def media_duration(self): + def media_duration(self) -> int | None: """Duration of current playing media in seconds.""" return self.coordinator.duration - async def async_turn_on(self): + async def async_turn_on(self) -> None: """Turn the device on.""" await self.coordinator.async_turn_on() - async def async_turn_off(self): + async def async_turn_off(self) -> None: """Turn the device off.""" await self.coordinator.async_turn_off() - async def async_set_volume_level(self, volume): + async def async_set_volume_level(self, volume: float) -> None: """Set volume level, range 0..1.""" await self.coordinator.async_set_volume_level(volume) - async def async_volume_up(self): + async def async_volume_up(self) -> None: """Send volume up command.""" await self.coordinator.async_volume_up() - async def async_volume_down(self): + async def async_volume_down(self) -> None: """Send volume down command.""" await self.coordinator.async_volume_down() - async def async_mute_volume(self, mute): + async def async_mute_volume(self, mute: bool) -> None: """Send mute command.""" await self.coordinator.async_volume_mute(mute) - async def async_select_source(self, source): + async def async_select_source(self, source: str) -> None: """Set the input source.""" await self.coordinator.async_select_source(source) - async def async_media_play(self): + async def async_media_play(self) -> None: """Send play command.""" await self.coordinator.async_media_play() - async def async_media_pause(self): + async def async_media_pause(self) -> None: """Send pause command.""" await self.coordinator.async_media_pause() - async def async_media_stop(self): + async def async_media_stop(self) -> None: """Send media stop command to media player.""" await self.coordinator.async_media_stop() - async def async_media_next_track(self): + async def async_media_next_track(self) -> None: """Send next track command.""" await self.coordinator.async_media_next_track() - async def async_media_previous_track(self): + async def async_media_previous_track(self) -> None: """Send previous track command.""" await self.coordinator.async_media_previous_track() diff --git a/homeassistant/components/braviatv/remote.py b/homeassistant/components/braviatv/remote.py index 613d67f0187..81761240320 100644 --- a/homeassistant/components/braviatv/remote.py +++ b/homeassistant/components/braviatv/remote.py @@ -1,17 +1,31 @@ """Remote control support for Bravia TV.""" +from __future__ import annotations + +from collections.abc import Iterable +from typing import Any from homeassistant.components.remote import ATTR_NUM_REPEATS, RemoteEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity +from . import BraviaTVCoordinator from .const import ATTR_MANUFACTURER, DEFAULT_NAME, DOMAIN -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: """Set up Bravia TV Remote from a config entry.""" coordinator = hass.data[DOMAIN][config_entry.entry_id] unique_id = config_entry.unique_id - device_info = { + assert unique_id is not None + device_info: DeviceInfo = { "identifiers": {(DOMAIN, unique_id)}, "name": DEFAULT_NAME, "manufacturer": ATTR_MANUFACTURER, @@ -26,7 +40,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class BraviaTVRemote(CoordinatorEntity, RemoteEntity): """Representation of a Bravia TV Remote.""" - def __init__(self, coordinator, name, unique_id, device_info): + coordinator: BraviaTVCoordinator + + def __init__( + self, + coordinator: BraviaTVCoordinator, + name: str, + unique_id: str, + device_info: DeviceInfo, + ) -> None: """Initialize the entity.""" self._attr_device_info = device_info @@ -36,19 +58,19 @@ class BraviaTVRemote(CoordinatorEntity, RemoteEntity): super().__init__(coordinator) @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" return self.coordinator.is_on - async def async_turn_on(self, **kwargs): + async def async_turn_on(self, **kwargs: Any) -> None: """Turn the device on.""" await self.coordinator.async_turn_on() - async def async_turn_off(self, **kwargs): + async def async_turn_off(self, **kwargs: Any) -> None: """Turn the device off.""" await self.coordinator.async_turn_off() - async def async_send_command(self, command, **kwargs): + async def async_send_command(self, command: Iterable[str], **kwargs: Any) -> None: """Send a command to device.""" repeats = kwargs[ATTR_NUM_REPEATS] await self.coordinator.async_send_command(command, repeats) diff --git a/mypy.ini b/mypy.ini index 09869a5b5fe..4e27da2fcb5 100644 --- a/mypy.ini +++ b/mypy.ini @@ -209,6 +209,17 @@ no_implicit_optional = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.braviatv.*] +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.brother.*] check_untyped_defs = true disallow_incomplete_defs = true