chronaxis.results.aggregation_row
源码基线:8904c2f744951857659abd40aaa3535d57faf53c
1"""保存组级值、明确总体和互斥的纳入/排除计数,版本15不改变旧结果行。"""23from dataclasses import dataclass4from math import isfinite5from ..core.types import QualityFlag as Q6from ..core.validation import require_identifier, require_text789@dataclass(frozen=True)10class SummaryAggregationRow:11 """一个实际分组的结果;配对小计是观测请求分类,参与率不是时间覆盖率。"""1213 sequence: int14 dataset_id: str15 entity_id: str16 session_id: str17 aggregation_id: str18 source_kind: str19 source_id: str20 operation: str21 group_keys: tuple[str, ...]22 group_values: tuple[str, ...]23 value: int | float | None24 unit: str25 status: str26 reason: str27 candidate_count: int28 included_count: int29 definition_excluded_count: int30 quality_excluded_count: int31 included_partial_count: int32 matched_count: int33 timeout_count: int34 insufficient_observation_count: int35 pending_count: int36 discovery_complete: bool37 quality: Q3839 def __post_init__(self):40 """检查组身份、有限值、数值政策和计数守恒。参数: 无。返回: None。异常: 无效协议直接拒绝。"""41 for name in ('dataset_id','entity_id','session_id','aggregation_id','source_id'):42 require_identifier(getattr(self,name),name)43 if self.source_kind not in ('calculation','sequence','rule','window'):44 raise ValueError('聚合来源类型错误')45 if self.operation not in ('count','sum','mean','variance','quantile','median'):46 raise ValueError('聚合操作错误')47 if type(self.group_keys) is not tuple or type(self.group_values) is not tuple or len(self.group_keys)!=len(self.group_values):48 raise ValueError('聚合分组键值需要等长tuple')49 if len(set(self.group_keys))!=len(self.group_keys):50 raise ValueError('聚合分组键不能重复')51 for key,value in zip(self.group_keys,self.group_values):52 require_identifier(key,'group_key')53 require_text(value,'group_value')54 counts=(self.sequence,self.candidate_count,self.included_count,self.definition_excluded_count,55 self.quality_excluded_count,self.included_partial_count,self.matched_count,self.timeout_count,56 self.insufficient_observation_count,self.pending_count)57 if any(type(x) is not int or not 0<=x<1<<64 for x in counts):58 raise ValueError('聚合计数需要 uint64 范围原生整数')59 if self.candidate_count != self.included_count+self.definition_excluded_count+self.quality_excluded_count or self.included_partial_count>self.included_count:60 raise ValueError('聚合纳入/排除数量与总体不符')61 if sum(counts[-4:]) != (self.candidate_count if self.source_kind=='sequence' else 0):62 raise ValueError('请求分类数量与总体不符')63 if type(self.discovery_complete) is not bool or not isinstance(self.quality,Q):64 raise TypeError('聚合总体完整性或质量错误')65 if self.status not in ('complete','partial','indeterminate','empty'):66 raise ValueError('聚合状态错误')67 require_text(self.unit,'unit')68 require_text(self.reason,'reason')69 if self.value is not None and (type(self.value) not in (int,float) or type(self.value) is float and not isfinite(self.value)):70 raise ValueError('聚合数值需要有限数或null')71 if self.status in ('empty','indeterminate') and self.value is not None or self.status=='complete' and self.value is None:72 raise ValueError('聚合状态与数值矛盾')73 if self.operation=='count' and (self.unit!='1' or self.value is not None and74 (type(self.value) is not int or self.value!=self.included_count)):75 raise ValueError('对象计数须为实际纳入数,单位1')767778AGGREGATION_FIELDS = tuple(SummaryAggregationRow.__dataclass_fields__)79