Source code for marivo.analysis.frames.quality
"""QualityReport frame family."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal, cast
from pydantic import BaseModel, ConfigDict
from marivo.analysis.frames.base import BaseFrame, BaseFrameMeta
from marivo.render import format_bounded_card, result_repr
class CheckResult(BaseModel):
model_config = ConfigDict(extra="forbid")
check_id: str
status: Literal["ok", "warning", "blocking"]
message: str
class QualityReportSummary(BaseModel):
model_config = ConfigDict(extra="forbid")
kind: str
ref: str
target_metric_id: str | None
target_semantic_kind: Literal["scalar", "time_series", "segmented", "panel"]
overall_status: Literal["ok", "warning", "blocking"]
blocking_issue_count: int
warning_count: int
checks: list[CheckResult]
produced_by_job: str | None
lineage_oneliner: str
def _repr_identity(self) -> str:
return (
f"QualityReportSummary ref={self.ref} status={self.overall_status} "
f"blocking={self.blocking_issue_count}"
)
def render(self) -> str:
return format_bounded_card(
identity=self._repr_identity(),
status=(
f"{self.overall_status}; blocking={self.blocking_issue_count} "
f"warning={self.warning_count}"
),
available=(".render()", ".show()"),
)
def __repr__(self) -> str:
return result_repr(self._repr_identity())
def show(self) -> None:
print(self.render())
class QualityReportMeta(BaseFrameMeta):
model_config = ConfigDict(extra="forbid")
kind: Literal["quality_report"] = "quality_report"
source_refs: list[str]
report_shape: Literal["metric"]
target_kind: Literal["metric_frame"]
target_metric_id: str | None
target_semantic_model: str | None
target_semantic_kind: Literal["scalar", "time_series", "segmented", "panel"]
checks_run: list[str]
overall_status: Literal["ok", "warning", "blocking"]
blocking_issue_count: int
warning_count: int
[docs]
@dataclass(repr=False)
class QualityReport(BaseFrame):
meta: QualityReportMeta
def _repr_identity(self) -> str:
return (
f"QualityReport ref={self.meta.ref} status={self.meta.overall_status} "
f"blocking={self.meta.blocking_issue_count} rows={self.meta.row_count}"
)
def summary(self) -> QualityReportSummary: # type: ignore[override] # replaces meaningless FrameSummary fields with quality-specific ones
step_intents = [step.intent for step in self.meta.lineage.steps]
lineage_oneliner = " -> ".join(step_intents) if step_intents else "(empty)"
checks = [
CheckResult(
check_id=str(row["check_id"]),
status=cast("Literal['ok', 'warning', 'blocking']", str(row["status"])),
message=str(row["message"]),
)
for row in self._df.to_dict("records")
]
return QualityReportSummary(
kind=self.meta.kind,
ref=self.meta.ref,
target_metric_id=self.meta.target_metric_id,
target_semantic_kind=self.meta.target_semantic_kind,
overall_status=self.meta.overall_status,
blocking_issue_count=self.meta.blocking_issue_count,
warning_count=self.meta.warning_count,
checks=checks,
produced_by_job=self.meta.produced_by_job,
lineage_oneliner=lineage_oneliner,
)