File: C:/Users/fred/anaconda3/pkgs/watchdog-4.0.1-py312haa95532_0/info/test/tests/utils.py
from __future__ import annotations
import dataclasses
import os
import sys
from queue import Empty, Queue
from typing import List, Optional, Tuple, Type, Union
from watchdog.events import FileSystemEvent
from watchdog.observers.api import EventEmitter, ObservedWatch
from watchdog.utils import Protocol
Emitter: Type[EventEmitter]
if sys.platform.startswith("linux"):
from watchdog.observers.inotify import InotifyEmitter as Emitter
from watchdog.observers.inotify import InotifyFullEmitter
elif sys.platform.startswith("darwin"):
from watchdog.observers.fsevents import FSEventsEmitter as Emitter
elif sys.platform.startswith("win"):
from watchdog.observers.read_directory_changes import WindowsApiEmitter as Emitter
elif sys.platform.startswith(("dragonfly", "freebsd", "netbsd", "openbsd", "bsd")):
from watchdog.observers.kqueue import KqueueEmitter as Emitter
class P(Protocol):
def __call__(self, *args: str) -> str:
...
class StartWatching(Protocol):
def __call__(
self,
path: Optional[Union[str, bytes]] = ...,
use_full_emitter: bool = ...,
recursive: bool = ...,
) -> EventEmitter:
...
class ExpectEvent(Protocol):
def __call__(self, expected_event: FileSystemEvent, timeout: float = ...) -> None:
...
TestEventQueue = Union["Queue[Tuple[FileSystemEvent, ObservedWatch]]"]
@dataclasses.dataclass()
class Helper:
tmp: str
emitters: List[EventEmitter] = dataclasses.field(default_factory=list)
event_queue: TestEventQueue = dataclasses.field(default_factory=Queue)
def joinpath(self, *args: str) -> str:
return os.path.join(self.tmp, *args)
def start_watching(
self,
path: Optional[Union[str, bytes]] = None,
use_full_emitter: bool = False,
recursive: bool = True,
) -> EventEmitter:
# todo: check if other platforms expect the trailing slash (e.g. `p('')`)
path = self.tmp if path is None else path
emitter: EventEmitter
if sys.platform.startswith("linux") and use_full_emitter:
emitter = InotifyFullEmitter(self.event_queue, ObservedWatch(path, recursive=recursive))
else:
emitter = Emitter(self.event_queue, ObservedWatch(path, recursive=recursive))
self.emitters.append(emitter)
if sys.platform.startswith("darwin"):
# TODO: I think this could be better... .suppress_history should maybe
# become a common attribute.
from watchdog.observers.fsevents import FSEventsEmitter
assert isinstance(emitter, FSEventsEmitter)
emitter.suppress_history = True
emitter.start()
return emitter
def expect_event(self, expected_event: FileSystemEvent, timeout: float = 2) -> None:
"""Utility function to wait up to `timeout` seconds for an `event_type` for `path` to show up in the queue.
Provides some robustness for the otherwise flaky nature of asynchronous notifications.
"""
try:
event = self.event_queue.get(timeout=timeout)[0]
assert event == expected_event
except Empty:
raise
def close(self) -> None:
for emitter in self.emitters:
emitter.stop()
for emitter in self.emitters:
if emitter.is_alive():
emitter.join(5)
alive = [emitter.is_alive() for emitter in self.emitters]
self.emitters = []
assert alive == [False] * len(alive)