Files
iAOP/docs/_check_dcs_template.py
T

80 lines
2.8 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""DCS 点表需求模板(docs/DCS点表需求模板.md)与内核点位字典 schema 一致性检查。
检查项:
1. 文档 §3「点位需求表字段规范」表中的字段名(第一列)与内核
`core/edge-gateway/config/point_dict.example.csv` 表头**完全一致**;
2. 文档中的量纲字典与填表示例单位均在内核示例出现过的类别内(人工抽查,仅告警);
3. 文档引用到的内核文件路径存在。
用法:python _check_dcs_template.py
"""
import csv
import os
import re
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
REPO_ROOT = os.path.dirname(HERE)
DOC_PATH = os.path.join(HERE, "DCS点表需求模板.md")
CSV_PATH = os.path.join(REPO_ROOT, "core", "edge-gateway", "config",
"point_dict.example.csv")
def doc_field_table_columns() -> list:
"""抽取文档 §3 字段规范表的字段名(Markdown 表格第一列)。"""
lines = [ln.strip() for ln in open(DOC_PATH, "r", encoding="utf-8").readlines()]
fields = None
i = 0
while i < len(lines):
line = lines[i]
if line.startswith("|") and line.strip("|").split("|")[0].strip() == "字段":
header_cells = [c.strip() for c in line.strip("|").split("|")]
if "类型" not in header_cells: # §3 特征:字段规范表含"类型"列
i += 1
continue
sep = lines[i + 1] if i + 1 < len(lines) else ""
if all(re.fullmatch(r":?-{3,}:?", c.strip())
for c in sep.strip("|").split("|")):
j = i + 2
rows = []
while j < len(lines) and lines[j].startswith("|"):
cells = [c.strip() for c in lines[j].strip("|").split("|")]
if cells and cells[0]:
rows.append(cells[0])
j += 1
fields = rows
break
i += 1
return fields or []
def main() -> int:
failures = []
# 1) 文档字段规范与内核 CSV 表头一致
with open(CSV_PATH, "r", encoding="utf-8") as fh:
csv_header = [c.strip() for c in next(csv.reader(fh))]
doc_fields = doc_field_table_columns()
if doc_fields != csv_header:
failures.append(
f"文档字段 {doc_fields} 与内核 CSV 表头 {csv_header} 不一致")
# 2) 文档引用文件存在
for ref in ("core/edge-gateway/config/point_dict.example.csv",):
if not os.path.isfile(os.path.join(REPO_ROOT, ref)):
failures.append(f"引用文件缺失:{ref}")
if failures:
print("FAIL")
for f in failures:
print(" -", f)
return 1
print(f"OK: 文档字段规范与内核 schema 一致({len(csv_header)} 列),引用完整")
return 0
if __name__ == "__main__":
sys.exit(main())