Hedronite · Dev Lesson · Polyglot-Dev / Python · Thu 2026-09-10

Protocol for alarm handler plugins — structural typing without ABC lock-in

If it has notify(alarm_row), it is a handler. Inheritance is optional.

Lesson Class: Dev (Python Protocol)
Protocol
Structural.
Dispatch
Silent ALARM rows.
Not
TypedDict redo.
Keep the core loop open for new sinks.

If it has notify(alarm_row), it is a handler. Inheritance is optional.

§I — Frame

Pure Python depth for the Python track: typing.Protocol (and @runtime_checkable when needed) to describe alarm handler plugins. Ops produces census dicts; handlers send SNS, open tickets, or no-op in dry-run. Not TypedDict (09-07) and not deepcopy (09-04).

§II — Protocol sketch

from typing import Protocol, runtime_checkable

class AlarmRow(Protocol):
    name: str
    state: str
    actions: int

@runtime_checkable
class AlarmHandler(Protocol):
    def notify(self, row: AlarmRow) -> None: ...

A concrete class needs no explicit base if methods match. Mypy/pyright check structurally.

§III — Why not only ABC

ABCs force import-time coupling to a shared base package. Protocols let a thin ops script accept third-party handlers that never imported your base. Use ABC when you also need registration helpers or isinstance without @runtime_checkable.

§IV — Worked dispatch

def dispatch(rows: list[AlarmRow], handlers: list[AlarmHandler]) -> None:
    for row in rows:
        if row.actions == 0 and row.state == "ALARM":
            for h in handlers:
                h.notify(row)

Handlers stay side-effectful; the Protocol stays tiny.

§V — Pitfalls

§VI — Closing

Structural typing keeps the census script open for new sinks without rewriting the core loop.

Related