Coverage for src / tracekit / reporting / content / filtering.py: 100%
60 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-11 23:04 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-11 23:04 +0000
1"""Smart content filtering for reports.
3Shows only relevant information based on context, severity, and audience
4with conditional sections and violation-only modes.
7References:
8"""
10from __future__ import annotations
12from dataclasses import dataclass
13from enum import Enum
14from typing import Any, Literal
16from tracekit.reporting.formatting.standards import Severity
19class AudienceType(Enum):
20 """Audience types for content filtering."""
22 EXECUTIVE = "executive"
23 ENGINEERING = "engineering"
24 DEBUG = "debug"
25 REGULATORY = "regulatory"
26 PRODUCTION = "production"
29@dataclass
30class ContentFilter:
31 """Smart content filtering configuration.
33 Attributes:
34 severity_threshold: Minimum severity to show (critical/warning/info).
35 audience: Target audience type.
36 show_only: Show only specific content (violations, changes, all).
37 hide_empty_sections: Hide sections with no data.
38 relevance_threshold: Minimum relevance score (0.0-1.0).
40 References:
41 REPORT-005: Smart Content Filtering
42 """
44 severity_threshold: Severity = Severity.INFO
45 audience: AudienceType = AudienceType.ENGINEERING
46 show_only: Literal["all", "violations", "changes"] = "all"
47 hide_empty_sections: bool = True
48 relevance_threshold: float = 0.5
51def filter_by_severity(
52 items: list[dict[str, Any]],
53 min_severity: Severity | str,
54) -> list[dict[str, Any]]:
55 """Filter items by severity level.
57 Args:
58 items: List of items with 'severity' field.
59 min_severity: Minimum severity to include.
61 Returns:
62 Filtered list of items.
64 Example:
65 >>> items = [{"name": "test1", "severity": "critical"},
66 ... {"name": "test2", "severity": "info"}]
67 >>> filtered = filter_by_severity(items, "warning")
68 >>> len(filtered) # Only critical items
69 1
71 References:
72 REPORT-005: Smart Content Filtering
73 """
74 if isinstance(min_severity, str):
75 min_severity = Severity(min_severity.lower())
77 severity_order = {
78 Severity.INFO: 0,
79 Severity.WARNING: 1,
80 Severity.ERROR: 2,
81 Severity.CRITICAL: 3,
82 }
84 min_level = severity_order.get(min_severity, 0)
86 filtered = []
87 for item in items:
88 item_severity_str = item.get("severity", "info").lower()
89 try:
90 item_severity = Severity(item_severity_str)
91 item_level = severity_order.get(item_severity, 0)
92 if item_level >= min_level:
93 filtered.append(item)
94 except (ValueError, KeyError):
95 continue
97 return filtered
100def filter_by_audience(
101 content: dict[str, Any],
102 audience: AudienceType | str,
103) -> dict[str, Any]:
104 """Filter content for specific audience.
106 Args:
107 content: Content dictionary with various sections.
108 audience: Target audience type.
110 Returns:
111 Filtered content dictionary.
113 Example:
114 >>> content = {"methodology": "...", "results": "...", "raw_data": "..."}
115 >>> filtered = filter_by_audience(content, "executive")
116 >>> "raw_data" in filtered # False - executives don't need raw data
117 False
119 References:
120 REPORT-005: Smart Content Filtering
121 """
122 if isinstance(audience, str):
123 audience = AudienceType(audience.lower())
125 # Define what each audience sees
126 audience_sections = {
127 AudienceType.EXECUTIVE: ["executive_summary", "key_findings", "recommendations"],
128 AudienceType.ENGINEERING: ["summary", "results", "methodology", "plots"],
129 AudienceType.DEBUG: ["summary", "results", "methodology", "plots", "raw_data", "logs"],
130 AudienceType.REGULATORY: ["summary", "compliance", "test_procedures", "standards"],
131 AudienceType.PRODUCTION: ["summary", "pass_fail", "margin", "yield"],
132 }
134 allowed_sections = audience_sections.get(audience, list(content.keys()))
136 filtered = {}
137 for key, value in content.items():
138 if key in allowed_sections:
139 filtered[key] = value
141 return filtered
144def calculate_relevance_score(
145 item: dict[str, Any],
146 context: dict[str, Any] | None = None,
147) -> float:
148 """Calculate relevance score for content item.
150 Args:
151 item: Content item.
152 context: Optional context for relevance scoring.
154 Returns:
155 Relevance score 0.0-1.0.
157 References:
158 REPORT-005: Smart Content Filtering
159 """
160 score = 0.5 # Base score
162 # Increase score for violations
163 if item.get("status") == "fail":
164 score += 0.3
166 # Increase score for critical severity
167 severity = item.get("severity", "").lower()
168 if severity == "critical":
169 score += 0.3
170 elif severity == "warning":
171 score += 0.1
173 # Increase score for outliers
174 if item.get("is_outlier"):
175 score += 0.2
177 # Increase score for low margins
178 margin = item.get("margin_pct")
179 if margin is not None and margin < 20:
180 score += 0.2
182 return min(1.0, score)
185__all__ = [
186 "AudienceType",
187 "ContentFilter",
188 "calculate_relevance_score",
189 "filter_by_audience",
190 "filter_by_severity",
191]