"""Detector base class and registration mechanism.""" from __future__ import annotations from typing import Iterable from ..context import CaptureContext from ..findings import Finding class BaseDetector: #: Short unique name referenced by findings and reports. name: str = "BaseDetector" #: Human-readable description of the detector scope. description: str = "" def detect(self, ctx: CaptureContext) -> Iterable[Finding]: # pragma: no cover raise NotImplementedError def _tag(self, findings: Iterable[Finding]) -> list[Finding]: out = [] for f in findings: f.detector = self.name out.append(f) return out # ---- Registry ------------------------------------------------------------- # _REGISTRY: dict[str, type[BaseDetector]] = {} def register(cls: type[BaseDetector]) -> type[BaseDetector]: """Register a detector class.""" _REGISTRY[cls.name] = cls return cls def all_detector_classes() -> list[type[BaseDetector]]: return list(_REGISTRY.values()) def build_all() -> list[BaseDetector]: """Instantiate all registered detector classes.""" return [cls() for cls in _REGISTRY.values()]