"""Source ABC. Adding a new corpus to aborist = one new Source subclass. The Source contract is intentionally minimal: yield Document objects, one at a time. """ from __future__ import annotations from abc import ABC, abstractmethod from typing import Iterator from aborist.document import Document class Source(ABC): """A corpus that yields documents into the ingest pipeline.""" #: source_type tag stored on every Document this source produces. source_type: str @abstractmethod def iter_documents(self) -> Iterator[Document]: """Yield Document objects. Must be deterministic & idempotent.""" ...