From 47ab7cd90203283002f840f186e9b8f68aeda33f Mon Sep 17 00:00:00 2001 From: HeeJae Chang Date: Tue, 28 Jul 2026 02:41:14 -0700 Subject: [PATCH] Add partial type stubs for core modules Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/hupper/interfaces.pyi | 36 ++++++++++++++++++++++++++++++++++++ src/hupper/logger.pyi | 20 ++++++++++++++++++++ src/hupper/polling.pyi | 27 +++++++++++++++++++++++++++ src/hupper/py.typed | 0 src/hupper/utils.pyi | 26 ++++++++++++++++++++++++++ 5 files changed, 109 insertions(+) create mode 100644 src/hupper/interfaces.pyi create mode 100644 src/hupper/logger.pyi create mode 100644 src/hupper/polling.pyi create mode 100644 src/hupper/py.typed create mode 100644 src/hupper/utils.pyi diff --git a/src/hupper/interfaces.pyi b/src/hupper/interfaces.pyi new file mode 100644 index 0000000..29717f6 --- /dev/null +++ b/src/hupper/interfaces.pyi @@ -0,0 +1,36 @@ +from abc import ABC as ABC, abstractmethod as abstractmethod +from collections.abc import Callable as _Callable, Iterable as _Iterable + +class IReloaderProxy(ABC): + @abstractmethod + def watch_files(self, files: _Iterable[str]) -> None: ... + @abstractmethod + def trigger_reload(self) -> None: ... + @abstractmethod + def graceful_shutdown(self) -> None: ... + +class IFileMonitorFactory(ABC): + @abstractmethod + def __call__( + self, + callback: _Callable[[str], None], + **kw: object, + ) -> IFileMonitor: ... + +class IFileMonitor(ABC): + @abstractmethod + def add_path(self, path: str) -> None: ... + @abstractmethod + def start(self) -> None: ... + @abstractmethod + def stop(self) -> None: ... + @abstractmethod + def join(self) -> None: ... + +class ILogger(ABC): + @abstractmethod + def error(self, msg: str) -> None: ... + @abstractmethod + def info(self, msg: str) -> None: ... + @abstractmethod + def debug(self, msg: str) -> None: ... diff --git a/src/hupper/logger.pyi b/src/hupper/logger.pyi new file mode 100644 index 0000000..5a17fdb --- /dev/null +++ b/src/hupper/logger.pyi @@ -0,0 +1,20 @@ +import sys as sys + +from .interfaces import ILogger as ILogger + +class LogLevel: + ERROR: int + INFO: int + DEBUG: int + +class DefaultLogger(ILogger): + level: int + def __init__(self, level: int) -> None: ... + def error(self, msg: str) -> None: ... + def info(self, msg: str) -> None: ... + def debug(self, msg: str) -> None: ... + +class SilentLogger(ILogger): + def error(self, msg: str) -> None: ... + def info(self, msg: str) -> None: ... + def debug(self, msg: str) -> None: ... diff --git a/src/hupper/polling.pyi b/src/hupper/polling.pyi new file mode 100644 index 0000000..aeb9e52 --- /dev/null +++ b/src/hupper/polling.pyi @@ -0,0 +1,27 @@ +from _thread import LockType as _LockType +from collections.abc import Callable as _Callable, Iterable as _Iterable +import os as os +import threading as threading +import time as time + +from .interfaces import IFileMonitor as IFileMonitor + +class PollingFileMonitor(threading.Thread, IFileMonitor): + callback: _Callable[[str], None] + poll_interval: float + paths: set[str] + mtimes: dict[str, float] + lock: _LockType + enabled: bool + def __init__( + self, + callback: _Callable[[str], None], + interval: float = 1, + **kw: object, + ) -> None: ... + def add_path(self, path: str) -> None: ... + def run(self) -> None: ... + def stop(self) -> None: ... + def check_reload(self, paths: _Iterable[str]) -> None: ... + +def get_mtime(path: str) -> float: ... diff --git a/src/hupper/py.typed b/src/hupper/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/src/hupper/utils.pyi b/src/hupper/utils.pyi new file mode 100644 index 0000000..26a8a48 --- /dev/null +++ b/src/hupper/utils.pyi @@ -0,0 +1,26 @@ +import importlib as importlib +import json as json +import os as os +import subprocess as subprocess +import sys as sys +from typing import Protocol as _Protocol + +class _InteractiveStream(_Protocol): + def isatty(self) -> bool: ... + +WIN: bool + +class Sentinel: + name: object + def __init__(self, name: object) -> None: ... + def __repr__(self) -> str: ... + +default: Sentinel + +def resolve_spec(spec: str) -> object: ... +def is_watchdog_supported() -> bool: ... +def is_watchman_supported() -> bool: ... +def get_watchman_sockpath(binpath: str = "watchman") -> str: ... +def is_stream_interactive( + stream: _InteractiveStream | None, +) -> bool: ...