Improve folder_watcher typing (#107271)

This commit is contained in:
Marc Mueller 2024-01-08 10:49:15 +01:00 committed by GitHub
parent 3632d6be46
commit e7cc26d028
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,13 +1,25 @@
"""Component for monitoring activity on a folder.""" """Component for monitoring activity on a folder."""
from __future__ import annotations
import logging import logging
import os import os
from typing import cast
import voluptuous as vol import voluptuous as vol
from watchdog.events import PatternMatchingEventHandler from watchdog.events import (
FileClosedEvent,
FileCreatedEvent,
FileDeletedEvent,
FileModifiedEvent,
FileMovedEvent,
FileSystemEvent,
FileSystemMovedEvent,
PatternMatchingEventHandler,
)
from watchdog.observers import Observer from watchdog.observers import Observer
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant from homeassistant.core import Event, HomeAssistant
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
@ -42,8 +54,8 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the folder watcher.""" """Set up the folder watcher."""
conf = config[DOMAIN] conf = config[DOMAIN]
for watcher in conf: for watcher in conf:
path = watcher[CONF_FOLDER] path: str = watcher[CONF_FOLDER]
patterns = watcher[CONF_PATTERNS] patterns: list[str] = watcher[CONF_PATTERNS]
if not hass.config.is_allowed_path(path): if not hass.config.is_allowed_path(path):
_LOGGER.error("Folder %s is not valid or allowed", path) _LOGGER.error("Folder %s is not valid or allowed", path)
return False return False
@ -52,18 +64,21 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
return True return True
def create_event_handler(patterns, hass): def create_event_handler(patterns: list[str], hass: HomeAssistant) -> EventHandler:
"""Return the Watchdog EventHandler object.""" """Return the Watchdog EventHandler object."""
class EventHandler(PatternMatchingEventHandler): return EventHandler(patterns, hass)
class EventHandler(PatternMatchingEventHandler):
"""Class for handling Watcher events.""" """Class for handling Watcher events."""
def __init__(self, patterns, hass): def __init__(self, patterns: list[str], hass: HomeAssistant) -> None:
"""Initialise the EventHandler.""" """Initialise the EventHandler."""
super().__init__(patterns) super().__init__(patterns)
self.hass = hass self.hass = hass
def process(self, event, moved=False): def process(self, event: FileSystemEvent, moved: bool = False) -> None:
"""On Watcher event, fire HA event.""" """On Watcher event, fire HA event."""
_LOGGER.debug("process(%s)", event) _LOGGER.debug("process(%s)", event)
if not event.is_directory: if not event.is_directory:
@ -76,6 +91,7 @@ def create_event_handler(patterns, hass):
} }
if moved: if moved:
event = cast(FileSystemMovedEvent, event)
dest_folder, dest_file_name = os.path.split(event.dest_path) dest_folder, dest_file_name = os.path.split(event.dest_path)
fireable.update( fireable.update(
{ {
@ -89,33 +105,31 @@ def create_event_handler(patterns, hass):
fireable, fireable,
) )
def on_modified(self, event): def on_modified(self, event: FileModifiedEvent) -> None:
"""File modified.""" """File modified."""
self.process(event) self.process(event)
def on_moved(self, event): def on_moved(self, event: FileMovedEvent) -> None:
"""File moved.""" """File moved."""
self.process(event, moved=True) self.process(event, moved=True)
def on_created(self, event): def on_created(self, event: FileCreatedEvent) -> None:
"""File created.""" """File created."""
self.process(event) self.process(event)
def on_deleted(self, event): def on_deleted(self, event: FileDeletedEvent) -> None:
"""File deleted.""" """File deleted."""
self.process(event) self.process(event)
def on_closed(self, event): def on_closed(self, event: FileClosedEvent) -> None:
"""File closed.""" """File closed."""
self.process(event) self.process(event)
return EventHandler(patterns, hass)
class Watcher: class Watcher:
"""Class for starting Watchdog.""" """Class for starting Watchdog."""
def __init__(self, path, patterns, hass): def __init__(self, path: str, patterns: list[str], hass: HomeAssistant) -> None:
"""Initialise the watchdog observer.""" """Initialise the watchdog observer."""
self._observer = Observer() self._observer = Observer()
self._observer.schedule( self._observer.schedule(
@ -124,11 +138,11 @@ class Watcher:
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, self.startup) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, self.startup)
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self.shutdown) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self.shutdown)
def startup(self, event): def startup(self, event: Event) -> None:
"""Start the watcher.""" """Start the watcher."""
self._observer.start() self._observer.start()
def shutdown(self, event): def shutdown(self, event: Event) -> None:
"""Shutdown the watcher.""" """Shutdown the watcher."""
self._observer.stop() self._observer.stop()
self._observer.join() self._observer.join()