Improve debouncer typing (#75436)

This commit is contained in:
Marc Mueller 2022-07-19 18:35:04 +02:00 committed by GitHub
parent 4b036cbad9
commit 5ae5ae5392
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 33 additions and 20 deletions

View File

@ -15,6 +15,7 @@ homeassistant.auth.auth_store
homeassistant.auth.providers.* homeassistant.auth.providers.*
homeassistant.helpers.area_registry homeassistant.helpers.area_registry
homeassistant.helpers.condition homeassistant.helpers.condition
homeassistant.helpers.debounce
homeassistant.helpers.discovery homeassistant.helpers.discovery
homeassistant.helpers.entity homeassistant.helpers.entity
homeassistant.helpers.entity_values homeassistant.helpers.entity_values

View File

@ -2,8 +2,9 @@
from __future__ import annotations from __future__ import annotations
from abc import abstractmethod from abc import abstractmethod
from collections.abc import Coroutine
import logging import logging
from typing import cast from typing import Any, cast
from flux_led.protocol import ( from flux_led.protocol import (
MUSIC_PIXELS_MAX, MUSIC_PIXELS_MAX,
@ -143,7 +144,7 @@ class FluxConfigNumber(
) -> None: ) -> None:
"""Initialize the flux number.""" """Initialize the flux number."""
super().__init__(coordinator, base_unique_id, name, key) super().__init__(coordinator, base_unique_id, name, key)
self._debouncer: Debouncer | None = None self._debouncer: Debouncer[Coroutine[Any, Any, None]] | None = None
self._pending_value: int | None = None self._pending_value: int | None = None
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None:

View File

@ -95,7 +95,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
_LOGGER.debug("Scanning for GDM clients") _LOGGER.debug("Scanning for GDM clients")
gdm.scan(scan_for_clients=True) gdm.scan(scan_for_clients=True)
hass.data[PLEX_DOMAIN][GDM_DEBOUNCER] = Debouncer( hass.data[PLEX_DOMAIN][GDM_DEBOUNCER] = Debouncer[None](
hass, hass,
_LOGGER, _LOGGER,
cooldown=10, cooldown=10,

View File

@ -1,7 +1,7 @@
"""The Samsung TV integration.""" """The Samsung TV integration."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Mapping from collections.abc import Coroutine, Mapping
from functools import partial from functools import partial
import socket import socket
from typing import Any from typing import Any
@ -131,7 +131,7 @@ class DebouncedEntryReloader:
self.hass = hass self.hass = hass
self.entry = entry self.entry = entry
self.token = self.entry.data.get(CONF_TOKEN) self.token = self.entry.data.get(CONF_TOKEN)
self._debounced_reload = Debouncer( self._debounced_reload: Debouncer[Coroutine[Any, Any, None]] = Debouncer(
hass, hass,
LOGGER, LOGGER,
cooldown=ENTRY_RELOAD_COOLDOWN, cooldown=ENTRY_RELOAD_COOLDOWN,

View File

@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from collections.abc import Coroutine
from datetime import timedelta from datetime import timedelta
from typing import Any, Final, cast from typing import Any, Final, cast
@ -296,7 +297,7 @@ class BlockDeviceWrapper(update_coordinator.DataUpdateCoordinator):
self.entry = entry self.entry = entry
self.device = device self.device = device
self._debounced_reload = Debouncer( self._debounced_reload: Debouncer[Coroutine[Any, Any, None]] = Debouncer(
hass, hass,
LOGGER, LOGGER,
cooldown=ENTRY_RELOAD_COOLDOWN, cooldown=ENTRY_RELOAD_COOLDOWN,
@ -636,7 +637,7 @@ class RpcDeviceWrapper(update_coordinator.DataUpdateCoordinator):
self.entry = entry self.entry = entry
self.device = device self.device = device
self._debounced_reload = Debouncer( self._debounced_reload: Debouncer[Coroutine[Any, Any, None]] = Debouncer(
hass, hass,
LOGGER, LOGGER,
cooldown=ENTRY_RELOAD_COOLDOWN, cooldown=ENTRY_RELOAD_COOLDOWN,

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import asyncio import asyncio
from collections.abc import Callable, Coroutine from collections.abc import Callable, Coroutine
import logging import logging
from typing import Any
from soco import SoCo from soco import SoCo
@ -35,7 +36,7 @@ class SonosHouseholdCoordinator:
async def _async_setup(self) -> None: async def _async_setup(self) -> None:
"""Finish setup in async context.""" """Finish setup in async context."""
self.cache_update_lock = asyncio.Lock() self.cache_update_lock = asyncio.Lock()
self.async_poll = Debouncer( self.async_poll = Debouncer[Coroutine[Any, Any, None]](
self.hass, self.hass,
_LOGGER, _LOGGER,
cooldown=3, cooldown=3,

View File

@ -1,12 +1,13 @@
"""The USB Discovery integration.""" """The USB Discovery integration."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Coroutine
import dataclasses import dataclasses
import fnmatch import fnmatch
import logging import logging
import os import os
import sys import sys
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Any
from serial.tools.list_ports import comports from serial.tools.list_ports import comports
from serial.tools.list_ports_common import ListPortInfo from serial.tools.list_ports_common import ListPortInfo
@ -109,7 +110,7 @@ class USBDiscovery:
self.usb = usb self.usb = usb
self.seen: set[tuple[str, ...]] = set() self.seen: set[tuple[str, ...]] = set()
self.observer_active = False self.observer_active = False
self._request_debouncer: Debouncer | None = None self._request_debouncer: Debouncer[Coroutine[Any, Any, None]] | None = None
async def async_setup(self) -> None: async def async_setup(self) -> None:
"""Set up USB Discovery.""" """Set up USB Discovery."""

View File

@ -2,14 +2,16 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from collections.abc import Awaitable, Callable from collections.abc import Callable
from logging import Logger from logging import Logger
from typing import Any from typing import Generic, TypeVar
from homeassistant.core import HassJob, HomeAssistant, callback from homeassistant.core import HassJob, HomeAssistant, callback
_R_co = TypeVar("_R_co", covariant=True)
class Debouncer:
class Debouncer(Generic[_R_co]):
"""Class to rate limit calls to a specific command.""" """Class to rate limit calls to a specific command."""
def __init__( def __init__(
@ -19,7 +21,7 @@ class Debouncer:
*, *,
cooldown: float, cooldown: float,
immediate: bool, immediate: bool,
function: Callable[..., Awaitable[Any]] | None = None, function: Callable[[], _R_co] | None = None,
) -> None: ) -> None:
"""Initialize debounce. """Initialize debounce.
@ -35,15 +37,17 @@ class Debouncer:
self._timer_task: asyncio.TimerHandle | None = None self._timer_task: asyncio.TimerHandle | None = None
self._execute_at_end_of_timer: bool = False self._execute_at_end_of_timer: bool = False
self._execute_lock = asyncio.Lock() self._execute_lock = asyncio.Lock()
self._job: HassJob | None = None if function is None else HassJob(function) self._job: HassJob[[], _R_co] | None = (
None if function is None else HassJob(function)
)
@property @property
def function(self) -> Callable[..., Awaitable[Any]] | None: def function(self) -> Callable[[], _R_co] | None:
"""Return the function being wrapped by the Debouncer.""" """Return the function being wrapped by the Debouncer."""
return self._function return self._function
@function.setter @function.setter
def function(self, function: Callable[..., Awaitable[Any]]) -> None: def function(self, function: Callable[[], _R_co]) -> None:
"""Update the function being wrapped by the Debouncer.""" """Update the function being wrapped by the Debouncer."""
self._function = function self._function = function
if self._job is None or function != self._job.target: if self._job is None or function != self._job.target:

View File

@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
from collections import OrderedDict from collections import OrderedDict
from collections.abc import Coroutine
import logging import logging
import time import time
from typing import TYPE_CHECKING, Any, NamedTuple, cast from typing import TYPE_CHECKING, Any, NamedTuple, cast
@ -832,7 +833,7 @@ def async_setup_cleanup(hass: HomeAssistant, dev_reg: DeviceRegistry) -> None:
ent_reg = entity_registry.async_get(hass) ent_reg = entity_registry.async_get(hass)
async_cleanup(hass, dev_reg, ent_reg) async_cleanup(hass, dev_reg, ent_reg)
debounced_cleanup = Debouncer( debounced_cleanup: Debouncer[Coroutine[Any, Any, None]] = Debouncer(
hass, _LOGGER, cooldown=CLEANUP_DELAY, immediate=False, function=cleanup hass, _LOGGER, cooldown=CLEANUP_DELAY, immediate=False, function=cleanup
) )

View File

@ -2,7 +2,7 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from collections.abc import Awaitable, Callable, Generator from collections.abc import Awaitable, Callable, Coroutine, Generator
from datetime import datetime, timedelta from datetime import datetime, timedelta
import logging import logging
from time import monotonic from time import monotonic
@ -44,7 +44,7 @@ class DataUpdateCoordinator(Generic[_T]):
name: str, name: str,
update_interval: timedelta | None = None, update_interval: timedelta | None = None,
update_method: Callable[[], Awaitable[_T]] | None = None, update_method: Callable[[], Awaitable[_T]] | None = None,
request_refresh_debouncer: Debouncer | None = None, request_refresh_debouncer: Debouncer[Coroutine[Any, Any, None]] | None = None,
) -> None: ) -> None:
"""Initialize global data updater.""" """Initialize global data updater."""
self.hass = hass self.hass = hass

View File

@ -57,6 +57,9 @@ disallow_any_generics = true
[mypy-homeassistant.helpers.condition] [mypy-homeassistant.helpers.condition]
disallow_any_generics = true disallow_any_generics = true
[mypy-homeassistant.helpers.debounce]
disallow_any_generics = true
[mypy-homeassistant.helpers.discovery] [mypy-homeassistant.helpers.discovery]
disallow_any_generics = true disallow_any_generics = true