feat: standardize algorithm measurement results

This commit is contained in:
2026-08-14 00:12:53 +08:00
parent ac1387debc
commit 185dd36bf3
15 changed files with 1273 additions and 19 deletions

View File

@@ -0,0 +1,136 @@
#!/usr/bin/env python3
"""算法测量结果契约 1.0 的零第三方依赖校验器。"""
from __future__ import annotations
import json
import math
import re
import sys
from pathlib import Path
from typing import Any
METRIC_CODE_RE = re.compile(r"^[a-z0-9]+(?:[._-][a-z0-9]+)*$")
TASK_NO_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$")
TASK_NAME_PREFIX_RE = re.compile(r"^任务\s*\d+")
FINAL_STATUSES = {"pass", "warning", "fail"}
def is_number(value: Any) -> bool:
return isinstance(value, (int, float)) and not isinstance(value, bool) and math.isfinite(value)
def validate(payload: Any) -> list[str]:
errors: list[str] = []
if not isinstance(payload, dict):
return ["根节点必须是 JSON 对象"]
if not isinstance(payload.get("schemaVersion"), int) or payload["schemaVersion"] < 1:
errors.append("schemaVersion 必须是大于等于 1 的整数")
if payload.get("measurementContractVersion") != "1.0":
errors.append('measurementContractVersion 必须为 "1.0"')
if payload.get("status") not in {"completed", "error"}:
errors.append("status 必须为 completed 或 error")
measurements = payload.get("measurements")
if payload.get("status") == "completed" and not isinstance(measurements, list):
errors.append("completed 结果必须包含 measurements 数组")
measurements = []
elif measurements is None:
measurements = []
elif not isinstance(measurements, list):
errors.append("measurements 必须是数组")
measurements = []
unique_keys: set[tuple[str, str, str]] = set()
for index, item in enumerate(measurements):
path = f"measurements[{index}]"
if not isinstance(item, dict):
errors.append(f"{path} 必须是对象")
continue
task_no = item.get("taskNo")
metric_code = item.get("metricCode")
name = item.get("name")
position = item.get("position", "")
value = item.get("value", ...)
status = item.get("status")
if not isinstance(task_no, str) or not TASK_NO_RE.fullmatch(task_no):
errors.append(f"{path}.taskNo 必须是非空规范字符串,数字任务号也要加引号")
if not isinstance(metric_code, str) or not METRIC_CODE_RE.fullmatch(metric_code):
errors.append(f"{path}.metricCode 格式无效")
if not isinstance(name, str) or not name.strip():
errors.append(f"{path}.name 必须是非空字符串")
elif TASK_NAME_PREFIX_RE.search(name):
errors.append(f"{path}.name 不得包含任务号前缀,请使用 taskNo 字段")
if position and not isinstance(position, str):
errors.append(f"{path}.position 必须是字符串")
if value is ... or (value is not None and not is_number(value)):
errors.append(f"{path}.value 必须是有限数值或 null")
if status not in FINAL_STATUSES:
errors.append(f"{path}.status 必须为 pass、warning 或 fail,正式结果不得使用 info")
if value is None and status == "pass":
errors.append(f"{path} 的 value 为 null 时不能判定为 pass")
if "baseline" in item and (not is_number(item["baseline"]) or item["baseline"] <= 0):
errors.append(f"{path}.baseline 必须是正数")
if "tolerance" in item and (not is_number(item["tolerance"]) or item["tolerance"] < 0):
errors.append(f"{path}.tolerance 必须是非负有限数值")
if isinstance(task_no, str) and isinstance(metric_code, str) and isinstance(position, str):
key = (task_no, metric_code, position)
if key in unique_keys:
errors.append(f"{path} 与其他正式测量项重复:taskNo + metricCode + position 必须唯一")
unique_keys.add(key)
extra = payload.get("extra", {})
if extra is not None and not isinstance(extra, dict):
errors.append("extra 必须是对象")
extra = {}
intermediate = extra.get("intermediateMetrics", []) if isinstance(extra, dict) else []
if not isinstance(intermediate, list):
errors.append("extra.intermediateMetrics 必须是数组")
intermediate = []
for index, item in enumerate(intermediate):
path = f"extra.intermediateMetrics[{index}]"
if not isinstance(item, dict):
errors.append(f"{path} 必须是对象")
continue
if any(field in item for field in ("taskNo", "status", "tolerance")):
errors.append(f"{path} 不得包含 taskNo、status 或 tolerance")
code = item.get("metricCode")
if not isinstance(code, str) or not METRIC_CODE_RE.fullmatch(code):
errors.append(f"{path}.metricCode 格式无效")
if not isinstance(item.get("name"), str) or not item["name"].strip():
errors.append(f"{path}.name 必须是非空字符串")
value = item.get("value", ...)
if value is ... or (value is not None and not is_number(value)):
errors.append(f"{path}.value 必须是有限数值或 null")
return errors
def main() -> int:
if len(sys.argv) != 2:
print(f"用法: {Path(sys.argv[0]).name} /path/to/result.json", file=sys.stderr)
return 2
path = Path(sys.argv[1])
try:
payload = json.loads(path.read_text(encoding="utf-8"), parse_constant=lambda value: (_ for _ in ()).throw(ValueError(f"非法数值 {value}")))
except (OSError, json.JSONDecodeError, ValueError) as exc:
print(f"校验失败: 无法读取标准 JSON:{exc}", file=sys.stderr)
return 1
errors = validate(payload)
if errors:
print(f"校验失败,共 {len(errors)} 个问题:", file=sys.stderr)
for error in errors:
print(f"- {error}", file=sys.stderr)
return 1
print(f"校验通过:{path}")
return 0
if __name__ == "__main__":
raise SystemExit(main())