Hook Lifecycle Demo
Register handlers, dispatch hooks, handle veto/patch
01
Sample Code
from psp.platform.hooks import (
HookDispatcher, HookPoint, HookContext,
Patch, Veto, SideEffectRequest
)
dispatcher = HookDispatcher()
# Hook 1: Auto-tag emails (priority 50 - runs first)
def auto_tag(ctx: HookContext) -> Patch | None:
if "email" in ctx.entity_data.get("title", "").lower():
return Patch(add_items={"tags": ["email"]})
return None
dispatcher.register(HookPoint.BEFORE_CREATE_TASK, auto_tag, priority=50)
# Hook 2: Block empty titles (priority 100)
def block_empty(ctx: HookContext) -> Veto | None:
if not ctx.entity_data.get("title", "").strip():
return Veto(reason="Title cannot be empty")
return None
dispatcher.register(HookPoint.BEFORE_CREATE_TASK, block_empty, priority=100)
# Hook 3: Notify on complete
def notify(ctx: HookContext) -> SideEffectRequest:
return SideEffectRequest(kind="notify", payload={"task": ctx.entity_id})
dispatcher.register(HookPoint.AFTER_COMPLETE_TASK, notify)
# Dispatch before_create with valid data
ctx = HookContext(
hook_point=HookPoint.BEFORE_CREATE_TASK,
entity_type="Task",
entity_id=None,
entity_data={"title": "Check email inbox"},
)
result = dispatcher.dispatch(ctx)
print(f"Vetoed: {result.vetoed}") # False
print(f"Tags to add: {result.merged_patch.add_items}") # {'tags': ['email']}