Remove unifi from mypy ignore list (#74456)

* Remove unifi diagnostics from mypy ignore list

* Remove unifi init from mypy ignore list

* Remove unifi device tracker from mypy ignore list

* Adjust doc string

* Adjust doc string

* Remove unifi entity base from mypy ignore list

* Keep comprehension

* Remove unifi config flow from mypy ignore list

* Fix circular import
This commit is contained in:
epenet 2022-07-06 10:25:53 +02:00 committed by GitHub
parent ef6fd78ede
commit a27d483009
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 43 additions and 53 deletions

View file

@ -1,4 +1,7 @@
"""Integration to UniFi Network and its various features.""" """Integration to UniFi Network and its various features."""
from collections.abc import Mapping
from typing import Any
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
@ -92,7 +95,10 @@ async def async_flatten_entry_data(
Keep controller key layer in case user rollbacks. Keep controller key layer in case user rollbacks.
""" """
data: dict = {**config_entry.data, **config_entry.data[CONF_CONTROLLER]} data: Mapping[str, Any] = {
**config_entry.data,
**config_entry.data[CONF_CONTROLLER],
}
if config_entry.data != data: if config_entry.data != data:
hass.config_entries.async_update_entry(config_entry, data=data) hass.config_entries.async_update_entry(config_entry, data=data)

View file

@ -46,7 +46,7 @@ from .const import (
DEFAULT_POE_CLIENTS, DEFAULT_POE_CLIENTS,
DOMAIN as UNIFI_DOMAIN, DOMAIN as UNIFI_DOMAIN,
) )
from .controller import get_controller from .controller import UniFiController, get_controller
from .errors import AuthenticationRequired, CannotConnect from .errors import AuthenticationRequired, CannotConnect
DEFAULT_PORT = 443 DEFAULT_PORT = 443
@ -75,11 +75,11 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=UNIFI_DOMAIN):
def __init__(self) -> None: def __init__(self) -> None:
"""Initialize the UniFi Network flow.""" """Initialize the UniFi Network flow."""
self.config = {} self.config: dict[str, Any] = {}
self.site_ids = {} self.site_ids: dict[str, str] = {}
self.site_names = {} self.site_names: dict[str, str] = {}
self.reauth_config_entry = None self.reauth_config_entry: config_entries.ConfigEntry | None = None
self.reauth_schema = {} self.reauth_schema: dict[vol.Marker, Any] = {}
async def async_step_user( async def async_step_user(
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
@ -156,8 +156,6 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=UNIFI_DOMAIN):
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
) -> FlowResult: ) -> FlowResult:
"""Select site to control.""" """Select site to control."""
errors = {}
if user_input is not None: if user_input is not None:
unique_id = user_input[CONF_SITE_ID] unique_id = user_input[CONF_SITE_ID]
@ -173,9 +171,9 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=UNIFI_DOMAIN):
abort_reason = "reauth_successful" abort_reason = "reauth_successful"
if config_entry: if config_entry:
controller = self.hass.data.get(UNIFI_DOMAIN, {}).get( controller: UniFiController | None = self.hass.data.get(
config_entry.entry_id UNIFI_DOMAIN, {}
) ).get(config_entry.entry_id)
if controller and controller.available: if controller and controller.available:
return self.async_abort(reason="already_configured") return self.async_abort(reason="already_configured")
@ -199,7 +197,6 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=UNIFI_DOMAIN):
data_schema=vol.Schema( data_schema=vol.Schema(
{vol.Required(CONF_SITE_ID): vol.In(self.site_names)} {vol.Required(CONF_SITE_ID): vol.In(self.site_names)}
), ),
errors=errors,
) )
async def async_step_reauth(self, entry_data: Mapping[str, Any]) -> FlowResult: async def async_step_reauth(self, entry_data: Mapping[str, Any]) -> FlowResult:
@ -207,6 +204,7 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=UNIFI_DOMAIN):
config_entry = self.hass.config_entries.async_get_entry( config_entry = self.hass.config_entries.async_get_entry(
self.context["entry_id"] self.context["entry_id"]
) )
assert config_entry
self.reauth_config_entry = config_entry self.reauth_config_entry = config_entry
self.context["title_placeholders"] = { self.context["title_placeholders"] = {
@ -258,11 +256,12 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=UNIFI_DOMAIN):
class UnifiOptionsFlowHandler(config_entries.OptionsFlow): class UnifiOptionsFlowHandler(config_entries.OptionsFlow):
"""Handle Unifi Network options.""" """Handle Unifi Network options."""
controller: UniFiController
def __init__(self, config_entry: config_entries.ConfigEntry) -> None: def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
"""Initialize UniFi Network options flow.""" """Initialize UniFi Network options flow."""
self.config_entry = config_entry self.config_entry = config_entry
self.options = dict(config_entry.options) self.options = dict(config_entry.options)
self.controller = None
async def async_step_init( async def async_step_init(
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
@ -379,8 +378,6 @@ class UnifiOptionsFlowHandler(config_entries.OptionsFlow):
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
) -> FlowResult: ) -> FlowResult:
"""Manage configuration of network access controlled clients.""" """Manage configuration of network access controlled clients."""
errors = {}
if user_input is not None: if user_input is not None:
self.options.update(user_input) self.options.update(user_input)
return await self.async_step_statistics_sensors() return await self.async_step_statistics_sensors()
@ -417,7 +414,6 @@ class UnifiOptionsFlowHandler(config_entries.OptionsFlow):
): bool, ): bool,
} }
), ),
errors=errors,
last_step=False, last_step=False,
) )

View file

@ -27,7 +27,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .const import DOMAIN as UNIFI_DOMAIN from .const import DOMAIN as UNIFI_DOMAIN
from .unifi_client import UniFiClient from .controller import UniFiController
from .unifi_client import UniFiClientBase
from .unifi_entity_base import UniFiBase from .unifi_entity_base import UniFiBase
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
@ -79,7 +80,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up device tracker for UniFi Network integration.""" """Set up device tracker for UniFi Network integration."""
controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id] controller: UniFiController = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
controller.entities[DOMAIN] = {CLIENT_TRACKER: set(), DEVICE_TRACKER: set()} controller.entities[DOMAIN] = {CLIENT_TRACKER: set(), DEVICE_TRACKER: set()}
@callback @callback
@ -144,7 +145,7 @@ def add_device_entities(controller, async_add_entities, devices):
async_add_entities(trackers) async_add_entities(trackers)
class UniFiClientTracker(UniFiClient, ScannerEntity): class UniFiClientTracker(UniFiClientBase, ScannerEntity):
"""Representation of a network client.""" """Representation of a network client."""
DOMAIN = DOMAIN DOMAIN = DOMAIN
@ -261,11 +262,6 @@ class UniFiClientTracker(UniFiClient, ScannerEntity):
self.async_write_ha_state() self.async_write_ha_state()
self._async_log_debug_data("make_disconnected") self._async_log_debug_data("make_disconnected")
@property
def device_info(self) -> None:
"""Return no device info."""
return None
@property @property
def is_connected(self): def is_connected(self):
"""Return true if the client is connected to the network.""" """Return true if the client is connected to the network."""

View file

@ -12,6 +12,7 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import format_mac from homeassistant.helpers.device_registry import format_mac
from .const import CONF_CONTROLLER, DOMAIN as UNIFI_DOMAIN from .const import CONF_CONTROLLER, DOMAIN as UNIFI_DOMAIN
from .controller import UniFiController
TO_REDACT = {CONF_CONTROLLER, CONF_PASSWORD} TO_REDACT = {CONF_CONTROLLER, CONF_PASSWORD}
REDACT_CONFIG = {CONF_CONTROLLER, CONF_HOST, CONF_PASSWORD, CONF_USERNAME} REDACT_CONFIG = {CONF_CONTROLLER, CONF_HOST, CONF_PASSWORD, CONF_USERNAME}
@ -56,7 +57,7 @@ def async_replace_list_data(
"""Redact sensitive data in a list.""" """Redact sensitive data in a list."""
redacted = [] redacted = []
for item in data: for item in data:
new_value = None new_value: Any | None = None
if isinstance(item, (list, set, tuple)): if isinstance(item, (list, set, tuple)):
new_value = async_replace_list_data(item, to_replace) new_value = async_replace_list_data(item, to_replace)
elif isinstance(item, Mapping): elif isinstance(item, Mapping):
@ -74,7 +75,7 @@ async def async_get_config_entry_diagnostics(
hass: HomeAssistant, config_entry: ConfigEntry hass: HomeAssistant, config_entry: ConfigEntry
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Return diagnostics for a config entry.""" """Return diagnostics for a config entry."""
controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id] controller: UniFiController = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
diag: dict[str, Any] = {} diag: dict[str, Any] = {}
macs_to_redact: dict[str, str] = {} macs_to_redact: dict[str, str] = {}

View file

@ -5,8 +5,8 @@ from homeassistant.helpers.entity import DeviceInfo
from .unifi_entity_base import UniFiBase from .unifi_entity_base import UniFiBase
class UniFiClient(UniFiBase): class UniFiClientBase(UniFiBase):
"""Base class for UniFi clients.""" """Base class for UniFi clients (without device info)."""
def __init__(self, client, controller) -> None: def __init__(self, client, controller) -> None:
"""Set up client.""" """Set up client."""
@ -44,6 +44,10 @@ class UniFiClient(UniFiBase):
"""Return if controller is available.""" """Return if controller is available."""
return self.controller.available return self.controller.available
class UniFiClient(UniFiClientBase):
"""Base class for UniFi clients (with device info)."""
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
"""Return a client description for device registry.""" """Return a client description for device registry."""

View file

@ -1,12 +1,18 @@
"""Base class for UniFi Network entities.""" """Base class for UniFi Network entities."""
from __future__ import annotations
from collections.abc import Callable
import logging import logging
from typing import Any from typing import TYPE_CHECKING, Any
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
if TYPE_CHECKING:
from .controller import UniFiController
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -16,7 +22,7 @@ class UniFiBase(Entity):
DOMAIN = "" DOMAIN = ""
TYPE = "" TYPE = ""
def __init__(self, item, controller) -> None: def __init__(self, item, controller: UniFiController) -> None:
"""Set up UniFi Network entity base. """Set up UniFi Network entity base.
Register mac to controller entities to cover disabled entities. Register mac to controller entities to cover disabled entities.
@ -38,11 +44,12 @@ class UniFiBase(Entity):
self.entity_id, self.entity_id,
self.key, self.key,
) )
for signal, method in ( signals: tuple[tuple[str, Callable[..., Any]], ...] = (
(self.controller.signal_reachable, self.async_signal_reachable_callback), (self.controller.signal_reachable, self.async_signal_reachable_callback),
(self.controller.signal_options_update, self.options_updated), (self.controller.signal_options_update, self.options_updated),
(self.controller.signal_remove, self.remove_item), (self.controller.signal_remove, self.remove_item),
): )
for signal, method in signals:
self.async_on_remove(async_dispatcher_connect(self.hass, signal, method)) self.async_on_remove(async_dispatcher_connect(self.hass, signal, method))
self._item.register_callback(self.async_update_callback) self._item.register_callback(self.async_update_callback)

View file

@ -2890,21 +2890,6 @@ ignore_errors = true
[mypy-homeassistant.components.toon.models] [mypy-homeassistant.components.toon.models]
ignore_errors = true ignore_errors = true
[mypy-homeassistant.components.unifi]
ignore_errors = true
[mypy-homeassistant.components.unifi.config_flow]
ignore_errors = true
[mypy-homeassistant.components.unifi.device_tracker]
ignore_errors = true
[mypy-homeassistant.components.unifi.diagnostics]
ignore_errors = true
[mypy-homeassistant.components.unifi.unifi_entity_base]
ignore_errors = true
[mypy-homeassistant.components.withings] [mypy-homeassistant.components.withings]
ignore_errors = true ignore_errors = true

View file

@ -105,11 +105,6 @@ IGNORED_MODULES: Final[list[str]] = [
"homeassistant.components.toon", "homeassistant.components.toon",
"homeassistant.components.toon.config_flow", "homeassistant.components.toon.config_flow",
"homeassistant.components.toon.models", "homeassistant.components.toon.models",
"homeassistant.components.unifi",
"homeassistant.components.unifi.config_flow",
"homeassistant.components.unifi.device_tracker",
"homeassistant.components.unifi.diagnostics",
"homeassistant.components.unifi.unifi_entity_base",
"homeassistant.components.withings", "homeassistant.components.withings",
"homeassistant.components.withings.binary_sensor", "homeassistant.components.withings.binary_sensor",
"homeassistant.components.withings.common", "homeassistant.components.withings.common",