Source code for gatenet.core.hooks
from __future__ import annotations
from typing import Callable, Dict, List, Any, Optional
[docs]
class Hooks:
"""A tiny, dependency-free hook system.
- Register callbacks under a string key (event name).
- Emit events with arbitrary kwargs; results are collected and returned.
- Supports simple middleware patterns across modules (HTTP, clients, diagnostics).
Example:
hooks = Hooks()
hooks.on("http:before_request", lambda req: req)
hooks.emit("http:before_request", req=request)
"""
def __init__(self) -> None:
self._events: Dict[str, List[Callable[..., Any]]] = {}
[docs]
def on(self, event: str, fn: Callable[..., Any]) -> None:
"""Register a callback for an event.
Args:
event: The event name.
fn: The callback function.
"""
self._events.setdefault(event, []).append(fn)
[docs]
def off(self, event: str, fn: Callable[..., Any]) -> None:
"""Remove a callback for an event if present."""
if event in self._events:
self._events[event] = [f for f in self._events[event] if f is not fn]
if not self._events[event]:
del self._events[event]
[docs]
def clear(self, event: Optional[str] = None) -> None:
"""Clear all callbacks for an event, or all events if None."""
if event is None:
self._events.clear()
else:
self._events.pop(event, None)
[docs]
def emit(self, event: str, **kwargs: Any) -> List[Any]:
"""Emit an event and collect results from listeners.
Args:
event: The event name.
**kwargs: Arbitrary keyword args to pass to listeners.
Returns:
A list of results returned by listeners (order preserved).
"""
listeners = self._events.get(event, [])
results: List[Any] = []
for fn in listeners:
try:
results.append(fn(**kwargs))
except Exception as _:
# Best-effort hooks: ignore listener errors to avoid breaking core flows
results.append(None)
return results