Remove freebox from mypy ignore list (#65126)

* Add type hints to freebox

* Remove freebox from mypy ignore list

* Adjust type hints

* Refactor FreeboxRouter setup/close

* Remove unnecessary assert

* Remove unused constant

* Rework unload routine

* Bring back close method

* Suppress NotOpenError

* Use async_on_unload on signal_device_new

Co-authored-by: epenet <epenet@users.noreply.github.com>
This commit is contained in:
epenet 2022-02-03 10:01:41 +01:00 committed by GitHub
parent c8504bd21d
commit 9fde84ab41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 55 additions and 70 deletions

View File

@ -1,18 +1,19 @@
"""Support for Freebox devices (Freebox v6 and Freebox mini 4K)."""
import logging
from datetime import timedelta
from freebox_api.exceptions import HttpRequestError
import voluptuous as vol
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.core import Event, HomeAssistant, ServiceCall
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN, PLATFORMS, SERVICE_REBOOT
from .router import FreeboxRouter
_LOGGER = logging.getLogger(__name__)
from .router import FreeboxRouter, get_api
FREEBOX_SCHEMA = vol.Schema(
{vol.Required(CONF_HOST): cv.string, vol.Required(CONF_PORT): cv.port}
@ -26,6 +27,8 @@ CONFIG_SCHEMA = vol.Schema(
extra=vol.ALLOW_EXTRA,
)
SCAN_INTERVAL = timedelta(seconds=30)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Freebox integration."""
@ -42,8 +45,19 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Freebox entry."""
router = FreeboxRouter(hass, entry)
await router.setup()
api = await get_api(hass, entry.data[CONF_HOST])
try:
await api.open(entry.data[CONF_HOST], entry.data[CONF_PORT])
except HttpRequestError as err:
raise ConfigEntryNotReady from err
freebox_config = await api.system.get_config()
router = FreeboxRouter(hass, entry, api, freebox_config)
await router.update_all()
entry.async_on_unload(
async_track_time_interval(hass, router.update_all, SCAN_INTERVAL)
)
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.unique_id] = router
@ -57,7 +71,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.services.async_register(DOMAIN, SERVICE_REBOOT, async_reboot)
async def async_close_connection(event):
async def async_close_connection(event: Event) -> None:
"""Close Freebox connection on HA Stop."""
await router.close()
@ -72,7 +86,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
router = hass.data[DOMAIN].pop(entry.unique_id)
router: FreeboxRouter = hass.data[DOMAIN].pop(entry.unique_id)
await router.close()
hass.services.async_remove(DOMAIN, SERVICE_REBOOT)

View File

@ -19,15 +19,15 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up device tracker for Freebox component."""
router = hass.data[DOMAIN][entry.unique_id]
tracked = set()
router: FreeboxRouter = hass.data[DOMAIN][entry.unique_id]
tracked: set[str] = set()
@callback
def update_router():
def update_router() -> None:
"""Update the values of the router."""
add_entities(router, async_add_entities, tracked)
router.listeners.append(
entry.async_on_unload(
async_dispatcher_connect(hass, router.signal_device_new, update_router)
)
@ -35,7 +35,9 @@ async def async_setup_entry(
@callback
def add_entities(router, async_add_entities, tracked):
def add_entities(
router: FreeboxRouter, async_add_entities: AddEntitiesCallback, tracked: set[str]
) -> None:
"""Add new tracker entities from the router."""
new_tracked = []
@ -61,7 +63,7 @@ class FreeboxDevice(ScannerEntity):
self._manufacturer = device["vendor_name"]
self._icon = icon_for_freebox_device(device)
self._active = False
self._attrs = {}
self._attrs: dict[str, Any] = {}
@callback
def async_update_state(self) -> None:

View File

@ -1,24 +1,23 @@
"""Represent the Freebox router and its devices and sensors."""
from __future__ import annotations
from datetime import datetime, timedelta
import logging
from collections.abc import Mapping
from contextlib import suppress
from datetime import datetime
import os
from pathlib import Path
from typing import Any
from freebox_api import Freepybox
from freebox_api.api.wifi import Wifi
from freebox_api.exceptions import HttpRequestError
from freebox_api.exceptions import NotOpenError
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.util import slugify
from .const import (
@ -30,10 +29,6 @@ from .const import (
STORAGE_VERSION,
)
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=30)
async def get_api(hass: HomeAssistant, host: str) -> Freepybox:
"""Get the Freebox API."""
@ -50,18 +45,23 @@ async def get_api(hass: HomeAssistant, host: str) -> Freepybox:
class FreeboxRouter:
"""Representation of a Freebox router."""
def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
def __init__(
self,
hass: HomeAssistant,
entry: ConfigEntry,
api: Freepybox,
freebox_config: Mapping[str, Any],
) -> None:
"""Initialize a Freebox router."""
self.hass = hass
self._entry = entry
self._host = entry.data[CONF_HOST]
self._port = entry.data[CONF_PORT]
self._api: Freepybox = None
self.name = None
self.mac = None
self._sw_v = None
self._attrs = {}
self._api: Freepybox = api
self.name: str = freebox_config["model_info"]["pretty_name"]
self.mac: str = freebox_config["mac"]
self._sw_v: str = freebox_config["firmware_version"]
self._attrs: dict[str, Any] = {}
self.devices: dict[str, dict[str, Any]] = {}
self.disks: dict[int, dict[str, Any]] = {}
@ -69,31 +69,6 @@ class FreeboxRouter:
self.sensors_connection: dict[str, float] = {}
self.call_list: list[dict[str, Any]] = []
self._unsub_dispatcher = None
self.listeners = []
async def setup(self) -> None:
"""Set up a Freebox router."""
self._api = await get_api(self.hass, self._host)
try:
await self._api.open(self._host, self._port)
except HttpRequestError:
_LOGGER.exception("Failed to connect to Freebox")
return ConfigEntryNotReady
# System
fbx_config = await self._api.system.get_config()
self.mac = fbx_config["mac"]
self.name = fbx_config["model_info"]["pretty_name"]
self._sw_v = fbx_config["firmware_version"]
# Devices & sensors
await self.update_all()
self._unsub_dispatcher = async_track_time_interval(
self.hass, self.update_all, SCAN_INTERVAL
)
async def update_all(self, now: datetime | None = None) -> None:
"""Update all Freebox platforms."""
await self.update_device_trackers()
@ -102,7 +77,7 @@ class FreeboxRouter:
async def update_device_trackers(self) -> None:
"""Update Freebox devices."""
new_device = False
fbx_devices: [dict[str, Any]] = await self._api.lan.get_hosts_list()
fbx_devices: list[dict[str, Any]] = await self._api.lan.get_hosts_list()
# Adds the Freebox itself
fbx_devices.append(
@ -164,7 +139,7 @@ class FreeboxRouter:
async def _update_disks_sensors(self) -> None:
"""Update Freebox disks."""
# None at first request
fbx_disks: [dict[str, Any]] = await self._api.storage.get_disks() or []
fbx_disks: list[dict[str, Any]] = await self._api.storage.get_disks() or []
for fbx_disk in fbx_disks:
self.disks[fbx_disk["id"]] = fbx_disk
@ -175,10 +150,8 @@ class FreeboxRouter:
async def close(self) -> None:
"""Close the connection."""
if self._api is not None:
with suppress(NotOpenError):
await self._api.close()
self._unsub_dispatcher()
self._api = None
@property
def device_info(self) -> DeviceInfo:

View File

@ -27,7 +27,7 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the sensors."""
router = hass.data[DOMAIN][entry.unique_id]
router: FreeboxRouter = hass.data[DOMAIN][entry.unique_id]
entities = []
_LOGGER.debug(
@ -120,7 +120,7 @@ class FreeboxCallSensor(FreeboxSensor):
) -> None:
"""Initialize a Freebox call sensor."""
super().__init__(router, description)
self._call_list_for_type = []
self._call_list_for_type: list[dict[str, Any]] = []
@callback
def async_update_state(self) -> None:

View File

@ -21,7 +21,7 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the switch."""
router = hass.data[DOMAIN][entry.unique_id]
router: FreeboxRouter = hass.data[DOMAIN][entry.unique_id]
async_add_entities([FreeboxWifiSwitch(router)], True)
@ -31,7 +31,7 @@ class FreeboxWifiSwitch(SwitchEntity):
def __init__(self, router: FreeboxRouter) -> None:
"""Initialize the Wifi switch."""
self._name = "Freebox WiFi"
self._state = None
self._state: bool | None = None
self._router = router
self._unique_id = f"{self._router.mac} {self._name}"
@ -46,7 +46,7 @@ class FreeboxWifiSwitch(SwitchEntity):
return self._name
@property
def is_on(self) -> bool:
def is_on(self) -> bool | None:
"""Return true if device is on."""
return self._state

View File

@ -2050,9 +2050,6 @@ ignore_errors = true
[mypy-homeassistant.components.firmata.*]
ignore_errors = true
[mypy-homeassistant.components.freebox.*]
ignore_errors = true
[mypy-homeassistant.components.geniushub.*]
ignore_errors = true

View File

@ -26,7 +26,6 @@ IGNORED_MODULES: Final[list[str]] = [
"homeassistant.components.evohome.*",
"homeassistant.components.fireservicerota.*",
"homeassistant.components.firmata.*",
"homeassistant.components.freebox.*",
"homeassistant.components.geniushub.*",
"homeassistant.components.google_assistant.*",
"homeassistant.components.gree.*",