Remove denonavr from mypy ignore list (#74580)
This commit is contained in:
parent
4604694255
commit
f19c542d6d
5 changed files with 94 additions and 92 deletions
|
@ -90,14 +90,14 @@ class DenonAvrFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
"""Initialize the Denon AVR flow."""
|
"""Initialize the Denon AVR flow."""
|
||||||
self.host = None
|
self.host: str | None = None
|
||||||
self.serial_number = None
|
self.serial_number: str | None = None
|
||||||
self.model_name = None
|
self.model_name: str | None = None
|
||||||
self.timeout = DEFAULT_TIMEOUT
|
self.timeout = DEFAULT_TIMEOUT
|
||||||
self.show_all_sources = DEFAULT_SHOW_SOURCES
|
self.show_all_sources = DEFAULT_SHOW_SOURCES
|
||||||
self.zone2 = DEFAULT_ZONE2
|
self.zone2 = DEFAULT_ZONE2
|
||||||
self.zone3 = DEFAULT_ZONE3
|
self.zone3 = DEFAULT_ZONE3
|
||||||
self.d_receivers = []
|
self.d_receivers: list[dict[str, Any]] = []
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@callback
|
@callback
|
||||||
|
@ -138,7 +138,7 @@ class DenonAvrFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> FlowResult:
|
) -> FlowResult:
|
||||||
"""Handle multiple receivers found."""
|
"""Handle multiple receivers found."""
|
||||||
errors = {}
|
errors: dict[str, str] = {}
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
self.host = user_input["select_host"]
|
self.host = user_input["select_host"]
|
||||||
return await self.async_step_connect()
|
return await self.async_step_connect()
|
||||||
|
@ -169,6 +169,7 @@ class DenonAvrFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> FlowResult:
|
) -> FlowResult:
|
||||||
"""Connect to the receiver."""
|
"""Connect to the receiver."""
|
||||||
|
assert self.host
|
||||||
connect_denonavr = ConnectDenonAVR(
|
connect_denonavr = ConnectDenonAVR(
|
||||||
self.host,
|
self.host,
|
||||||
self.timeout,
|
self.timeout,
|
||||||
|
@ -185,6 +186,7 @@ class DenonAvrFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
if not success:
|
if not success:
|
||||||
return self.async_abort(reason="cannot_connect")
|
return self.async_abort(reason="cannot_connect")
|
||||||
receiver = connect_denonavr.receiver
|
receiver = connect_denonavr.receiver
|
||||||
|
assert receiver
|
||||||
|
|
||||||
if not self.serial_number:
|
if not self.serial_number:
|
||||||
self.serial_number = receiver.serial_number
|
self.serial_number = receiver.serial_number
|
||||||
|
@ -238,6 +240,7 @@ class DenonAvrFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
"*", ""
|
"*", ""
|
||||||
)
|
)
|
||||||
self.serial_number = discovery_info.upnp[ssdp.ATTR_UPNP_SERIAL]
|
self.serial_number = discovery_info.upnp[ssdp.ATTR_UPNP_SERIAL]
|
||||||
|
assert discovery_info.ssdp_location is not None
|
||||||
self.host = urlparse(discovery_info.ssdp_location).hostname
|
self.host = urlparse(discovery_info.ssdp_location).hostname
|
||||||
|
|
||||||
if self.model_name in IGNORED_MODELS:
|
if self.model_name in IGNORED_MODELS:
|
||||||
|
@ -260,6 +263,6 @@ class DenonAvrFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
return await self.async_step_confirm()
|
return await self.async_step_confirm()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def construct_unique_id(model_name: str, serial_number: str) -> str:
|
def construct_unique_id(model_name: str | None, serial_number: str | None) -> str:
|
||||||
"""Construct the unique id from the ssdp discovery or user_step."""
|
"""Construct the unique id from the ssdp discovery or user_step."""
|
||||||
return f"{model_name}-{serial_number}"
|
return f"{model_name}-{serial_number}"
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
"""Support for Denon AVR receivers using their HTTP interface."""
|
"""Support for Denon AVR receivers using their HTTP interface."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Coroutine
|
from collections.abc import Awaitable, Callable, Coroutine
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Any, TypeVar
|
||||||
|
|
||||||
from denonavr import DenonAVR
|
from denonavr import DenonAVR
|
||||||
from denonavr.const import POWER_ON
|
from denonavr.const import POWER_ON
|
||||||
|
@ -15,6 +16,7 @@ from denonavr.exceptions import (
|
||||||
AvrTimoutError,
|
AvrTimoutError,
|
||||||
DenonAvrError,
|
DenonAvrError,
|
||||||
)
|
)
|
||||||
|
from typing_extensions import Concatenate, ParamSpec
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.media_player import (
|
from homeassistant.components.media_player import (
|
||||||
|
@ -79,6 +81,10 @@ SERVICE_GET_COMMAND = "get_command"
|
||||||
SERVICE_SET_DYNAMIC_EQ = "set_dynamic_eq"
|
SERVICE_SET_DYNAMIC_EQ = "set_dynamic_eq"
|
||||||
SERVICE_UPDATE_AUDYSSEY = "update_audyssey"
|
SERVICE_UPDATE_AUDYSSEY = "update_audyssey"
|
||||||
|
|
||||||
|
_DenonDeviceT = TypeVar("_DenonDeviceT", bound="DenonDevice")
|
||||||
|
_R = TypeVar("_R")
|
||||||
|
_P = ParamSpec("_P")
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
@ -131,6 +137,79 @@ async def async_setup_entry(
|
||||||
async_add_entities(entities, update_before_add=True)
|
async_add_entities(entities, update_before_add=True)
|
||||||
|
|
||||||
|
|
||||||
|
def async_log_errors(
|
||||||
|
func: Callable[Concatenate[_DenonDeviceT, _P], Awaitable[_R]],
|
||||||
|
) -> Callable[Concatenate[_DenonDeviceT, _P], Coroutine[Any, Any, _R | None]]:
|
||||||
|
"""
|
||||||
|
Log errors occurred when calling a Denon AVR receiver.
|
||||||
|
|
||||||
|
Decorates methods of DenonDevice class.
|
||||||
|
Declaration of staticmethod for this method is at the end of this class.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
async def wrapper(
|
||||||
|
self: _DenonDeviceT, *args: _P.args, **kwargs: _P.kwargs
|
||||||
|
) -> _R | None:
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
available = True
|
||||||
|
try:
|
||||||
|
return await func(self, *args, **kwargs)
|
||||||
|
except AvrTimoutError:
|
||||||
|
available = False
|
||||||
|
if self._available is True:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Timeout connecting to Denon AVR receiver at host %s. "
|
||||||
|
"Device is unavailable",
|
||||||
|
self._receiver.host,
|
||||||
|
)
|
||||||
|
self._available = False
|
||||||
|
except AvrNetworkError:
|
||||||
|
available = False
|
||||||
|
if self._available is True:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Network error connecting to Denon AVR receiver at host %s. "
|
||||||
|
"Device is unavailable",
|
||||||
|
self._receiver.host,
|
||||||
|
)
|
||||||
|
self._available = False
|
||||||
|
except AvrForbiddenError:
|
||||||
|
available = False
|
||||||
|
if self._available is True:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Denon AVR receiver at host %s responded with HTTP 403 error. "
|
||||||
|
"Device is unavailable. Please consider power cycling your "
|
||||||
|
"receiver",
|
||||||
|
self._receiver.host,
|
||||||
|
)
|
||||||
|
self._available = False
|
||||||
|
except AvrCommandError as err:
|
||||||
|
available = False
|
||||||
|
_LOGGER.error(
|
||||||
|
"Command %s failed with error: %s",
|
||||||
|
func.__name__,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
except DenonAvrError as err:
|
||||||
|
available = False
|
||||||
|
_LOGGER.error(
|
||||||
|
"Error %s occurred in method %s for Denon AVR receiver",
|
||||||
|
err,
|
||||||
|
func.__name__,
|
||||||
|
exc_info=True,
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
if available is True and self._available is False:
|
||||||
|
_LOGGER.info(
|
||||||
|
"Denon AVR receiver at host %s is available again",
|
||||||
|
self._receiver.host,
|
||||||
|
)
|
||||||
|
self._available = True
|
||||||
|
return None
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class DenonDevice(MediaPlayerEntity):
|
class DenonDevice(MediaPlayerEntity):
|
||||||
"""Representation of a Denon Media Player Device."""
|
"""Representation of a Denon Media Player Device."""
|
||||||
|
|
||||||
|
@ -144,6 +223,7 @@ class DenonDevice(MediaPlayerEntity):
|
||||||
"""Initialize the device."""
|
"""Initialize the device."""
|
||||||
self._attr_name = receiver.name
|
self._attr_name = receiver.name
|
||||||
self._attr_unique_id = unique_id
|
self._attr_unique_id = unique_id
|
||||||
|
assert config_entry.unique_id
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
configuration_url=f"http://{config_entry.data[CONF_HOST]}/",
|
configuration_url=f"http://{config_entry.data[CONF_HOST]}/",
|
||||||
identifiers={(DOMAIN, config_entry.unique_id)},
|
identifiers={(DOMAIN, config_entry.unique_id)},
|
||||||
|
@ -163,71 +243,6 @@ class DenonDevice(MediaPlayerEntity):
|
||||||
)
|
)
|
||||||
self._available = True
|
self._available = True
|
||||||
|
|
||||||
def async_log_errors(
|
|
||||||
func: Coroutine,
|
|
||||||
) -> Coroutine:
|
|
||||||
"""
|
|
||||||
Log errors occurred when calling a Denon AVR receiver.
|
|
||||||
|
|
||||||
Decorates methods of DenonDevice class.
|
|
||||||
Declaration of staticmethod for this method is at the end of this class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@wraps(func)
|
|
||||||
async def wrapper(self, *args, **kwargs):
|
|
||||||
# pylint: disable=protected-access
|
|
||||||
available = True
|
|
||||||
try:
|
|
||||||
return await func(self, *args, **kwargs)
|
|
||||||
except AvrTimoutError:
|
|
||||||
available = False
|
|
||||||
if self._available is True:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Timeout connecting to Denon AVR receiver at host %s. Device is unavailable",
|
|
||||||
self._receiver.host,
|
|
||||||
)
|
|
||||||
self._available = False
|
|
||||||
except AvrNetworkError:
|
|
||||||
available = False
|
|
||||||
if self._available is True:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Network error connecting to Denon AVR receiver at host %s. Device is unavailable",
|
|
||||||
self._receiver.host,
|
|
||||||
)
|
|
||||||
self._available = False
|
|
||||||
except AvrForbiddenError:
|
|
||||||
available = False
|
|
||||||
if self._available is True:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Denon AVR receiver at host %s responded with HTTP 403 error. Device is unavailable. Please consider power cycling your receiver",
|
|
||||||
self._receiver.host,
|
|
||||||
)
|
|
||||||
self._available = False
|
|
||||||
except AvrCommandError as err:
|
|
||||||
available = False
|
|
||||||
_LOGGER.error(
|
|
||||||
"Command %s failed with error: %s",
|
|
||||||
func.__name__,
|
|
||||||
err,
|
|
||||||
)
|
|
||||||
except DenonAvrError as err:
|
|
||||||
available = False
|
|
||||||
_LOGGER.error(
|
|
||||||
"Error %s occurred in method %s for Denon AVR receiver",
|
|
||||||
err,
|
|
||||||
func.__name__,
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
finally:
|
|
||||||
if available is True and self._available is False:
|
|
||||||
_LOGGER.info(
|
|
||||||
"Denon AVR receiver at host %s is available again",
|
|
||||||
self._receiver.host,
|
|
||||||
)
|
|
||||||
self._available = True
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
@async_log_errors
|
@async_log_errors
|
||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Get the latest status information from device."""
|
"""Get the latest status information from device."""
|
||||||
|
@ -466,8 +481,3 @@ class DenonDevice(MediaPlayerEntity):
|
||||||
|
|
||||||
if self._update_audyssey:
|
if self._update_audyssey:
|
||||||
await self._receiver.async_update_audyssey()
|
await self._receiver.async_update_audyssey()
|
||||||
|
|
||||||
# Decorator defined before is a staticmethod
|
|
||||||
async_log_errors = staticmethod( # pylint: disable=no-staticmethod-decorator
|
|
||||||
async_log_errors
|
|
||||||
)
|
|
||||||
|
|
|
@ -23,12 +23,12 @@ class ConnectDenonAVR:
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the class."""
|
"""Initialize the class."""
|
||||||
self._async_client_getter = async_client_getter
|
self._async_client_getter = async_client_getter
|
||||||
self._receiver = None
|
self._receiver: DenonAVR | None = None
|
||||||
self._host = host
|
self._host = host
|
||||||
self._show_all_inputs = show_all_inputs
|
self._show_all_inputs = show_all_inputs
|
||||||
self._timeout = timeout
|
self._timeout = timeout
|
||||||
|
|
||||||
self._zones = {}
|
self._zones: dict[str, str | None] = {}
|
||||||
if zone2:
|
if zone2:
|
||||||
self._zones["Zone2"] = None
|
self._zones["Zone2"] = None
|
||||||
if zone3:
|
if zone3:
|
||||||
|
@ -42,6 +42,7 @@ class ConnectDenonAVR:
|
||||||
async def async_connect_receiver(self) -> bool:
|
async def async_connect_receiver(self) -> bool:
|
||||||
"""Connect to the DenonAVR receiver."""
|
"""Connect to the DenonAVR receiver."""
|
||||||
await self.async_init_receiver_class()
|
await self.async_init_receiver_class()
|
||||||
|
assert self._receiver
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self._receiver.manufacturer is None
|
self._receiver.manufacturer is None
|
||||||
|
@ -70,7 +71,7 @@ class ConnectDenonAVR:
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def async_init_receiver_class(self) -> bool:
|
async def async_init_receiver_class(self) -> None:
|
||||||
"""Initialize the DenonAVR class asynchronously."""
|
"""Initialize the DenonAVR class asynchronously."""
|
||||||
receiver = DenonAVR(
|
receiver = DenonAVR(
|
||||||
host=self._host,
|
host=self._host,
|
||||||
|
|
9
mypy.ini
9
mypy.ini
|
@ -2644,15 +2644,6 @@ ignore_errors = true
|
||||||
[mypy-homeassistant.components.conversation.default_agent]
|
[mypy-homeassistant.components.conversation.default_agent]
|
||||||
ignore_errors = true
|
ignore_errors = true
|
||||||
|
|
||||||
[mypy-homeassistant.components.denonavr.config_flow]
|
|
||||||
ignore_errors = true
|
|
||||||
|
|
||||||
[mypy-homeassistant.components.denonavr.media_player]
|
|
||||||
ignore_errors = true
|
|
||||||
|
|
||||||
[mypy-homeassistant.components.denonavr.receiver]
|
|
||||||
ignore_errors = true
|
|
||||||
|
|
||||||
[mypy-homeassistant.components.evohome]
|
[mypy-homeassistant.components.evohome]
|
||||||
ignore_errors = true
|
ignore_errors = true
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,6 @@ IGNORED_MODULES: Final[list[str]] = [
|
||||||
"homeassistant.components.cloud.http_api",
|
"homeassistant.components.cloud.http_api",
|
||||||
"homeassistant.components.conversation",
|
"homeassistant.components.conversation",
|
||||||
"homeassistant.components.conversation.default_agent",
|
"homeassistant.components.conversation.default_agent",
|
||||||
"homeassistant.components.denonavr.config_flow",
|
|
||||||
"homeassistant.components.denonavr.media_player",
|
|
||||||
"homeassistant.components.denonavr.receiver",
|
|
||||||
"homeassistant.components.evohome",
|
"homeassistant.components.evohome",
|
||||||
"homeassistant.components.evohome.climate",
|
"homeassistant.components.evohome.climate",
|
||||||
"homeassistant.components.evohome.water_heater",
|
"homeassistant.components.evohome.water_heater",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue