85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
|||
|
|
"""采集网只读隔离与网闸配置文档一致性检查 + 代码级只读自检(issue #27)。
|
||
|
|
|
||
|
|
检查项:
|
||
|
|
1. 文档必备章节齐全(只读隔离设计 / 单向网闸配置 / 防火墙规则集 / 验证方法);
|
||
|
|
2. 红线关键词存在(只读 / 不反控 / 零控制指令 / 反向 DROP);
|
||
|
|
3. 引用文件(#19 拓扑策略文档 / edge-gateway 目录)存在;
|
||
|
|
4. **代码级只读自检**:扫描 `core/edge-gateway/drivers/*.py`,确认驱动
|
||
|
|
无任何写/控制方法(write / set_value / control 等),对齐 PRD 9 章。
|
||
|
|
|
||
|
|
用法:python _check_isolation_doc.py
|
||
|
|
"""
|
||
|
|
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, "采集网只读隔离与网闸配置.md")
|
||
|
|
DRIVERS_DIR = os.path.join(REPO_ROOT, "core", "edge-gateway", "drivers")
|
||
|
|
|
||
|
|
REQUIRED_SECTIONS = [
|
||
|
|
"## 2. 只读隔离设计",
|
||
|
|
"## 3. 单向网闸配置",
|
||
|
|
"## 4. 防火墙规则集示例",
|
||
|
|
"## 5. 验证方法",
|
||
|
|
]
|
||
|
|
|
||
|
|
REDLINE_KEYWORDS = ["只读", "不反控", "零控制指令", "DROP", "反向"]
|
||
|
|
|
||
|
|
# 写/控制方法名黑名单(驱动只读约束)
|
||
|
|
WRITE_METHOD_PATTERN = re.compile(
|
||
|
|
r"def (write|write_points|set_value|control|set_point|write_register)"
|
||
|
|
r"|class .*Writer\b", re.IGNORECASE)
|
||
|
|
|
||
|
|
|
||
|
|
def scan_drivers_readonly() -> list:
|
||
|
|
"""扫描 drivers/ 源码,返回命中写/控制方法的行描述。"""
|
||
|
|
hits = []
|
||
|
|
if not os.path.isdir(DRIVERS_DIR):
|
||
|
|
return ["drivers 目录不存在"]
|
||
|
|
for name in sorted(os.listdir(DRIVERS_DIR)):
|
||
|
|
if not name.endswith(".py") or name.startswith("_"):
|
||
|
|
continue
|
||
|
|
path = os.path.join(DRIVERS_DIR, name)
|
||
|
|
for no, line in enumerate(
|
||
|
|
open(path, "r", encoding="utf-8").read().splitlines(), 1):
|
||
|
|
if WRITE_METHOD_PATTERN.search(line):
|
||
|
|
hits.append(f"{name}:{no}: {line.strip()}")
|
||
|
|
return hits
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> int:
|
||
|
|
failures = []
|
||
|
|
text = open(DOC_PATH, "r", encoding="utf-8").read()
|
||
|
|
|
||
|
|
for sec in REQUIRED_SECTIONS:
|
||
|
|
if sec not in text:
|
||
|
|
failures.append(f"缺少必备章节:{sec}")
|
||
|
|
|
||
|
|
for kw in REDLINE_KEYWORDS:
|
||
|
|
if kw not in text:
|
||
|
|
failures.append(f"缺少红线关键词:{kw}")
|
||
|
|
|
||
|
|
for ref in ("网络拓扑与隔离策略.md",):
|
||
|
|
if not os.path.isfile(os.path.join(HERE, ref)):
|
||
|
|
failures.append(f"引用文档缺失:{ref}")
|
||
|
|
|
||
|
|
# 代码级只读自检:drivers/ 零写方法
|
||
|
|
hits = scan_drivers_readonly()
|
||
|
|
if hits:
|
||
|
|
failures.append(f"驱动存在写/控制方法:{hits}")
|
||
|
|
|
||
|
|
if failures:
|
||
|
|
print("FAIL")
|
||
|
|
for f in failures:
|
||
|
|
print(" -", f)
|
||
|
|
return 1
|
||
|
|
print("OK: 章节/红线关键词/引用/驱动只读自检(零写方法)全部通过")
|
||
|
|
return 0
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
sys.exit(main())
|