Files
docs/standards/src/templates/app/pipelines/example/abc.py

54 lines
1.4 KiB
Python

"""# Summary
Example pipeline family — port contracts (stage interfaces + root interface).
Ports are declared as a DI tree: the root's annotated slots *are* the dependency
decisions. The concrete subclass in ``impl.py`` pins the stage types.
"""
from abc import ABC, abstractmethod
from typing import Any
from pipelines.shared.ports import FinalizePort
class IngestPort(ABC):
"""Obtain the raw input as text/bytes."""
@abstractmethod
def materialize(self, source: Any) -> str:
"""Return the raw input materialized as text."""
class ReadPort(ABC):
"""Parse materialized input into records."""
@abstractmethod
def read(self, content: str) -> list[dict[str, Any]]:
"""Return parsed records."""
class NormalizePort(ABC):
"""Normalize raw records into the target shape."""
@abstractmethod
def build(self, records: list[dict[str, Any]]) -> list[dict[str, Any]]:
"""Return normalized records."""
class ExamplePipelinePort(ABC):
"""Root of the example family.
Notes:
The slot annotations below are contracts. A concrete subclass re-annotates
them with stage implementations; the DI container instantiates the tree.
"""
ingest: IngestPort
reader: ReadPort
normalize: NormalizePort
finalize: FinalizePort
@abstractmethod
async def run(self, source: Any) -> list[dict[str, Any]]:
"""Run the full stage chain and return the normalized records."""