Coverage for src / lexigram / contracts / core / hooks.py: 0%
21 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
1"""Hook registry protocol and priority enum for framework extensibility."""
3from __future__ import annotations
5from enum import IntEnum
6from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
8if TYPE_CHECKING:
9 from collections.abc import Callable
12class HookPriority(IntEnum):
13 """Named priority levels for hook handlers.
15 Lower values run first. Custom integer values are accepted anywhere
16 a priority is expected — these named levels are conveniences.
18 Spacing between levels leaves room for application-specific
19 intermediate values (e.g. ``HookPriority.EARLY + 10``).
20 """
22 EARLIEST = 0
23 EARLY = 50
24 NORMAL = 100
25 LATE = 200
26 LATEST = 300
29@runtime_checkable
30class HookRegistryProtocol(Protocol):
31 """Structural protocol for hook registries.
33 Defines the contract for action hooks (fire-and-forget, error-isolated)
34 and filter hooks (value-pipeline, error-propagating) with priority ordering.
35 """
37 def register_action(
38 self,
39 hook_name: str,
40 handler: Callable[..., Any],
41 priority: int = 100,
42 *,
43 once: bool = False,
44 ) -> None:
45 """Register an action handler for the given hook.
47 Args:
48 hook_name: The hook point name.
49 handler: Callable to invoke. Can be sync or async.
50 priority: Lower values run first. Defaults to 100.
51 once: If True, auto-remove handler after first invocation.
52 """
53 ...
55 def register_filter(
56 self,
57 hook_name: str,
58 handler: Callable[..., Any],
59 priority: int = 100,
60 *,
61 once: bool = False,
62 ) -> None:
63 """Register a filter handler for the given hook.
65 Args:
66 hook_name: The hook point name.
67 handler: Callable that receives and returns a value.
68 priority: Lower values run first. Defaults to 100.
69 once: If True, auto-remove handler after first invocation.
70 """
71 ...
73 def unregister_action(self, hook_name: str, handler: Callable[..., Any]) -> bool:
74 """Remove an action handler. Returns True if found and removed."""
75 ...
77 def unregister_filter(self, hook_name: str, handler: Callable[..., Any]) -> bool:
78 """Remove a filter handler. Returns True if found and removed."""
79 ...
81 async def call_action(self, hook_name: str, **kwargs: Any) -> None:
82 """Invoke all action handlers. Errors are isolated and logged."""
83 ...
85 async def apply_filter(self, hook_name: str, value: Any, **kwargs: Any) -> Any:
86 """Pass value through all filter handlers. Errors propagate."""
87 ...
89 def has_action(self, hook_name: str) -> bool:
90 """Check if any action handlers are registered."""
91 ...
93 def has_filter(self, hook_name: str) -> bool:
94 """Check if any filter handlers are registered."""
95 ...
97 def clear(self, hook_name: str | None = None) -> None:
98 """Clear handlers for a specific hook, or all hooks."""
99 ...
102__all__ = [
103 "HookPriority",
104 "HookRegistryProtocol",
105]