Source code for loom.etl.maintenance._step

"""MaintenanceStep — base class for declarative Delta table maintenance.

Mirrors the ``ETLStep`` authoring pattern (class-level declarations validated
at definition time) but is entirely separate from the data-transformation
machinery — maintenance steps have no sources, no target, and no execute().
"""

from __future__ import annotations

from typing import Any, ClassVar, Generic, TypeVar

from loom.etl.maintenance._protocol import OperationDeclaration
from loom.etl.pipeline._generics import _extract_generic_arg

ParamsT = TypeVar("ParamsT")


[docs] class MaintenanceStep(Generic[ParamsT]): """Base class for Delta table maintenance steps. Subclass and declare :attr:`operations` as a list of :class:`~loom.etl.maintenance.MaintainTable` and/or :class:`~loom.etl.maintenance.MaintainSchema` instances. Example:: class NightlyMaintenance(MaintenanceStep[None]): operations = [ MaintainSchema("raw").vacuum(retention_hours=168, dry_run=False).compact(), MaintainTable("staging.orders") .vacuum(dry_run=False) .z_order_by(["run_date", "_id"]), ] The step is executed via :class:`~loom.etl.maintenance.MaintenanceRunner`:: runner = MaintenanceRunner.from_config(config) report = runner.run(NightlyMaintenance) report.raise_if_errors() """ operations: ClassVar[list[OperationDeclaration]] = [] _params_type: ClassVar[type[Any] | None] = None def __init_subclass__(cls, **kwargs: Any) -> None: super().__init_subclass__(**kwargs) cls._params_type = _extract_params_type(cls) _validate_operations(cls)
[docs] def operations_for(self, params: ParamsT) -> list[OperationDeclaration]: """Return the list of operations to execute for this run. Override to build the list dynamically from *params* — useful when operations are driven by Prefect deployment parameters instead of being hardcoded at class-definition time. The default implementation returns the class-level :attr:`operations` list (static behaviour, backwards-compatible). """ _ = params return type(self).operations
# --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _extract_params_type(cls: type[Any]) -> type[Any] | None: """Extract the ParamsT generic arg from MaintenanceStep[ParamsT].""" return _extract_generic_arg(cls, MaintenanceStep) def _validate_operations(cls: type[Any]) -> None: """Ensure ``operations`` is a list of OperationDeclaration implementors.""" ops = cls.__dict__.get("operations", cls.operations) if not isinstance(ops, list): raise TypeError( f"{cls.__qualname__}: 'operations' must be a list, got {type(ops).__name__}" ) for idx, op in enumerate(ops): if not isinstance(op, OperationDeclaration): raise TypeError( f"{cls.__qualname__}: operations[{idx}] must implement OperationDeclaration " f"(MaintainTable or MaintainSchema), got {type(op).__name__}" )